package editor import ( "bufio" "log" "os" "timshome.page/gilo/terminal" ) // ---------------------------------------------------------------------------- // !Editor // ---------------------------------------------------------------------------- type point struct { x int y int } type editor struct { screen *terminal.Screen cursor *point offset *point rows []*row } func New() *editor { screen := terminal.Size() cursor := &point { 0, 0 } offset := &point { 0, 0 } var rows []*row return &editor{ screen, cursor, offset, rows, } } func (e *editor) Open(filename string) { file, err := os.Open(filename) if err != nil { log.Fatalf("failed to open file") } defer file.Close() scanner := bufio.NewScanner(file) scanner.Split(bufio.ScanLines) for scanner.Scan() { e.appendRow(scanner.Text()) } } func (e *editor) ProcessKeypress() bool { var str string ch, _ := terminal.ReadKey() if isCtrl(ch) { switch ch { case ctrl('q'): // Clean up on exit terminal.Write(terminal.ClearScreen + terminal.ResetCursor) return false } } if ch == '\x1b' { str = parseEscapeSequence() } else { str = string(ch) } switch str { case keyUp, keyDown, keyLeft, keyRight, keyPageUp, keyPageDown, keyHome, keyEnd: e.moveCursor(str) return true default: // Do something later terminal.Write("Code: %v", str) } return true } func (e *editor) moveCursor (key string) { switch key { case keyLeft: if e.cursor.x != 0 { e.cursor.x -= 1 } case keyRight: if e.cursor.x != e.screen.Cols-1 { e.cursor.x += 1 } case keyUp: if e.cursor.y != 0 { e.cursor.y -= 1 } case keyDown: if e.cursor.y < len(e.rows) { e.cursor.y += 1 } case keyPageUp: e.cursor.y = 0 case keyPageDown: e.cursor.y = e.screen.Rows case keyHome: e.cursor.x = 0 case keyEnd: e.cursor.x = e.screen.Cols } } func (e *editor) appendRow(s string) { newRow := NewRow(s) e.rows = append(e.rows, newRow) } // Convert the raw ANSI escape sequences to the type of key input func parseEscapeSequence () string { var runes []rune for i := 0; i < 3; i++ { ch, size := terminal.ReadKey() if size == 0 { return "\x1b" } runes = append(runes, ch) if i == 1 && runes[1] >= 'A' { // \eOH \eOF if runes[0] == 'O' { switch runes[1] { case 'H': return keyHome case 'F': return keyEnd } } // \e[A if runes[0] == '[' { switch runes[1] { case 'A': return keyUp case 'B': return keyDown case 'C': return keyRight case 'D': return keyLeft case 'H': return keyHome case 'F': return keyEnd } } } // \e[1~ if i == 2 && runes[0] == '[' && runes[2] == '~' { switch runes[1] { case '1': return keyHome case '3': return keyDelete case '4': return keyEnd case '5': return keyPageUp case '6': return keyPageDown case '7': return keyHome case '8': return keyEnd } } } return string('\x1b') }