Start work on readline completions
This commit is contained in:
parent
f919efcd42
commit
7c23536bfe
@ -434,6 +434,9 @@ def generate_readline_actions() -> str:
|
|||||||
ActionNumericArgumentDigit8
|
ActionNumericArgumentDigit8
|
||||||
ActionNumericArgumentDigit9
|
ActionNumericArgumentDigit9
|
||||||
ActionNumericArgumentDigitMinus
|
ActionNumericArgumentDigitMinus
|
||||||
|
|
||||||
|
ActionCompleteForward
|
||||||
|
ActionCompleteBackward
|
||||||
''')
|
''')
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -51,6 +51,14 @@ 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 {
|
||||||
|
|||||||
@ -176,6 +176,15 @@ func exec_command(rl *readline.Readline, cmdline string) bool {
|
|||||||
return true
|
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) {
|
func shell_main(cmd *cli.Command, args []string) (int, error) {
|
||||||
formatter = markup.New(true)
|
formatter = markup.New(true)
|
||||||
fmt.Println("Welcome to the kitty shell!")
|
fmt.Println("Welcome to the kitty shell!")
|
||||||
@ -189,7 +198,7 @@ func shell_main(cmd *cli.Command, args []string) (int, error) {
|
|||||||
}
|
}
|
||||||
fmt.Println(amsg)
|
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() {
|
defer func() {
|
||||||
rl.Shutdown()
|
rl.Shutdown()
|
||||||
}()
|
}()
|
||||||
|
|||||||
@ -654,6 +654,14 @@ func (self *Readline) _perform_action(ac Action, repeat_count uint) (err error,
|
|||||||
self.end_history_search(true)
|
self.end_history_search(true)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
case ActionCompleteForward:
|
||||||
|
if self.complete(true, repeat_count) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case ActionCompleteBackward:
|
||||||
|
if self.complete(false, repeat_count) {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
err = ErrCouldNotPerformAction
|
err = ErrCouldNotPerformAction
|
||||||
return
|
return
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"kitty/tools/cli"
|
||||||
"kitty/tools/cli/markup"
|
"kitty/tools/cli/markup"
|
||||||
"kitty/tools/tui/loop"
|
"kitty/tools/tui/loop"
|
||||||
"kitty/tools/wcswidth"
|
"kitty/tools/wcswidth"
|
||||||
@ -18,6 +19,7 @@ const ST = "\x1b\\"
|
|||||||
const PROMPT_MARK = "\x1b]133;"
|
const PROMPT_MARK = "\x1b]133;"
|
||||||
|
|
||||||
type SyntaxHighlightFunction = func(text string, x, y int) string
|
type SyntaxHighlightFunction = func(text string, x, y int) string
|
||||||
|
type CompleterFunction = func(before_cursor, after_cursor string) *cli.Completions
|
||||||
|
|
||||||
type RlInit struct {
|
type RlInit struct {
|
||||||
Prompt string
|
Prompt string
|
||||||
@ -27,6 +29,7 @@ type RlInit struct {
|
|||||||
EmptyContinuationPrompt bool
|
EmptyContinuationPrompt bool
|
||||||
DontMarkPrompts bool
|
DontMarkPrompts bool
|
||||||
SyntaxHighlighter SyntaxHighlightFunction
|
SyntaxHighlighter SyntaxHighlightFunction
|
||||||
|
Completer CompleterFunction
|
||||||
}
|
}
|
||||||
|
|
||||||
type Position struct {
|
type Position struct {
|
||||||
@ -127,6 +130,7 @@ type Readline struct {
|
|||||||
fmt_ctx *markup.Context
|
fmt_ctx *markup.Context
|
||||||
text_to_be_added string
|
text_to_be_added string
|
||||||
syntax_highlighted syntax_highlighted
|
syntax_highlighted syntax_highlighted
|
||||||
|
completions completions
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *Readline) make_prompt(text string, is_secondary bool) Prompt {
|
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),
|
mark_prompts: !r.DontMarkPrompts, fmt_ctx: markup.New(true),
|
||||||
loop: loop, input_state: InputState{lines: []string{""}}, history: NewHistory(r.HistoryPath, hc),
|
loop: loop, input_state: InputState{lines: []string{""}}, history: NewHistory(r.HistoryPath, hc),
|
||||||
syntax_highlighted: syntax_highlighted{highlighter: r.SyntaxHighlighter},
|
syntax_highlighted: syntax_highlighted{highlighter: r.SyntaxHighlighter},
|
||||||
|
completions: completions{completer: r.Completer},
|
||||||
kill_ring: kill_ring{items: list.New().Init()},
|
kill_ring: kill_ring{items: list.New().Init()},
|
||||||
}
|
}
|
||||||
ans.prompt = ans.make_prompt(r.Prompt, false)
|
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