mirror of
https://github.com/kovidgoyal/kitty
synced 2026-07-21 16:05:02 +02:00
More work on readline completion
This commit is contained in:
@@ -5,7 +5,9 @@ package readline
|
||||
import (
|
||||
"container/list"
|
||||
"fmt"
|
||||
"kitty/tools/cli"
|
||||
"kitty/tools/tui/loop"
|
||||
"kitty/tools/utils/shlex"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
@@ -481,7 +483,7 @@ func TestHistory(t *testing.T) {
|
||||
t.Fatalf("Text before cursor not as expected:\n%s", diff)
|
||||
}
|
||||
if diff := cmp.Diff(after_cursor, aa); diff != "" {
|
||||
t.Fatalf("Text before cursor not as expected:\n%s", diff)
|
||||
t.Fatalf("Text after cursor not as expected:\n%s", diff)
|
||||
}
|
||||
}
|
||||
add_item("xyz1")
|
||||
@@ -512,3 +514,48 @@ func TestHistory(t *testing.T) {
|
||||
rl.perform_action(ActionTerminateHistorySearchAndRestore, 1)
|
||||
ah("a", "")
|
||||
}
|
||||
|
||||
func TestReadlineCompletion(t *testing.T) {
|
||||
lp, _ := loop.New()
|
||||
|
||||
completer := func(before_cursor, after_cursor string) (ans *cli.Completions) {
|
||||
root := cli.NewRootCommand()
|
||||
c := root.AddSubCommand(&cli.Command{Name: "test-completion"})
|
||||
c.AddSubCommand(&cli.Command{Name: "a1"})
|
||||
c.AddSubCommand(&cli.Command{Name: "a11"})
|
||||
c.AddSubCommand(&cli.Command{Name: "a2"})
|
||||
prefix := c.Name + " "
|
||||
text := prefix + before_cursor
|
||||
argv, position_of_last_arg := shlex.SplitForCompletion(text)
|
||||
if len(argv) == 0 || position_of_last_arg < len(prefix) {
|
||||
return
|
||||
}
|
||||
ans = root.GetCompletions(argv, nil)
|
||||
ans.CurrentWordIdx = position_of_last_arg - len(prefix)
|
||||
return
|
||||
|
||||
}
|
||||
rl := New(lp, RlInit{Prompt: "$$ ", Completer: completer})
|
||||
|
||||
ah := func(before_cursor, after_cursor string) {
|
||||
ab := rl.text_upto_cursor_pos()
|
||||
aa := rl.text_after_cursor_pos()
|
||||
if diff := cmp.Diff(before_cursor, ab); diff != "" {
|
||||
t.Fatalf("Text before cursor not as expected:\n%s", diff)
|
||||
}
|
||||
if diff := cmp.Diff(after_cursor, aa); diff != "" {
|
||||
t.Fatalf("Text after cursor not as expected:\n%s", diff)
|
||||
}
|
||||
}
|
||||
rl.add_text("a")
|
||||
rl.perform_action(ActionCompleteForward, 1)
|
||||
ah("a", "")
|
||||
rl.perform_action(ActionCompleteForward, 1)
|
||||
ah("a1 ", "")
|
||||
rl.perform_action(ActionCompleteForward, 1)
|
||||
ah("a11 ", "")
|
||||
rl.perform_action(ActionCompleteForward, 1)
|
||||
ah("a2 ", "")
|
||||
rl.perform_action(ActionCompleteBackward, 1)
|
||||
ah("a11 ", "")
|
||||
}
|
||||
|
||||
@@ -181,6 +181,7 @@ func (self *Readline) ResetText() {
|
||||
self.last_action = ActionNil
|
||||
self.keyboard_state = KeyboardState{}
|
||||
self.history_search = nil
|
||||
self.completions.current = completion{}
|
||||
self.cursor_y = 0
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"kitty/tools/cli"
|
||||
"kitty/tools/utils"
|
||||
)
|
||||
|
||||
var _ = fmt.Print
|
||||
@@ -39,7 +40,11 @@ func (self *completion) current_match_text() string {
|
||||
for _, g := range self.results.Groups {
|
||||
for _, m := range g.Matches {
|
||||
if i == self.current_match {
|
||||
return m.Word
|
||||
t := m.Word
|
||||
if !g.NoTrailingSpace {
|
||||
t += " "
|
||||
}
|
||||
return t
|
||||
}
|
||||
i++
|
||||
}
|
||||
@@ -83,6 +88,19 @@ func (self *Readline) complete(forwards bool, repeat_count uint) bool {
|
||||
}
|
||||
ct := c.current.current_match_text()
|
||||
if ct != "" {
|
||||
before := c.current.before_cursor[:c.current.results.CurrentWordIdx] + ct
|
||||
after := c.current.after_cursor
|
||||
self.input_state.lines = utils.Splitlines(before)
|
||||
if len(self.input_state.lines) == 0 {
|
||||
self.input_state.lines = []string{""}
|
||||
}
|
||||
self.input_state.cursor.Y = len(self.input_state.lines) - 1
|
||||
self.input_state.cursor.X = len(self.input_state.lines[self.input_state.cursor.Y])
|
||||
al := utils.Splitlines(after)
|
||||
if len(al) > 0 {
|
||||
self.input_state.lines[self.input_state.cursor.Y] += al[0]
|
||||
self.input_state.lines = append(self.input_state.lines, al[1:]...)
|
||||
}
|
||||
}
|
||||
if repeat_count > 0 {
|
||||
self.complete(forwards, repeat_count)
|
||||
|
||||
Reference in New Issue
Block a user