More work on readline completion
This commit is contained in:
parent
4974219e0f
commit
9e2c96653f
@ -51,14 +51,6 @@ func RegisterExeForCompletion(x func(root *Command)) {
|
||||
registered_exes = append(registered_exes, x)
|
||||
}
|
||||
|
||||
func CompletionsForArgv(argv []string) *Completions {
|
||||
var root = NewRootCommand()
|
||||
for _, re := range registered_exes {
|
||||
re(root)
|
||||
}
|
||||
return root.GetCompletions(argv, init_completions["json"])
|
||||
}
|
||||
|
||||
func GenerateCompletions(args []string) error {
|
||||
output_type := "json"
|
||||
if len(args) > 0 {
|
||||
|
||||
@ -175,13 +175,19 @@ func exec_command(rl *readline.Readline, cmdline string) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func completions(before_cursor, after_cursor string) *cli.Completions {
|
||||
text := "kitty @ " + before_cursor
|
||||
argv, err := shlex.Split(text)
|
||||
if err != nil {
|
||||
return nil
|
||||
func completions(before_cursor, after_cursor string) (ans *cli.Completions) {
|
||||
const prefix = "kitty @ "
|
||||
text := prefix + before_cursor
|
||||
argv, position_of_last_arg := shlex.SplitForCompletion(text)
|
||||
if len(argv) == 0 || position_of_last_arg < len(prefix) {
|
||||
return
|
||||
}
|
||||
return cli.CompletionsForArgv(argv)
|
||||
root := cli.NewRootCommand()
|
||||
c := root.AddSubCommand(&cli.Command{Name: "kitty-tool"})
|
||||
EntryPoint(c)
|
||||
ans = root.GetCompletions(argv, nil)
|
||||
ans.CurrentWordIdx = position_of_last_arg - len(prefix)
|
||||
return
|
||||
}
|
||||
|
||||
func shell_main(cmd *cli.Command, args []string) (int, error) {
|
||||
|
||||
@ -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)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user