Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

keys: Implement unix-word-rubout (Ctrl-W) #54

Merged
merged 1 commit into from
Apr 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ Please keep the contents of this file sorted alphabetically.

Александр Крамарев <[email protected]>
Calum MacRae <[email protected]>
Ghislain Rodrigues <[email protected]>
Mateusz Czapliński <[email protected]>
Rohan Verma <[email protected]>
22 changes: 21 additions & 1 deletion up.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"os"
"os/exec"
"sync"
"unicode"

"github.com/gdamore/tcell"
"github.com/gdamore/tcell/terminfo"
Expand Down Expand Up @@ -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
akavel marked this conversation as resolved.
Show resolved Hide resolved
- navigate and edit the pipeline command
- Enter - execute the pipeline command, updating the pipeline output panel
- Up, Dn, PgUp, PgDn, Ctrl-Left, Ctrl-Right
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
padawin marked this conversation as resolved.
Show resolved Hide resolved
// delimited by whitespaces.
akavel marked this conversation as resolved.
Show resolved Hide resolved
// 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
Expand Down
92 changes: 92 additions & 0 deletions up_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,95 @@ func Test_Editor_insert(t *testing.T) {
}
}
}

func Test_Editor_unix_word_rubout(t *testing.T) {
akavel marked this conversation as resolved.
Show resolved Hide resolved
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 `),
},
akavel marked this conversation as resolved.
Show resolved Hide resolved
}

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