Skip to content
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.

Александр Крамарев <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>
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
Comment thread
akavel marked this conversation as 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
Comment thread
padawin marked this conversation as resolved.
// delimited by whitespaces.
Comment thread
akavel marked this conversation as 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) {
Comment thread
akavel marked this conversation as 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 `),
},
Comment thread
akavel marked this conversation as 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)
}
}
}