diff --git a/tools/tui/readline/actions_test.go b/tools/tui/readline/actions_test.go index 1c91b8645..3f3ab5e00 100644 --- a/tools/tui/readline/actions_test.go +++ b/tools/tui/readline/actions_test.go @@ -70,7 +70,7 @@ func TestGetScreenLines(t *testing.T) { actual[i] = *x } if diff := cmp.Diff(expected, actual); diff != "" { - t.Fatalf("Did not get expected screen lines for: %#v\n%s", rl.AllText(), diff) + t.Fatalf("Did not get expected screen lines for: %#v and cursor: %+v\n%s", rl.AllText(), rl.cursor, diff) } } tsl(ScreenLine{PromptLen: 3, CursorCell: 3}) @@ -83,6 +83,43 @@ func TestGetScreenLines(t *testing.T) { ScreenLine{PromptLen: 3, CursorCell: -1, Text: "1234567", CursorTextPos: -1, TextLengthInCells: 7}, ScreenLine{OffsetInParentLine: 7}, ) + rl.add_text("89") + tsl( + ScreenLine{PromptLen: 3, CursorCell: -1, Text: "1234567", CursorTextPos: -1, TextLengthInCells: 7}, + ScreenLine{OffsetInParentLine: 7, Text: "89", CursorCell: 2, TextLengthInCells: 2, CursorTextPos: 2}, + ) + rl.ResetText() + rl.add_text("123\n456abcdeXYZ") + tsl( + ScreenLine{PromptLen: 3, CursorCell: -1, Text: "123", CursorTextPos: -1, TextLengthInCells: 3}, + ScreenLine{ParentLineNumber: 1, PromptLen: 2, Text: "456abcde", TextLengthInCells: 8, CursorCell: -1, CursorTextPos: -1}, + ScreenLine{OffsetInParentLine: 8, ParentLineNumber: 1, TextLengthInCells: 3, CursorCell: 3, CursorTextPos: 3, Text: "XYZ"}, + ) + rl.cursor = Position{X: 2} + tsl( + ScreenLine{PromptLen: 3, CursorCell: 5, Text: "123", CursorTextPos: 2, TextLengthInCells: 3}, + ScreenLine{ParentLineNumber: 1, PromptLen: 2, Text: "456abcde", TextLengthInCells: 8, CursorCell: -1, CursorTextPos: -1}, + ScreenLine{OffsetInParentLine: 8, ParentLineNumber: 1, TextLengthInCells: 3, CursorCell: -1, CursorTextPos: -1, Text: "XYZ"}, + ) + rl.cursor = Position{X: 2, Y: 1} + tsl( + ScreenLine{PromptLen: 3, CursorCell: -1, Text: "123", CursorTextPos: -1, TextLengthInCells: 3}, + ScreenLine{ParentLineNumber: 1, PromptLen: 2, Text: "456abcde", TextLengthInCells: 8, CursorCell: 4, CursorTextPos: 2}, + ScreenLine{OffsetInParentLine: 8, ParentLineNumber: 1, TextLengthInCells: 3, CursorCell: -1, CursorTextPos: -1, Text: "XYZ"}, + ) + rl.cursor = Position{X: 8, Y: 1} + tsl( + ScreenLine{PromptLen: 3, CursorCell: -1, Text: "123", CursorTextPos: -1, TextLengthInCells: 3}, + ScreenLine{ParentLineNumber: 1, PromptLen: 2, Text: "456abcde", TextLengthInCells: 8, CursorCell: -1, CursorTextPos: -1}, + ScreenLine{OffsetInParentLine: 8, ParentLineNumber: 1, TextLengthInCells: 3, CursorCell: 0, CursorTextPos: 0, Text: "XYZ"}, + ) + rl.ResetText() + rl.add_text("1234567\nabc") + rl.cursor = Position{X: 7} + tsl( + ScreenLine{PromptLen: 3, CursorCell: -1, Text: "1234567", CursorTextPos: -1, TextLengthInCells: 7}, + ScreenLine{ParentLineNumber: 1, PromptLen: 2, Text: "abc", CursorCell: 2, TextLengthInCells: 3, CursorTextPos: 0}, + ) } func TestCursorMovement(t *testing.T) { diff --git a/tools/tui/readline/api.go b/tools/tui/readline/api.go index 61cf8430f..4d32e5404 100644 --- a/tools/tui/readline/api.go +++ b/tools/tui/readline/api.go @@ -105,13 +105,17 @@ func (self *Readline) AddHistoryItem(hi HistoryItem) { self.history.add_item(hi) } -func (self *Readline) ChangeLoopAndResetText(lp *loop.Loop) { - self.loop = lp +func (self *Readline) ResetText() { self.lines = []string{""} self.cursor = Position{} self.cursor_y = 0 } +func (self *Readline) ChangeLoopAndResetText(lp *loop.Loop) { + self.loop = lp + self.ResetText() +} + func (self *Readline) Start() { self.loop.SetCursorShape(loop.BAR_CURSOR, true) self.loop.StartBracketedPaste() diff --git a/tools/tui/readline/draw.go b/tools/tui/readline/draw.go index f5f183460..5f1c85737 100644 --- a/tools/tui/readline/draw.go +++ b/tools/tui/readline/draw.go @@ -36,6 +36,7 @@ func (self *Readline) get_screen_lines() []*ScreenLine { } ans := make([]*ScreenLine, 0, len(self.lines)) found_cursor := false + cursor_at_start_of_next_line := false for i, line := range self.lines { plen := self.prompt_len if i > 0 { @@ -50,20 +51,28 @@ func (self *Readline) get_screen_lines() []*ScreenLine { PromptLen: plen, TextLengthInCells: width, CursorCell: -1, Text: l, CursorTextPos: -1, } + if cursor_at_start_of_next_line { + cursor_at_start_of_next_line = false + sl.CursorCell = plen + sl.CursorTextPos = 0 + } ans = append(ans, &sl) if has_cursor && !found_cursor && offset <= self.cursor.X && self.cursor.X <= offset+len(l) { found_cursor = true ctpos := self.cursor.X - offset ccell := plen + wcswidth.Stringwidth(l[:ctpos]) if ccell >= self.screen_width { - ans = append(ans, &ScreenLine{OffsetInParentLine: len(line)}) + if offset+len(l) < len(line) || i < len(self.lines)-1 { + cursor_at_start_of_next_line = true + } else { + ans = append(ans, &ScreenLine{ParentLineNumber: i, OffsetInParentLine: len(line)}) + } } else { sl.CursorTextPos = ctpos sl.CursorCell = ccell } } plen = 0 - is_first = false offset += len(l) } }