summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGhislain Rodrigues <git@ghislain-rodrigues.fr>2021-03-31 11:08:27 +0200
committerMateusz Czapliński <czapkofan@gmail.com>2021-04-27 09:22:47 +0200
commit840f23c21d3e692661d6ee574490880d7524f761 (patch)
treea1f56eefbb9d9af07ea9ffdc3616bbf15fb0489d
parent88516fde4023aafa335f8da0a12a95bab0f8033a (diff)
keys: Implement unix-word-rubout (Ctrl-W)HEADmaster
unix-word-rubout erases all the characters before the cursor until finding either a space or a BOL.
-rw-r--r--AUTHORS1
-rw-r--r--up.go22
-rw-r--r--up_test.go92
3 files changed, 114 insertions, 1 deletions
diff --git a/AUTHORS b/AUTHORS
index 1a7b9a6..4209ea9 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -2,5 +2,6 @@ Please keep the contents of this file sorted alphabetically.
Александр Крамарев <pochemuto@gmail.com>
Calum MacRae <calum0macrae@gmail.com>
+Ghislain Rodrigues <git@ghislain-rodrigues.fr>
Mateusz Czapliński <czapkofan@gmail.com>
Rohan Verma <hello@rohanverma.net>
diff --git a/up.go b/up.go
index 53ebc09..e83cceb 100644
--- a/up.go
+++ b/up.go
@@ -30,6 +30,7 @@ import (
"os"
"os/exec"
"sync"
+ "unicode"
"github.com/gdamore/tcell"
"github.com/gdamore/tcell/terminfo"
@@ -97,7 +98,7 @@ If a plus '+' is visible in top-left corner, the internal buffer limit
KEYS
-- alphanumeric & symbol keys, Left, Right, Ctrl-A/E/B/F/K/Y
+- alphanumeric & symbol keys, Left, Right, Ctrl-A/E/B/F/K/Y/W
- navigate and edit the pipeline command
- Enter - execute the pipeline command, updating the pipeline output panel
- Up, Dn, PgUp, PgDn, Ctrl-Left, Ctrl-Right
@@ -419,6 +420,9 @@ func (e *Editor) HandleKey(ev *tcell.EventKey) bool {
case key(tcell.KeyCtrlY),
ctrlKey(tcell.KeyCtrlY):
e.insert(e.killspace...)
+ case key(tcell.KeyCtrlW),
+ ctrlKey(tcell.KeyCtrlW):
+ e.unixWordRubout()
default:
// Unknown key/combination, not handled
return false
@@ -450,6 +454,22 @@ func (e *Editor) kill() {
e.value = e.value[:e.cursor]
}
+// unixWordRubout removes the part of the word on the left of the cursor. A word is
+// delimited by whitespaces.
+// The term `unix-word-rubout` comes from `readline` (see `man 3 readline`)
+func (e *Editor) unixWordRubout() {
+ if e.cursor <= 0 {
+ return
+ }
+ pos := e.cursor - 1
+ for pos != 0 && (unicode.IsSpace(e.value[pos]) || !unicode.IsSpace(e.value[pos-1])) {
+ pos--
+ }
+ e.killspace = append(e.killspace[:0], e.value[pos:e.cursor]...)
+ e.value = append(e.value[:pos], e.value[e.cursor:]...)
+ e.cursor = pos
+}
+
type BufView struct {
// TODO: Wrap bool
Y int // Y of the view in the Buf, for down/up scrolling
diff --git a/up_test.go b/up_test.go
index 20e8482..87f5278 100644
--- a/up_test.go
+++ b/up_test.go
@@ -81,3 +81,95 @@ func Test_Editor_insert(t *testing.T) {
}
}
}
+
+func Test_Editor_unix_word_rubout(t *testing.T) {
+ tests := []struct {
+ comment string
+ e Editor
+ wantValue []rune
+ wantKillspace []rune
+ }{
+ {
+ comment: "unix-word-rubout at beginning of line",
+ e: Editor{
+ value: []rune(`abc`),
+ cursor: 0,
+ },
+ wantValue: []rune(`abc`),
+ wantKillspace: []rune(``),
+ },
+ {
+ comment: "unix-word-rubout at soft beginning of line",
+ e: Editor{
+ value: []rune(` abc`),
+ cursor: 1,
+ },
+ wantValue: []rune(`abc`),
+ wantKillspace: []rune(` `),
+ },
+ {
+ comment: "unix-word-rubout until soft beginning of line",
+ e: Editor{
+ value: []rune(` abc`),
+ cursor: 2,
+ },
+ wantValue: []rune(` bc`),
+ wantKillspace: []rune(`a`),
+ },
+ {
+ comment: "unix-word-rubout until beginning of line",
+ e: Editor{
+ value: []rune(`abc`),
+ cursor: 2,
+ },
+ wantValue: []rune(`c`),
+ wantKillspace: []rune(`ab`),
+ },
+ {
+ comment: "unix-word-rubout in middle of line",
+ e: Editor{
+ value: []rune(`lorem ipsum dolor`),
+ cursor: 11,
+ },
+ wantValue: []rune(`lorem dolor`),
+ wantKillspace: []rune(`ipsum`),
+ },
+ {
+ comment: "unix-word-rubout cursor at beginning of word",
+ e: Editor{
+ value: []rune(`lorem ipsum dolor`),
+ cursor: 12,
+ },
+ wantValue: []rune(`lorem dolor`),
+ wantKillspace: []rune(`ipsum `),
+ },
+ {
+ comment: "unix-word-rubout cursor between multiple spaces",
+ e: Editor{
+ value: []rune(`a b c`),
+ cursor: 5,
+ },
+ wantValue: []rune(`a c`),
+ wantKillspace: []rune(`b `),
+ },
+ {
+ comment: "unix-word-rubout tab as space char (although is it a realistic case in the context of a command line instruction?)",
+ e: Editor{
+ value: []rune(`a b c`),
+ cursor: 5,
+ },
+ wantValue: []rune(`a c`),
+ wantKillspace: []rune(`b `),
+ },
+ }
+
+ for _, tt := range tests {
+ tt.e.unixWordRubout()
+ if string(tt.e.value) != string(tt.wantValue) {
+ t.Errorf("%q: bad value\nwant: %q\nhave: %q", tt.comment, tt.wantValue, tt.e.value)
+ }
+ if string(tt.e.killspace) != string(tt.wantKillspace) {
+ t.Errorf("%q: bad value in killspace\nwant: %q\nhave: %q", tt.comment, tt.wantKillspace, tt.e.value)
+ }
+ }
+}