summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AUTHORS1
-rw-r--r--up.go48
-rw-r--r--up_test.go83
3 files changed, 120 insertions, 12 deletions
diff --git a/AUTHORS b/AUTHORS
index c7f2ac2..3ddb6f7 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,4 +1,5 @@
Please keep the contents of this file sorted alphabetically.
+Calum MacRae <calum0macrae@gmail.com>
Mateusz Czapliński <czapkofan@gmail.com>
Rohan Verma <hello@rohanverma.net>
diff --git a/up.go b/up.go
index 9028d89..be6a877 100644
--- a/up.go
+++ b/up.go
@@ -36,7 +36,7 @@ import (
"github.com/spf13/pflag"
)
-const version = "0.3.1 (2018-10-31)"
+const version = "0.3.2 (2018-12-04)"
// TODO: in case of error, show it in red (bg?), then below show again initial normal output (see also #4)
// TODO: F1 should display help, and it should be multi-line, and scrolling licensing credits
@@ -283,9 +283,10 @@ func NewEditor(prompt string) *Editor {
type Editor struct {
// TODO: make editor multiline. Reuse gocui or something for this?
- prompt []rune
- value []rune
- cursor int
+ prompt []rune
+ value []rune
+ killspace []rune
+ cursor int
// lastw is length of value on last Draw; we need it to know how much to erase after backspace
lastw int
}
@@ -326,14 +327,30 @@ func (e *Editor) HandleKey(ev *tcell.EventKey) bool {
e.delete(-1)
case key(tcell.KeyDelete):
e.delete(0)
- case key(tcell.KeyLeft):
+ case key(tcell.KeyLeft),
+ key(tcell.KeyCtrlB),
+ ctrlKey(tcell.KeyCtrlB):
if e.cursor > 0 {
e.cursor--
}
- case key(tcell.KeyRight):
+ case key(tcell.KeyRight),
+ key(tcell.KeyCtrlF),
+ ctrlKey(tcell.KeyCtrlF):
if e.cursor < len(e.value) {
e.cursor++
}
+ case key(tcell.KeyCtrlA),
+ ctrlKey(tcell.KeyCtrlA):
+ e.cursor = 0
+ case key(tcell.KeyCtrlE),
+ ctrlKey(tcell.KeyCtrlE):
+ e.cursor = len(e.value)
+ case key(tcell.KeyCtrlK),
+ ctrlKey(tcell.KeyCtrlK):
+ e.kill()
+ case key(tcell.KeyCtrlY),
+ ctrlKey(tcell.KeyCtrlY):
+ e.insert(e.killspace...)
default:
// Unknown key/combination, not handled
return false
@@ -341,12 +358,12 @@ func (e *Editor) HandleKey(ev *tcell.EventKey) bool {
return true
}
-func (e *Editor) insert(ch rune) {
- // Insert character into value (https://github.com/golang/go/wiki/SliceTricks#insert)
- e.value = append(e.value, 0)
- copy(e.value[e.cursor+1:], e.value[e.cursor:])
- e.value[e.cursor] = ch
- e.cursor++
+func (e *Editor) insert(ch ...rune) {
+ // Based on https://github.com/golang/go/wiki/SliceTricks#insert
+ e.value = append(e.value, ch...) // = PREFIX + SUFFIX + (filler)
+ copy(e.value[e.cursor+len(ch):], e.value[e.cursor:]) // = PREFIX + (filler) + SUFFIX
+ copy(e.value[e.cursor:], ch) // = PREFIX + ch + SUFFIX
+ e.cursor += len(ch)
}
func (e *Editor) delete(dx int) {
@@ -358,6 +375,13 @@ func (e *Editor) delete(dx int) {
e.cursor = pos
}
+func (e *Editor) kill() {
+ if e.cursor != len(e.value) {
+ e.killspace = append(e.killspace[:0], e.value[e.cursor:]...)
+ }
+ e.value = e.value[:e.cursor]
+}
+
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
new file mode 100644
index 0000000..de31c59
--- /dev/null
+++ b/up_test.go
@@ -0,0 +1,83 @@
+package main
+
+import "testing"
+
+func Test_Editor_insert(test *testing.T) {
+ cases := []struct {
+ comment string
+ e Editor
+ insert []rune
+ wantValue []rune
+ }{
+ {
+ comment: "prepend ASCII char",
+ e: Editor{
+ value: []rune(`abc`),
+ cursor: 0,
+ },
+ insert: []rune{'X'},
+ wantValue: []rune(`Xabc`),
+ },
+ {
+ comment: "prepend UTF char",
+ e: Editor{
+ value: []rune(`abc`),
+ cursor: 0,
+ },
+ insert: []rune{'☃'},
+ wantValue: []rune(`☃abc`),
+ },
+ {
+ comment: "insert ASCII char",
+ e: Editor{
+ value: []rune(`abc`),
+ cursor: 1,
+ },
+ insert: []rune{'X'},
+ wantValue: []rune(`aXbc`),
+ },
+ {
+ comment: "insert UTF char",
+ e: Editor{
+ value: []rune(`abc`),
+ cursor: 1,
+ },
+ insert: []rune{'☃'},
+ wantValue: []rune(`a☃bc`),
+ },
+ {
+ comment: "append ASCII char",
+ e: Editor{
+ value: []rune(`abc`),
+ cursor: 3,
+ },
+ insert: []rune{'X'},
+ wantValue: []rune(`abcX`),
+ },
+ {
+ comment: "append UTF char",
+ e: Editor{
+ value: []rune(`abc`),
+ cursor: 3,
+ },
+ insert: []rune{'☃'},
+ wantValue: []rune(`abc☃`),
+ },
+ {
+ comment: "insert 2 ASCII chars",
+ e: Editor{
+ value: []rune(`abc`),
+ cursor: 1,
+ },
+ insert: []rune{'X', 'Y'},
+ wantValue: []rune(`aXYbc`),
+ },
+ }
+
+ for _, c := range cases {
+ c.e.insert(c.insert...)
+ if string(c.e.value) != string(c.wantValue) {
+ test.Errorf("%q: bad value\nwant: %q\nhave: %q", c.comment, c.wantValue, c.e.value)
+ }
+ }
+}