From 7f161e668319deb75f6a3959dea790d8fad2ce9e Mon Sep 17 00:00:00 2001 From: Renzix <31043283+Renzix@users.noreply.github.com> Date: Thu, 14 Apr 2022 07:42:46 -0400 Subject: [PATCH] feat: added forward/backward word keybinds (#139) Added emacsForwardWord and emacsBackwardWord which is used by M-f and M-b directly. Also added M-d to ctrl delete and removed the bad old funcion in favor of the fancy new one. Lastly I added alt delete which deletes with emacsBackwardWord. Works identically to gnu readline Co-authored-by: Renzix --- readline/codes.go | 4 ++++ readline/line.go | 31 +++++++++++++++++++++++-------- readline/readline.go | 42 +++++++++++++++++++++++++++++++++++++----- 3 files changed, 64 insertions(+), 13 deletions(-) diff --git a/readline/codes.go b/readline/codes.go index e97af90..29d7462 100644 --- a/readline/codes.go +++ b/readline/codes.go @@ -50,8 +50,12 @@ var ( seqDelete2 = string([]byte{27, 91, 80}) seqCtrlDelete = string([]byte{27, 91, 51, 59, 53, 126}) seqCtrlDelete2 = string([]byte{27, 91, 77}) + seqAltDelete = string([]byte{27, 91, 51, 59, 51, 126}) seqShiftTab = string([]byte{27, 91, 90}) seqAltQuote = string([]byte{27, 34}) // Added for showing registers ^[" + seqAltB = string([]byte{27, 98}) + seqAltD = string([]byte{27, 100}) + seqAltF = string([]byte{27, 102}) seqAltR = string([]byte{27, 114}) // Used for alternative history seqAltBackspace = string([]byte{27, 127}) ) diff --git a/readline/line.go b/readline/line.go index 274d11b..be5ef2c 100644 --- a/readline/line.go +++ b/readline/line.go @@ -183,26 +183,41 @@ func (rl *Instance) deleteToEnd() { rl.line = rl.line[:rl.pos] } +// @TODO(Renzix): move to emacs sepecific file func (rl *Instance) emacsForwardWord(tokeniser tokeniser) (adjust int) { - // when emacs has more specific stuff, move this in a file with then split, index, pos := tokeniser(rl.line, rl.pos) if len(split) == 0 { return } - word := rTrimWhiteSpace(split[index]) + word := strings.TrimSpace(split[index]) switch { case len(split) == 0: return - case index == len(split)-1 && pos >= len(word)-1: - return - case pos >= len(word)-1: - word = rTrimWhiteSpace(split[index+1]) - adjust = len(split[index]) - pos - adjust += len(word) + case pos == len(word) && index != len(split)-1: + extrawhitespace := len(strings.TrimLeft(split[index], " ")) - len(word) + word = split[index+1] + adjust = len(word) + extrawhitespace default: adjust = len(word) - pos } return } + +func (rl *Instance) emacsBackwardWord(tokeniser tokeniser) (adjust int) { + split, index, pos := tokeniser(rl.line, rl.pos) + if len(split) == 0 { + return + } + + switch { + case len(split) == 0: + return + case pos == 0 && index != 0: + adjust = len(split[index-1]) + default: + adjust = pos + } + return +} diff --git a/readline/readline.go b/readline/readline.go index 255fcd6..925bc8f 100644 --- a/readline/readline.go +++ b/readline/readline.go @@ -761,6 +761,34 @@ func (rl *Instance) escapeSeq(r []rune) { rl.pos = len(rl.line) rl.viUndoSkipAppend = true + case seqAltB: + if rl.modeTabCompletion { + return + } + + // This is only available in Insert mode + if rl.modeViMode != VimInsert { + return + } + + move := rl.emacsBackwardWord(tokeniseLine) + rl.moveCursorByAdjust(-move) + rl.updateHelpers() + + case seqAltF: + if rl.modeTabCompletion { + return + } + + // This is only available in Insert mode + if rl.modeViMode != VimInsert { + return + } + + move := rl.emacsForwardWord(tokeniseLine) + rl.moveCursorByAdjust(move) + rl.updateHelpers() + case seqAltR: rl.resetVirtualComp(false) // For some modes only, if we are in vim Keys mode, @@ -792,19 +820,23 @@ func (rl *Instance) escapeSeq(r []rune) { rl.viDeleteByAdjust(rl.viJumpB(tokeniseLine)) rl.updateHelpers() - case seqCtrlDelete, seqCtrlDelete2: + case seqCtrlDelete, seqCtrlDelete2, seqAltD: if rl.modeTabCompletion { rl.resetVirtualComp(false) } - // This is only available in Insert mode - if rl.modeViMode != VimInsert { - return - } rl.saveToRegister(rl.emacsForwardWord(tokeniseLine)) // vi delete, emacs forward, funny huh rl.viDeleteByAdjust(rl.emacsForwardWord(tokeniseLine)) rl.updateHelpers() + case seqAltDelete: + if rl.modeTabCompletion { + rl.resetVirtualComp(false) + } + rl.saveToRegister(-rl.emacsBackwardWord(tokeniseLine)) + rl.viDeleteByAdjust(-rl.emacsBackwardWord(tokeniseLine)) + rl.updateHelpers() + default: if rl.modeTabFind { return