package editor import ( "os" "strings" "unicode/utf8" "tea.kareha.org/lab/termi" ) type mode int const ( modeCommand mode = iota modeInsert ) type Editor struct { col, row int x, y int vrow int lines []string head, tail string insert *strings.Builder mode mode path string bell bool } func (ed *Editor) load() { if ed.path == "" { return } _, err := os.Stat(ed.path) if err != nil { // file not exists return } data, err := os.ReadFile(ed.path) if err != nil { panic(err) } if len(data) < 1 { ed.lines = make([]string, 1) } // TODO CRLF if data[len(data)-1] == '\n' { data = data[:len(data)-1] } ed.lines = strings.Split(string(data), "\n") } func Init(args []string) *Editor { var path string if len(args) > 1 { path = args[1] } ed := &Editor{ col: 0, row: 0, x: 0, y: 0, vrow: 0, lines: make([]string, 1), head: "", tail: "", insert: new(strings.Builder), mode: modeCommand, path: path, bell: false, } ed.load() termi.Raw() return ed } func (ed *Editor) save() { if ed.path == "" { return } text := strings.Join(ed.lines, "\n") + "\n" err := os.WriteFile(ed.path, []byte(text), 0644) if err != nil { panic(err) } } func (ed *Editor) Finish() { termi.Clear() termi.HomeCursor() termi.Cooked() termi.ShowCursor() ed.save() } func (ed *Editor) runeCount() int { return utf8.RuneCountInString(ed.lines[ed.row]) } func (ed *Editor) insertRune(r rune) { ed.insert.WriteRune(r) ed.col++ } func (ed *Editor) ring() { ed.bell = true }