Code to move cursor left

This commit is contained in:
Kovid Goyal
2022-10-06 13:25:10 +05:30
parent 066465bce7
commit 57310a772a
2 changed files with 70 additions and 5 deletions

View File

@@ -7,6 +7,7 @@ import (
"strings"
"kitty/tools/utils"
"kitty/tools/wcswidth"
)
var _ = fmt.Print
@@ -90,3 +91,32 @@ func (self *Readline) add_text(text string) {
}
self.lines = new_lines
}
func (self *Readline) move_cursor_left(amt uint, traverse_line_breaks bool) uint {
var amt_moved uint
for ; amt > 0; amt -= 1 {
if self.cursor_pos_in_line == 0 {
if !traverse_line_breaks || self.cursor_line == 0 {
return amt_moved
}
self.cursor_line -= 1
self.cursor_pos_in_line = len(self.lines[self.cursor_pos_in_line])
amt_moved += 1
continue
}
// This is an extremely inefficient algorithm but it does not matter since
// lines are not large.
line := self.lines[self.cursor_line]
runes := []rune(line[:self.cursor_pos_in_line])
orig_width := wcswidth.Stringwidth(line[:self.cursor_pos_in_line])
current_width := orig_width
for current_width == orig_width && len(runes) > 0 {
runes = runes[:len(runes)-1]
s := string(runes)
current_width = wcswidth.Stringwidth(s)
}
self.cursor_pos_in_line = len(string(runes))
amt_moved += 1
}
return amt_moved
}

View File

@@ -10,10 +10,9 @@ import (
var _ = fmt.Print
func TestAddText(t *testing.T) {
lp, _ := loop.New()
dt := func(initial string, prepare func(rl *Readline), expected ...string) {
func test_func(t *testing.T) func(string, func(*Readline), ...string) *Readline {
return func(initial string, prepare func(rl *Readline), expected ...string) *Readline {
lp, _ := loop.New()
rl := New(lp, RlInit{})
rl.add_text(initial)
if prepare != nil {
@@ -34,8 +33,13 @@ func TestAddText(t *testing.T) {
t.Fatalf("Text not as expected for: %#v\n%#v != %#v", initial, expected[2], rl.all_text())
}
}
return rl
}
}
func TestAddText(t *testing.T) {
dt := test_func(t)
dt("test", nil, "test", "", "test")
dt("1234\n", nil, "1234\n", "", "1234\n")
dt("abcd", func(rl *Readline) {
@@ -50,5 +54,36 @@ func TestAddText(t *testing.T) {
rl.cursor_pos_in_line = 2
rl.add_text("12\n34")
}, "abcd\nxy12\n34", "z", "abcd\nxy12\n34z")
}
func TestCursorMovement(t *testing.T) {
dt := test_func(t)
left := func(rl *Readline, amt uint, moved_amt uint, traverse_line_breaks bool) {
actual := rl.move_cursor_left(amt, traverse_line_breaks)
if actual != moved_amt {
t.Fatalf("Failed to move cursor by %#v\nactual != expected: %#v != %#v", amt, actual, moved_amt)
}
}
dt("one\ntwo", func(rl *Readline) {
left(rl, 2, 2, false)
}, "one\nt", "wo")
dt("one\ntwo", func(rl *Readline) {
left(rl, 4, 3, false)
}, "one\n", "two")
dt("one\ntwo", func(rl *Readline) {
left(rl, 4, 4, true)
}, "one", "\ntwo")
dt("one\ntwo", func(rl *Readline) {
left(rl, 7, 7, true)
}, "", "one\ntwo")
dt("one\ntwo", func(rl *Readline) {
left(rl, 10, 7, true)
}, "", "one\ntwo")
dt("one😀", func(rl *Readline) {
left(rl, 1, 1, false)
}, "one", "😀")
dt("oneä", func(rl *Readline) {
left(rl, 1, 1, false)
}, "one", "ä")
}