From 16764c79b2875dc14a447ad9b35bcdfccc2ebfe3 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 23 Aug 2018 15:02:03 +0530 Subject: [PATCH] Start work on completion for the kitty command --- completion/zsh/_kitty | 9 +++++ kitty/cli.py | 4 ++ kitty/complete.py | 91 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+) create mode 100644 completion/zsh/_kitty create mode 100644 kitty/complete.py diff --git a/completion/zsh/_kitty b/completion/zsh/_kitty new file mode 100644 index 000000000..a363b0da1 --- /dev/null +++ b/completion/zsh/_kitty @@ -0,0 +1,9 @@ +#compdef kitty + +_kitty() { + local src + src=$(printf "%s\n" "${words[@]}" | kitty +complete zsh) + if [[ $? == 0 ]]; then + eval ${src} + fi +} diff --git a/kitty/cli.py b/kitty/cli.py index 44dd62325..5deb61e4f 100644 --- a/kitty/cli.py +++ b/kitty/cli.py @@ -599,6 +599,10 @@ def options_spec(): return options_spec.ans +def options_for_completion(): + return parse_option_spec(options_spec())[0] + + def option_spec_as_rst(ospec=options_spec, usage=None, message=None, appname=None, heading_char='-'): options = parse_option_spec(ospec()) seq, disabled = options diff --git a/kitty/complete.py b/kitty/complete.py new file mode 100644 index 000000000..32e03264c --- /dev/null +++ b/kitty/complete.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python +# vim:fileencoding=utf-8 +# License: GPLv3 Copyright: 2018, Kovid Goyal + +import shlex +import sys + +parsers, serializers = {}, {} + + +class Completions: + + def __init__(self, description=None): + self.matches = {} + self.description = description + + +def input_parser(func): + name = func.__name__.split('_')[0] + parsers[name] = func + return func + + +def output_serializer(func): + name = func.__name__.split('_')[0] + serializers[name] = func + return func + + +@input_parser +def zsh_input_parser(data): + new_word = data.endswith('\n\n') + words = data.rstrip().splitlines() + return words, new_word + + +@output_serializer +def zsh_output_serializer(ans): + output = ['compadd', '--'] + for word, description in ans.matches.items(): + output.append(shlex.quote(word)) + return ' '.join(output) + + +def completions_for_first_word(ans, prefix, entry_points, namespaced_entry_points): + ans.matches.update({ + k: None for k in + list(entry_points) + ['+' + k for k in namespaced_entry_points] + if not prefix or k.startswith(prefix) + }) + + +def kitty_cli_opts(prefix=None): + from kitty.cli import options_for_completion + ans = {} + for opt in options_for_completion(): + if isinstance(opt, str): + continue + aliases = frozenset(x for x in opt['aliases'] if x.startswith(prefix)) if prefix else opt['aliases'] + for alias in aliases: + ans[alias] = opt['help'].strip() + return ans + + +def find_completions(words, new_word, entry_points, namespaced_entry_points): + ans = Completions() + if not words or words[0] != 'kitty': + return ans + words = words[1:] + if not words or (len(words) == 1 and not new_word): + prefix = words[0] if words else '' + completions_for_first_word(ans, prefix, entry_points, namespaced_entry_points) + ans.matches.update(kitty_cli_opts(prefix)) + return ans + + return ans + + +def main(args, entry_points, namespaced_entry_points): + if not args: + raise SystemExit('Must specify completion style') + cstyle = args[0] + data = sys.stdin.read() + try: + parser = parsers[cstyle] + serializer = serializers[cstyle] + except KeyError: + raise SystemExit('Unknown completion style: {}'.format(cstyle)) + words, new_word = parser(data) + ans = find_completions(words, new_word, entry_points, namespaced_entry_points) + print(serializer(ans), end='')