From b5d7d9eae33759a6646cb41768966b593eef18f3 Mon Sep 17 00:00:00 2001 From: c-bata Date: Tue, 15 Aug 2017 01:50:33 +0900 Subject: [PATCH] Refactor emacs keybind --- emacs.go | 43 ++++++++++++------------------------------- emacs_test.go | 32 ++++++++++++++++++++++++++++++++ key_bind.go | 25 +++++++++---------------- 3 files changed, 53 insertions(+), 47 deletions(-) create mode 100644 emacs_test.go diff --git a/emacs.go b/emacs.go index 0ddaf67..a18b6b0 100644 --- a/emacs.go +++ b/emacs.go @@ -13,8 +13,6 @@ Moving the cursor * [x] Ctrl + e Go to the End of the line (End) * [x] Ctrl + p Previous command (Up arrow) * [x] Ctrl + n Next command (Down arrow) -* [ ] Alt + b Back (left) one word -* [ ] Alt + f Forward (right) one word * [x] Ctrl + f Forward one character * [x] Ctrl + b Backward one character * [x] Ctrl + xx Toggle between the start of line and current cursor position @@ -23,8 +21,6 @@ Editing ------- * [ ] Ctrl + L Clear the Screen, similar to the clear command -* [ ] Alt + Del Delete the Word before the cursor. -* [ ] Alt + d Delete the Word after the cursor. * [x] Ctrl + d Delete character under the cursor * [x] Ctrl + h Delete character before the cursor (Backspace) @@ -32,97 +28,82 @@ Editing * [x] Ctrl + k Cut the Line after the cursor to the clipboard. * [x] Ctrl + u Cut/delete the Line before the cursor to the clipboard. -* [ ] Alt + t Swap current word with previous * [ ] Ctrl + t Swap the last two characters before the cursor (typo). * [ ] Esc + t Swap the last two words before the cursor. * [ ] ctrl + y Paste the last thing to be cut (yank) -* [ ] Alt + u UPPER capitalize every character from the cursor to the end of the current word. -* [ ] Alt + l Lower the case of every character from the cursor to the end of the current word. -* [ ] Alt + c Capitalize the character under the cursor and move to the end of the word. -* [ ] Alt + r Cancel the changes and put back the line as it was in the history (revert). * [ ] ctrl + _ Undo */ -var emacsKeyBindings = []KeyBind { +var emacsKeyBindings = []KeyBind{ // Go to the End of the line { Key: ControlE, - Fn: func(buf *Buffer) *Buffer { + Fn: func(buf *Buffer) { x := []rune(buf.Document().TextAfterCursor()) buf.CursorRight(len(x)) - return buf }, }, // Go to the beginning of the line { Key: ControlA, - Fn: func(buf *Buffer) *Buffer { + Fn: func(buf *Buffer) { x := []rune(buf.Document().TextBeforeCursor()) buf.CursorLeft(len(x)) - return buf }, }, // Cut the Line after the cursor { Key: ControlK, - Fn: func(buf *Buffer) *Buffer { + Fn: func(buf *Buffer) { x := []rune(buf.Document().TextAfterCursor()) buf.Delete(len(x)) - return buf }, }, // Cut/delete the Line before the cursor { Key: ControlU, - Fn: func(buf *Buffer) *Buffer { + Fn: func(buf *Buffer) { x := []rune(buf.Document().TextBeforeCursor()) buf.DeleteBeforeCursor(len(x)) - return buf }, }, // Delete character under the cursor { Key: ControlD, - Fn: func(buf *Buffer) *Buffer { - if buf.Text() == "" { - return buf // This means just exit. + Fn: func(buf *Buffer) { + if buf.Text() != "" { + buf.Delete(1) } - buf.Delete(1) - return buf }, }, // Backspace { Key: ControlH, - Fn: func(buf *Buffer) *Buffer { + Fn: func(buf *Buffer) { buf.DeleteBeforeCursor(1) - return buf }, }, // Right allow: Forward one character { Key: ControlF, - Fn: func(buf *Buffer) *Buffer { + Fn: func(buf *Buffer) { buf.CursorRight(1) - return buf }, }, // Left allow: Backward one character { Key: ControlB, - Fn: func(buf *Buffer) *Buffer { + Fn: func(buf *Buffer) { buf.CursorLeft(1) - return buf }, }, // Cut the Word before the cursor. { Key: ControlW, - Fn: func(buf *Buffer) *Buffer { + Fn: func(buf *Buffer) { buf.DeleteBeforeCursor(len([]rune(buf.Document().GetWordBeforeCursor()))) - return buf }, }, } diff --git a/emacs_test.go b/emacs_test.go new file mode 100644 index 0000000..081cb51 --- /dev/null +++ b/emacs_test.go @@ -0,0 +1,32 @@ +package prompt + +import "testing" + +func TestEmacsKeyBindings(t *testing.T) { + buf := NewBuffer() + buf.InsertText("abcde", false, true) + if buf.CursorPosition != len("abcde") { + t.Errorf("Want %d, but got %d", len("abcde"), buf.CursorPosition) + } + + // Go to the beginning of the line + applyEmacsKeyBind(buf, ControlA) + if buf.CursorPosition != 0 { + t.Errorf("Want %d, but got %d", 0, buf.CursorPosition) + } + + // Go to the end of the line + applyEmacsKeyBind(buf, ControlE) + if buf.CursorPosition != len("abcde") { + t.Errorf("Want %d, but got %d", len("abcde"), buf.CursorPosition) + } +} + +func applyEmacsKeyBind(buf *Buffer, key Key) { + for i := range emacsKeyBindings { + kb := emacsKeyBindings[i] + if kb.Key == key { + kb.Fn(buf) + } + } +} diff --git a/key_bind.go b/key_bind.go index ec2db2f..0cfcab4 100644 --- a/key_bind.go +++ b/key_bind.go @@ -1,6 +1,6 @@ package prompt -type KeyBindFunc func(*Buffer) *Buffer +type KeyBindFunc func(*Buffer) type KeyBind struct { Key Key @@ -11,59 +11,52 @@ type KeyBindMode string const ( CommonKeyBind KeyBindMode = "common" - EmacsKeyBind KeyBindMode = "emacs" + EmacsKeyBind KeyBindMode = "emacs" ) -var commonKeyBindings = []KeyBind { +var commonKeyBindings = []KeyBind{ // Go to the End of the line { Key: End, - Fn: func(buf *Buffer) *Buffer { + Fn: func(buf *Buffer) { x := []rune(buf.Document().TextAfterCursor()) buf.CursorRight(len(x)) - return buf }, }, // Go to the beginning of the line { Key: Home, - Fn: func(buf *Buffer) *Buffer { + Fn: func(buf *Buffer) { x := []rune(buf.Document().TextBeforeCursor()) buf.CursorLeft(len(x)) - return buf }, }, // Delete character under the cursor { Key: Delete, - Fn: func(buf *Buffer) *Buffer { + Fn: func(buf *Buffer) { buf.Delete(1) - return buf }, }, // Backspace { Key: Backspace, - Fn: func(buf *Buffer) *Buffer { + Fn: func(buf *Buffer) { buf.DeleteBeforeCursor(1) - return buf }, }, // Right allow: Forward one character { Key: Right, - Fn: func(buf *Buffer) *Buffer { + Fn: func(buf *Buffer) { buf.CursorRight(1) - return buf }, }, // Left allow: Backward one character { Key: Left, - Fn: func(buf *Buffer) *Buffer { + Fn: func(buf *Buffer) { buf.CursorLeft(1) - return buf }, }, - }