Refactor emacs keybind

This commit is contained in:
c-bata 2017-08-15 01:50:33 +09:00
parent ba4f3458b5
commit b5d7d9eae3
3 changed files with 53 additions and 47 deletions

@ -13,8 +13,6 @@ Moving the cursor
* [x] Ctrl + e Go to the End of the line (End) * [x] Ctrl + e Go to the End of the line (End)
* [x] Ctrl + p Previous command (Up arrow) * [x] Ctrl + p Previous command (Up arrow)
* [x] Ctrl + n Next command (Down 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 + f Forward one character
* [x] Ctrl + b Backward one character * [x] Ctrl + b Backward one character
* [x] Ctrl + xx Toggle between the start of line and current cursor position * [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 * [ ] 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 + d Delete character under the cursor
* [x] Ctrl + h Delete character before the cursor (Backspace) * [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 + k Cut the Line after the cursor to the clipboard.
* [x] Ctrl + u Cut/delete the Line before 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). * [ ] Ctrl + t Swap the last two characters before the cursor (typo).
* [ ] Esc + t Swap the last two words before the cursor. * [ ] Esc + t Swap the last two words before the cursor.
* [ ] ctrl + y Paste the last thing to be cut (yank) * [ ] 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 * [ ] ctrl + _ Undo
*/ */
var emacsKeyBindings = []KeyBind { var emacsKeyBindings = []KeyBind{
// Go to the End of the line // Go to the End of the line
{ {
Key: ControlE, Key: ControlE,
Fn: func(buf *Buffer) *Buffer { Fn: func(buf *Buffer) {
x := []rune(buf.Document().TextAfterCursor()) x := []rune(buf.Document().TextAfterCursor())
buf.CursorRight(len(x)) buf.CursorRight(len(x))
return buf
}, },
}, },
// Go to the beginning of the line // Go to the beginning of the line
{ {
Key: ControlA, Key: ControlA,
Fn: func(buf *Buffer) *Buffer { Fn: func(buf *Buffer) {
x := []rune(buf.Document().TextBeforeCursor()) x := []rune(buf.Document().TextBeforeCursor())
buf.CursorLeft(len(x)) buf.CursorLeft(len(x))
return buf
}, },
}, },
// Cut the Line after the cursor // Cut the Line after the cursor
{ {
Key: ControlK, Key: ControlK,
Fn: func(buf *Buffer) *Buffer { Fn: func(buf *Buffer) {
x := []rune(buf.Document().TextAfterCursor()) x := []rune(buf.Document().TextAfterCursor())
buf.Delete(len(x)) buf.Delete(len(x))
return buf
}, },
}, },
// Cut/delete the Line before the cursor // Cut/delete the Line before the cursor
{ {
Key: ControlU, Key: ControlU,
Fn: func(buf *Buffer) *Buffer { Fn: func(buf *Buffer) {
x := []rune(buf.Document().TextBeforeCursor()) x := []rune(buf.Document().TextBeforeCursor())
buf.DeleteBeforeCursor(len(x)) buf.DeleteBeforeCursor(len(x))
return buf
}, },
}, },
// Delete character under the cursor // Delete character under the cursor
{ {
Key: ControlD, Key: ControlD,
Fn: func(buf *Buffer) *Buffer { Fn: func(buf *Buffer) {
if buf.Text() == "" { if buf.Text() != "" {
return buf // This means just exit. buf.Delete(1)
} }
buf.Delete(1)
return buf
}, },
}, },
// Backspace // Backspace
{ {
Key: ControlH, Key: ControlH,
Fn: func(buf *Buffer) *Buffer { Fn: func(buf *Buffer) {
buf.DeleteBeforeCursor(1) buf.DeleteBeforeCursor(1)
return buf
}, },
}, },
// Right allow: Forward one character // Right allow: Forward one character
{ {
Key: ControlF, Key: ControlF,
Fn: func(buf *Buffer) *Buffer { Fn: func(buf *Buffer) {
buf.CursorRight(1) buf.CursorRight(1)
return buf
}, },
}, },
// Left allow: Backward one character // Left allow: Backward one character
{ {
Key: ControlB, Key: ControlB,
Fn: func(buf *Buffer) *Buffer { Fn: func(buf *Buffer) {
buf.CursorLeft(1) buf.CursorLeft(1)
return buf
}, },
}, },
// Cut the Word before the cursor. // Cut the Word before the cursor.
{ {
Key: ControlW, Key: ControlW,
Fn: func(buf *Buffer) *Buffer { Fn: func(buf *Buffer) {
buf.DeleteBeforeCursor(len([]rune(buf.Document().GetWordBeforeCursor()))) buf.DeleteBeforeCursor(len([]rune(buf.Document().GetWordBeforeCursor())))
return buf
}, },
}, },
} }

32
emacs_test.go Normal file

@ -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)
}
}
}

@ -1,6 +1,6 @@
package prompt package prompt
type KeyBindFunc func(*Buffer) *Buffer type KeyBindFunc func(*Buffer)
type KeyBind struct { type KeyBind struct {
Key Key Key Key
@ -11,59 +11,52 @@ type KeyBindMode string
const ( const (
CommonKeyBind KeyBindMode = "common" CommonKeyBind KeyBindMode = "common"
EmacsKeyBind KeyBindMode = "emacs" EmacsKeyBind KeyBindMode = "emacs"
) )
var commonKeyBindings = []KeyBind { var commonKeyBindings = []KeyBind{
// Go to the End of the line // Go to the End of the line
{ {
Key: End, Key: End,
Fn: func(buf *Buffer) *Buffer { Fn: func(buf *Buffer) {
x := []rune(buf.Document().TextAfterCursor()) x := []rune(buf.Document().TextAfterCursor())
buf.CursorRight(len(x)) buf.CursorRight(len(x))
return buf
}, },
}, },
// Go to the beginning of the line // Go to the beginning of the line
{ {
Key: Home, Key: Home,
Fn: func(buf *Buffer) *Buffer { Fn: func(buf *Buffer) {
x := []rune(buf.Document().TextBeforeCursor()) x := []rune(buf.Document().TextBeforeCursor())
buf.CursorLeft(len(x)) buf.CursorLeft(len(x))
return buf
}, },
}, },
// Delete character under the cursor // Delete character under the cursor
{ {
Key: Delete, Key: Delete,
Fn: func(buf *Buffer) *Buffer { Fn: func(buf *Buffer) {
buf.Delete(1) buf.Delete(1)
return buf
}, },
}, },
// Backspace // Backspace
{ {
Key: Backspace, Key: Backspace,
Fn: func(buf *Buffer) *Buffer { Fn: func(buf *Buffer) {
buf.DeleteBeforeCursor(1) buf.DeleteBeforeCursor(1)
return buf
}, },
}, },
// Right allow: Forward one character // Right allow: Forward one character
{ {
Key: Right, Key: Right,
Fn: func(buf *Buffer) *Buffer { Fn: func(buf *Buffer) {
buf.CursorRight(1) buf.CursorRight(1)
return buf
}, },
}, },
// Left allow: Backward one character // Left allow: Backward one character
{ {
Key: Left, Key: Left,
Fn: func(buf *Buffer) *Buffer { Fn: func(buf *Buffer) {
buf.CursorLeft(1) buf.CursorLeft(1)
return buf
}, },
}, },
} }