summaryrefslogtreecommitdiff
path: root/cmd2/argparse_completer.py
diff options
context:
space:
mode:
Diffstat (limited to 'cmd2/argparse_completer.py')
-rw-r--r--cmd2/argparse_completer.py49
1 files changed, 34 insertions, 15 deletions
diff --git a/cmd2/argparse_completer.py b/cmd2/argparse_completer.py
index 539132dd..da57a9f9 100644
--- a/cmd2/argparse_completer.py
+++ b/cmd2/argparse_completer.py
@@ -1,6 +1,6 @@
# coding=utf-8
# flake8: noqa C901
-# NOTE: Ignoreing flake8 cyclomatic complexity in this file because the complexity due to copy-and-paste overrides from
+# NOTE: Ignoring flake8 cyclomatic complexity in this file because the complexity due to copy-and-paste overrides from
# argparse
"""
AutoCompleter interprets the argparse.ArgumentParser internals to automatically
@@ -252,29 +252,30 @@ class AutoCompleter(object):
self.needed = False
self.variable = False
- def __init__(self,
- parser: argparse.ArgumentParser,
- cmd2_app,
- token_start_index: int = 1,
+ def __init__(self, parser: argparse.ArgumentParser, cmd2_app, *,
+ tab_for_arg_help: bool = True, token_start_index: int = 1,
arg_choices: Dict[str, Union[List, Tuple, Callable]] = None,
- subcmd_args_lookup: dict = None,
- tab_for_arg_help: bool = True) -> None:
+ subcmd_args_lookup: dict = None, ) -> None:
"""
Create an AutoCompleter
:param parser: ArgumentParser instance
:param cmd2_app: reference to the Cmd2 application. Enables argparse argument completion with class methods
+ :param tab_for_arg_help: Enable of disable argument help when there's no completion result
+
+ # The following parameters are intended for internal use when AutoCompleter creates other AutoCompleters
+ # for subcommands. Developers don't need to worry about overriding these values.
:param token_start_index: index of the token to start parsing at
:param arg_choices: dictionary mapping from argparse argument 'dest' name to list of choices
- :param subcmd_args_lookup: mapping a sub-command group name to a tuple to fill the child\
- AutoCompleter's arg_choices and subcmd_args_lookup parameters
- :param tab_for_arg_help: Enable of disable argument help when there's no completion result
+ :param subcmd_args_lookup: mapping a sub-command group name to a tuple to fill the child
+ AutoCompleter's arg_choices and subcmd_args_lookup parameters
"""
if not subcmd_args_lookup:
subcmd_args_lookup = {}
forward_arg_choices = True
else:
forward_arg_choices = False
+
self._parser = parser
self._cmd2_app = cmd2_app
self._arg_choices = arg_choices.copy() if arg_choices is not None else {}
@@ -285,6 +286,7 @@ class AutoCompleter(object):
self._flags_without_args = [] # all flags that don't take arguments
self._flag_to_action = {} # maps flags to the argparse action object
self._positional_actions = [] # argument names for positional arguments (by position index)
+
# maps action name to sub-command autocompleter:
# action_name -> dict(sub_command -> completer)
self._positional_completers = {}
@@ -295,6 +297,7 @@ class AutoCompleter(object):
# if there are choices defined, record them in the arguments dictionary
if action.choices is not None:
self._arg_choices[action.dest] = action.choices
+
# if completion choices are tagged on the action, record them
elif hasattr(action, ACTION_ARG_CHOICES):
action_arg_choices = getattr(action, ACTION_ARG_CHOICES)
@@ -308,18 +311,30 @@ class AutoCompleter(object):
self._flag_to_action[option] = action
if action.nargs == 0:
self._flags_without_args.append(option)
+
+ # Otherwise this is a positional parameter
else:
self._positional_actions.append(action)
if isinstance(action, argparse._SubParsersAction):
sub_completers = {}
sub_commands = []
- args_for_action = subcmd_args_lookup[action.dest]\
- if action.dest in subcmd_args_lookup else {}
+
+ if action.dest in subcmd_args_lookup:
+ args_for_action = subcmd_args_lookup[action.dest]
+ else:
+ args_for_action = {}
+
+ # Create an AutoCompleter for each subcommand of this command
for subcmd in action.choices:
- (subcmd_args, subcmd_lookup) = args_for_action[subcmd] if \
- subcmd in args_for_action else \
- (arg_choices, subcmd_args_lookup) if forward_arg_choices else ({}, {})
+
+ if subcmd in args_for_action:
+ (subcmd_args, subcmd_lookup) = args_for_action[subcmd]
+ elif forward_arg_choices:
+ subcmd_args, subcmd_lookup = arg_choices, subcmd_args_lookup
+ else:
+ subcmd_args, subcmd_lookup = {}, {}
+
subcmd_start = token_start_index + len(self._positional_actions)
sub_completers[subcmd] = AutoCompleter(action.choices[subcmd],
cmd2_app,
@@ -328,11 +343,15 @@ class AutoCompleter(object):
subcmd_args_lookup=subcmd_lookup,
tab_for_arg_help=tab_for_arg_help)
sub_commands.append(subcmd)
+
self._positional_completers[action.dest] = sub_completers
self._arg_choices[action.dest] = sub_commands
def complete_command(self, tokens: List[str], text: str, line: str, begidx: int, endidx: int) -> List[str]:
"""Complete the command using the argparse metadata and provided argument dictionary"""
+ if not tokens:
+ return []
+
# Count which positional argument index we're at now. Loop through all tokens on the command line so far
# Skip any flags or flag parameter tokens
next_pos_arg_index = 0