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)
|
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 {
|
func GenerateCompletions(args []string) error {
|
||||||
output_type := "json"
|
output_type := "json"
|
||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
|
|||||||
@ -175,13 +175,19 @@ func exec_command(rl *readline.Readline, cmdline string) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func completions(before_cursor, after_cursor string) *cli.Completions {
|
func completions(before_cursor, after_cursor string) (ans *cli.Completions) {
|
||||||
text := "kitty @ " + before_cursor
|
const prefix = "kitty @ "
|
||||||
argv, err := shlex.Split(text)
|
text := prefix + before_cursor
|
||||||
if err != nil {
|
argv, position_of_last_arg := shlex.SplitForCompletion(text)
|
||||||
return nil
|
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) {
|
func shell_main(cmd *cli.Command, args []string) (int, error) {
|
||||||
|
|||||||
@ -5,7 +5,9 @@ package readline
|
|||||||
import (
|
import (
|
||||||
"container/list"
|
"container/list"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"kitty/tools/cli"
|
||||||
"kitty/tools/tui/loop"
|
"kitty/tools/tui/loop"
|
||||||
|
"kitty/tools/utils/shlex"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
@ -481,7 +483,7 @@ func TestHistory(t *testing.T) {
|
|||||||
t.Fatalf("Text before cursor not as expected:\n%s", diff)
|
t.Fatalf("Text before cursor not as expected:\n%s", diff)
|
||||||
}
|
}
|
||||||
if diff := cmp.Diff(after_cursor, aa); 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")
|
add_item("xyz1")
|
||||||
@ -512,3 +514,48 @@ func TestHistory(t *testing.T) {
|
|||||||
rl.perform_action(ActionTerminateHistorySearchAndRestore, 1)
|
rl.perform_action(ActionTerminateHistorySearchAndRestore, 1)
|
||||||
ah("a", "")
|
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.last_action = ActionNil
|
||||||
self.keyboard_state = KeyboardState{}
|
self.keyboard_state = KeyboardState{}
|
||||||
self.history_search = nil
|
self.history_search = nil
|
||||||
|
self.completions.current = completion{}
|
||||||
self.cursor_y = 0
|
self.cursor_y = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"kitty/tools/cli"
|
"kitty/tools/cli"
|
||||||
|
"kitty/tools/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = fmt.Print
|
var _ = fmt.Print
|
||||||
@ -39,7 +40,11 @@ func (self *completion) current_match_text() string {
|
|||||||
for _, g := range self.results.Groups {
|
for _, g := range self.results.Groups {
|
||||||
for _, m := range g.Matches {
|
for _, m := range g.Matches {
|
||||||
if i == self.current_match {
|
if i == self.current_match {
|
||||||
return m.Word
|
t := m.Word
|
||||||
|
if !g.NoTrailingSpace {
|
||||||
|
t += " "
|
||||||
|
}
|
||||||
|
return t
|
||||||
}
|
}
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
@ -83,6 +88,19 @@ func (self *Readline) complete(forwards bool, repeat_count uint) bool {
|
|||||||
}
|
}
|
||||||
ct := c.current.current_match_text()
|
ct := c.current.current_match_text()
|
||||||
if ct != "" {
|
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 {
|
if repeat_count > 0 {
|
||||||
self.complete(forwards, repeat_count)
|
self.complete(forwards, repeat_count)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user