Start work on readline completions
This commit is contained in:
parent
f919efcd42
commit
7c23536bfe
@ -434,6 +434,9 @@ def generate_readline_actions() -> str:
|
||||
ActionNumericArgumentDigit8
|
||||
ActionNumericArgumentDigit9
|
||||
ActionNumericArgumentDigitMinus
|
||||
|
||||
ActionCompleteForward
|
||||
ActionCompleteBackward
|
||||
''')
|
||||
|
||||
|
||||
|
||||
@ -51,6 +51,14 @@ 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 {
|
||||
|
||||
@ -176,6 +176,15 @@ 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
|
||||
}
|
||||
return cli.CompletionsForArgv(argv)
|
||||
}
|
||||
|
||||
func shell_main(cmd *cli.Command, args []string) (int, error) {
|
||||
formatter = markup.New(true)
|
||||
fmt.Println("Welcome to the kitty shell!")
|
||||
@ -189,7 +198,7 @@ func shell_main(cmd *cli.Command, args []string) (int, error) {
|
||||
}
|
||||
fmt.Println(amsg)
|
||||
}
|
||||
rl := readline.New(nil, readline.RlInit{Prompt: prompt, HistoryPath: filepath.Join(utils.CacheDir(), "shell.history.json")})
|
||||
rl := readline.New(nil, readline.RlInit{Prompt: prompt, Completer: completions, HistoryPath: filepath.Join(utils.CacheDir(), "shell.history.json")})
|
||||
defer func() {
|
||||
rl.Shutdown()
|
||||
}()
|
||||
|
||||
@ -654,6 +654,14 @@ func (self *Readline) _perform_action(ac Action, repeat_count uint) (err error,
|
||||
self.end_history_search(true)
|
||||
return
|
||||
}
|
||||
case ActionCompleteForward:
|
||||
if self.complete(true, repeat_count) {
|
||||
return
|
||||
}
|
||||
case ActionCompleteBackward:
|
||||
if self.complete(false, repeat_count) {
|
||||
return
|
||||
}
|
||||
}
|
||||
err = ErrCouldNotPerformAction
|
||||
return
|
||||
|
||||
@ -7,6 +7,7 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"kitty/tools/cli"
|
||||
"kitty/tools/cli/markup"
|
||||
"kitty/tools/tui/loop"
|
||||
"kitty/tools/wcswidth"
|
||||
@ -18,6 +19,7 @@ const ST = "\x1b\\"
|
||||
const PROMPT_MARK = "\x1b]133;"
|
||||
|
||||
type SyntaxHighlightFunction = func(text string, x, y int) string
|
||||
type CompleterFunction = func(before_cursor, after_cursor string) *cli.Completions
|
||||
|
||||
type RlInit struct {
|
||||
Prompt string
|
||||
@ -27,6 +29,7 @@ type RlInit struct {
|
||||
EmptyContinuationPrompt bool
|
||||
DontMarkPrompts bool
|
||||
SyntaxHighlighter SyntaxHighlightFunction
|
||||
Completer CompleterFunction
|
||||
}
|
||||
|
||||
type Position struct {
|
||||
@ -127,6 +130,7 @@ type Readline struct {
|
||||
fmt_ctx *markup.Context
|
||||
text_to_be_added string
|
||||
syntax_highlighted syntax_highlighted
|
||||
completions completions
|
||||
}
|
||||
|
||||
func (self *Readline) make_prompt(text string, is_secondary bool) Prompt {
|
||||
@ -149,6 +153,7 @@ func New(loop *loop.Loop, r RlInit) *Readline {
|
||||
mark_prompts: !r.DontMarkPrompts, fmt_ctx: markup.New(true),
|
||||
loop: loop, input_state: InputState{lines: []string{""}}, history: NewHistory(r.HistoryPath, hc),
|
||||
syntax_highlighted: syntax_highlighted{highlighter: r.SyntaxHighlighter},
|
||||
completions: completions{completer: r.Completer},
|
||||
kill_ring: kill_ring{items: list.New().Init()},
|
||||
}
|
||||
ans.prompt = ans.make_prompt(r.Prompt, false)
|
||||
|
||||
91
tools/tui/readline/completion.go
Normal file
91
tools/tui/readline/completion.go
Normal file
@ -0,0 +1,91 @@
|
||||
// License: GPLv3 Copyright: 2022, Kovid Goyal, <kovid at kovidgoyal.net>
|
||||
|
||||
package readline
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"kitty/tools/cli"
|
||||
)
|
||||
|
||||
var _ = fmt.Print
|
||||
|
||||
type completion struct {
|
||||
before_cursor, after_cursor string
|
||||
results *cli.Completions
|
||||
results_displayed, forwards bool
|
||||
num_of_matches, current_match int
|
||||
}
|
||||
|
||||
func (self *completion) initialize() {
|
||||
self.num_of_matches = 0
|
||||
if self.results != nil {
|
||||
for _, g := range self.results.Groups {
|
||||
self.num_of_matches += len(g.Matches)
|
||||
}
|
||||
}
|
||||
self.current_match = -1
|
||||
if !self.forwards {
|
||||
self.current_match = self.num_of_matches
|
||||
}
|
||||
if self.num_of_matches == 1 {
|
||||
self.current_match = 0
|
||||
}
|
||||
}
|
||||
|
||||
func (self *completion) current_match_text() string {
|
||||
if self.results != nil {
|
||||
i := 0
|
||||
for _, g := range self.results.Groups {
|
||||
for _, m := range g.Matches {
|
||||
if i == self.current_match {
|
||||
return m.Word
|
||||
}
|
||||
i++
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type completions struct {
|
||||
completer CompleterFunction
|
||||
current completion
|
||||
}
|
||||
|
||||
func (self *Readline) complete(forwards bool, repeat_count uint) bool {
|
||||
c := &self.completions
|
||||
if c.completer == nil {
|
||||
return false
|
||||
}
|
||||
if self.last_action == ActionCompleteForward || self.last_action == ActionCompleteBackward {
|
||||
delta := -1
|
||||
if forwards {
|
||||
delta = 1
|
||||
}
|
||||
delta *= int(repeat_count)
|
||||
c.current.current_match = (c.current.current_match + delta + c.current.num_of_matches) % c.current.num_of_matches
|
||||
repeat_count = 0
|
||||
} else {
|
||||
before, after := self.text_upto_cursor_pos(), self.text_after_cursor_pos()
|
||||
if before == "" {
|
||||
return false
|
||||
}
|
||||
c.current = completion{before_cursor: before, after_cursor: after, forwards: forwards, results: c.completer(before, after)}
|
||||
c.current.initialize()
|
||||
if repeat_count > 0 {
|
||||
repeat_count--
|
||||
}
|
||||
}
|
||||
c.current.forwards = forwards
|
||||
if c.current.results == nil {
|
||||
return false
|
||||
}
|
||||
ct := c.current.current_match_text()
|
||||
if ct != "" {
|
||||
}
|
||||
if repeat_count > 0 {
|
||||
self.complete(forwards, repeat_count)
|
||||
}
|
||||
return true
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user