args completion for rc commands

This commit is contained in:
Kovid Goyal 2022-09-15 21:49:04 +05:30
parent d4b67f3b6a
commit c9d986f9a8
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
5 changed files with 75 additions and 2 deletions

View File

@ -51,6 +51,8 @@ def generate_completion_for_rc(name: str) -> None:
cmd = command_for_name(name)
if cmd.short_desc:
print(f'{name}.Description = "{serialize_as_go_string(cmd.short_desc)}"')
for x in cmd.args.as_go_completion_code(name):
print(x)
def generate_completions_for_kitty() -> None:

View File

@ -197,6 +197,26 @@ class ArgsHandling:
return 0
return self.count
def as_go_completion_code(self, go_name: str) -> Iterator[str]:
from ..cli import serialize_as_go_string
c = self.args_count
if c is not None:
yield f'{go_name}.Stop_processing_at_arg = {c}'
if self.completion:
for k, v in self.completion.items():
if k == 'files':
title, pats = v
assert isinstance(pats, tuple)
gpats = (f'"{serialize_as_go_string(x)}"' for x in pats)
yield f'{go_name}.Completion_for_arg = fnmatch_completer("{serialize_as_go_string(title)}", {", ".join(gpats)})'
elif k == 'names':
title, gen = v
assert callable(gen)
gpats = (f'"{serialize_as_go_string(x)}"' for x in gen())
yield f'{go_name}.Completion_for_arg = names_completer("{serialize_as_go_string(title)}", {", ".join(gpats)})'
else:
raise KeyError(f'Unknown args completion type: {k}')
def as_go_code(self, cmd_name: str, field_types: Dict[str, str], handled_fields: Set[str]) -> Iterator[str]:
c = self.args_count
if c == 0:

View File

@ -83,9 +83,9 @@ def completion(self: TestCompletion, tdir: str):
make_file('bin/exe1', 0o700)
make_file('bin/exe-not1')
make_file('exe2', 0o700)
make_file('exe-not2')
make_file('exe-not2.jpeg')
make_file('sub/exe3', 0o700)
make_file('sub/exe-not3')
make_file('sub/exe-not3.png')
add('kitty x', all_words())
add('kitty e', all_words('exe1'))
@ -96,6 +96,13 @@ def completion(self: TestCompletion, tdir: str):
add('kitty ~/', all_words('~/exe3'))
add('kitty ~/e', all_words('~/exe3'))
add('kitty @ goto-layout ', has_words('tall', 'fat'))
add('kitty @ goto-layout spli', all_words('splits'))
add('kitty @ goto-layout f f', all_words())
add('kitty @ set-window-logo ', all_words('exe-not2.jpeg', 'sub/exe-not3.png'))
add('kitty @ set-window-logo e', all_words('exe-not2.jpeg'))
add('kitty @ set-window-logo e e', all_words())
for cmd, tests, result in zip(all_cmds, all_tests, run_tool()):
self.current_cmd = cmd
for test in tests:

View File

@ -78,3 +78,36 @@ func complete_executables_in_path(prefix string, paths ...string) []string {
}
return ans
}
func complete_by_fnmatch(prefix string, patterns []string) []string {
ans := make([]string, 0, 1024)
complete_files(prefix, func(completion_candidate, abspath string, d fs.DirEntry) error {
q := strings.ToLower(filepath.Base(abspath))
for _, pat := range patterns {
matched, err := filepath.Match(pat, q)
if err == nil && matched {
ans = append(ans, completion_candidate)
}
}
return nil
})
return ans
}
func fnmatch_completer(title string, patterns ...string) completion_func {
lpats := make([]string, 0, len(patterns))
for _, p := range patterns {
lpats = append(lpats, strings.ToLower(p))
}
return func(completions *Completions, word string, arg_num int) {
q := complete_by_fnmatch(word, lpats)
if len(q) > 0 {
mg := completions.add_match_group(title)
mg.IsFiles = true
for _, c := range q {
mg.add_match(c)
}
}
}
}

View File

@ -136,3 +136,14 @@ func (self *Command) GetCompletions(argv []string) *Completions {
ans.Groups = non_empty_groups
return &ans
}
func names_completer(title string, names ...string) completion_func {
return func(completions *Completions, word string, arg_num int) {
mg := completions.add_match_group(title)
for _, q := range names {
if strings.HasPrefix(q, word) {
mg.add_match(q)
}
}
}
}