Skip to content

Commit

Permalink
Issue click-contrib#68, added support in click's autocompletion
Browse files Browse the repository at this point in the history
  • Loading branch information
Ori Markovitch authored and hany committed Mar 2, 2021
1 parent b0f4a82 commit 05b15d2
Showing 1 changed file with 38 additions and 8 deletions.
46 changes: 38 additions & 8 deletions click_repl/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class ClickExit(RuntimeError):
text_type = str # noqa


__version__ = "0.1.6"
__version__ = "0.1.8"

_internal_commands = dict()

Expand Down Expand Up @@ -83,8 +83,9 @@ def _help_internal():


class ClickCompleter(Completer):
def __init__(self, cli, styles=None):
def __init__(self, cli, styles=None, ctx=None):
self.cli = cli
self.ctx = ctx
self.styles = styles if styles is not None else {
'command': '',
'argument': '',
Expand Down Expand Up @@ -113,26 +114,52 @@ def get_completions(self, document, complete_event=None):
# command, so give all relevant completions for this context.
incomplete = ""

ctx = click._bashcomplete.resolve_ctx(self.cli, "", args)
ctx = click._bashcomplete.resolve_ctx(self.cli, "", list(args))
if ctx is None:
return

choices = []
param_choices = []
param_called = False
autocomplete_ctx = self.ctx or ctx
for param in ctx.command.params:
if isinstance(param, click.Option):
for options in (param.opts, param.secondary_opts):
possible_options = (param.opts, param.secondary_opts)
for options in possible_options:
for o in options:
choices.append(
Completion(
text_type(o), -len(incomplete), display_meta=param.help,
style=self.styles['option']
)
)
# We want to make sure if this parameter was called
if o in args[param.nargs * -1:]:
param_called = True
if param_called and hasattr(param, "autocompletion") and param.autocompletion is not None:
for autocomplete in param.autocompletion(autocomplete_ctx, args, incomplete):
if isinstance(autocomplete, tuple):
param_choices.append(Completion(
text_type(autocomplete[0]), -len(incomplete),
display_meta=autocomplete[1]
))
else:
param_choices.append(Completion(text_type(autocomplete), -len(incomplete)))

elif isinstance(param, click.Argument):
if isinstance(param.type, click.Choice):
for choice in param.type.choices:
choices.append(Completion(text_type(choice), -len(incomplete),
style=self.styles['argument']))
if hasattr(param, "autocompletion") and param.autocompletion is not None:
for autocomplete in param.autocompletion(autocomplete_ctx, args, incomplete):
if isinstance(autocomplete, tuple):
choices.append(Completion(
text_type(autocomplete[0]), -len(incomplete),
display_meta=autocomplete[1]
))
else:
choices.append(Completion(text_type(autocomplete), -len(incomplete)))

if isinstance(ctx.command, click.MultiCommand):
for name in ctx.command.list_commands(ctx):
Expand All @@ -146,12 +173,16 @@ def get_completions(self, document, complete_event=None):
)
)

# If we are inside a parameter that was called, we want to show only
# relevant choices
if param_called:
choices = param_choices
for item in choices:
if item.text.startswith(incomplete):
yield item


def bootstrap_prompt(prompt_kwargs, group, styles=None):
def bootstrap_prompt(prompt_kwargs, group, styles=None, ctx=None):
"""
Bootstrap prompt_toolkit kwargs or use user defined values.
Expand All @@ -162,7 +193,7 @@ def bootstrap_prompt(prompt_kwargs, group, styles=None):

defaults = {
"history": InMemoryHistory(),
"completer": ClickCompleter(group, styles),
"completer": ClickCompleter(group, styles, ctx=ctx),
"message": u"> ",
}

Expand Down Expand Up @@ -219,7 +250,7 @@ def repl( # noqa: C901
available_commands = group_ctx.command.commands
available_commands.pop(repl_command_name, None)

prompt_kwargs = bootstrap_prompt(prompt_kwargs, group, styles)
prompt_kwargs = bootstrap_prompt(prompt_kwargs, group, styles, ctx=group_ctx)

if isatty:

Expand Down Expand Up @@ -308,4 +339,3 @@ def handle_internal_commands(command):
target = _get_registered_target(command[1:], default=None)
if target:
return target()

0 comments on commit 05b15d2

Please sign in to comment.