diff --git a/editor/constants.go b/editor/constants.go new file mode 100644 index 0000000..2b40751 --- /dev/null +++ b/editor/constants.go @@ -0,0 +1,7 @@ +package editor + +// ---------------------------------------------------------------------------- +// !Constants +// ---------------------------------------------------------------------------- + +const KiloVersion = "0.0.1" \ No newline at end of file diff --git a/editor/editor.go b/editor/editor.go index 4d229c7..759246c 100644 --- a/editor/editor.go +++ b/editor/editor.go @@ -2,12 +2,11 @@ package editor import ( "fmt" + "strings" "timshome.page/gilo/fn" "timshome.page/gilo/terminal" ) -const KiloVersion = "0.0.1" - // ---------------------------------------------------------------------------- // !Editor // ---------------------------------------------------------------------------- @@ -43,26 +42,6 @@ func (e *editor) RefreshScreen() { terminal.Write(ab.toString()) } -func (e *editor) ProcessKeypress() bool { - ch, _ := terminal.ReadKey() - - // Clean up on exit - if ch == fn.Ctrl('q') { - terminal.Write(terminal.ClearScreen + terminal.ResetCursor) - - return false - } - - switch ch { - case 'w', 'a', 's', 'd': - e.moveCursor(ch) - default: - // Do nothing! - } - - return true -} - func (e *editor) drawRows(ab *buffer) { for y :=0; y < e.screen.Rows; y += 1 { if y == e.screen.Rows / 3 { @@ -95,15 +74,44 @@ func (e *editor) drawRows(ab *buffer) { } } -func (e *editor) moveCursor (key rune) { +func (e *editor) ProcessKeypress() bool { + str, _ := terminal.Read() + + // Escape sequences can be less fun... + if strings.Contains(str, terminal.EscPrefix) { + code := strings.TrimPrefix(str, terminal.EscPrefix) + + switch code { + case KeyArrowUp, KeyArrowDown, KeyArrowLeft, KeyArrowRight: + e.moveCursor(code) + default: + // Do something later + } + } + + for _, ch := range str { + // Clean up on exit + if ch == fn.Ctrl('q') { + terminal.Write(terminal.ClearScreen + terminal.ResetCursor) + + return false + } + } + + return true +} + +func (e *editor) moveCursor (rawKey string) { + key := keyMap[rawKey] + switch key { - case 'a': + case keyLeft: e.cursor.x -= 1 - case 'd': + case keyRight: e.cursor.x += 1 - case 'w': + case keyUp: e.cursor.y -= 1 - case 's': + case keyDown: e.cursor.y += 1 } } \ No newline at end of file diff --git a/editor/keymap.go b/editor/keymap.go new file mode 100644 index 0000000..72b8d7c --- /dev/null +++ b/editor/keymap.go @@ -0,0 +1,30 @@ +package editor + +// ---------------------------------------------------------------------------- +// !Terminal Input Escape Code Sequences +// ---------------------------------------------------------------------------- + +const( + KeyArrowUp = "A" + KeyArrowDown = "B" + KeyArrowRight = "C" + KeyArrowLeft = "D" +) + +// ---------------------------------------------------------------------------- +// !Map escape sequences to simpler constants +// ---------------------------------------------------------------------------- + +const ( + keyUp = "ARROW_UP" + keyDown = "ARROW_DOWN" + keyLeft = "ARROW_LEFT" + keyRight = "ARROW_RIGHT" +) + +var keyMap = map[string]string{ + KeyArrowUp: keyUp, + KeyArrowDown: keyDown, + KeyArrowLeft: keyLeft, + KeyArrowRight: keyRight, +} \ No newline at end of file diff --git a/terminal/ansi.go b/terminal/ansi.go index e5cb6f0..3760c78 100644 --- a/terminal/ansi.go +++ b/terminal/ansi.go @@ -3,24 +3,44 @@ package terminal import "fmt" -const ClearLine = "\x1b[K" -const ClearScreen = "\x1b[2J" +// ---------------------------------------------------------------------------- +// !Terminal Escape Code Sequences +// ---------------------------------------------------------------------------- -const HideCursor = "\x1b[?25l" -const ShowCursor = "\x1b[?25h" -const ResetCursor = "\x1b[H" +const EscPrefix = "\x1b[" -const KeyArrowUp = "\x1b[A" -const KeyArrowDown = "\x1b[B" -const KeyArrowRight = "\x1b[C" -const KeyArrowLeft = "\x1b[D" +const ( + // Clears the line after the escape sequence + ClearLine = "\x1b[K" + + // Clears the entire screen + ClearScreen = "\x1b[2J" +) + +// Cursor Codes +const ( + HideCursor = "\x1b[?25l" + ShowCursor = "\x1b[?25h" + + // Reports cursor location to stdout + LocateCursor = "\x1b[6n" + + // Moves cursor to default position (1,1) + ResetCursor = "\x1b[H" +) + +// ---------------------------------------------------------------------------- +// !Helpers +// ---------------------------------------------------------------------------- + +// Add the ANSI escape code prefix to the relevant escape code func Code (s string) string { - return fmt.Sprintf("\x1b[%s", s) + return fmt.Sprintf("%s%s", EscPrefix, s) } -// Move the terminal cursor to the 0-based coordinate +// Generate the escape sequence to move the terminal cursor to the 0-based coordinate func MoveCursor(x int, y int) string { // Allow 0-based indexing, the terminal code is 1-based x += 1 diff --git a/terminal/size.go b/terminal/size.go index 982421a..89c43b3 100644 --- a/terminal/size.go +++ b/terminal/size.go @@ -33,10 +33,10 @@ func Size () *Screen { func sizeTrick () (rows int, cols int) { // Move cursor to location further than likely screen size // The cursor will move to maximum available position - fmt.Print("\x1b[999C\x1b[99B") + fmt.Print(Code("999C") + Code("999B")) // Ask the terminal where the cursor is - fmt.Print("\x1b[6n") + fmt.Print(LocateCursor) // Read stdin looking for the reported location buffer := ""