summaryrefslogtreecommitdiff
path: root/cmd2/argparse_completer.py
diff options
context:
space:
mode:
authorKevin Van Brunt <kmvanbrunt@gmail.com>2019-07-08 16:16:32 -0400
committerKevin Van Brunt <kmvanbrunt@gmail.com>2019-07-08 16:16:32 -0400
commit9e49b7eb70b715f8adc06748a73caa5a0fafd065 (patch)
treebc2118d80be2ac48351df9d402272b92c2803038 /cmd2/argparse_completer.py
parent36209ae6d9563054d57c630729be3c9002453729 (diff)
downloadcmd2-git-9e49b7eb70b715f8adc06748a73caa5a0fafd065.tar.gz
Resetting consumed arguments list each time a flag is used
Started adding AutoCompleter unit tests for nargs.
Diffstat (limited to 'cmd2/argparse_completer.py')
-rw-r--r--cmd2/argparse_completer.py72
1 files changed, 40 insertions, 32 deletions
diff --git a/cmd2/argparse_completer.py b/cmd2/argparse_completer.py
index 6fef6f80..9f497ca8 100644
--- a/cmd2/argparse_completer.py
+++ b/cmd2/argparse_completer.py
@@ -227,6 +227,7 @@ class AutoCompleter(object):
# does this complete an option item for the flag
arg_choices = self._resolve_choices_for_arg(flag_action)
+
# if the current token matches the current flag's autocomplete argument list,
# track that we've used it already. Unless this is the current token, then keep it.
if not is_last_token and token in arg_choices:
@@ -239,42 +240,45 @@ class AutoCompleter(object):
# does this complete an option item for the positional
arg_choices = self._resolve_choices_for_arg(pos_action)
+
# if the current token matches the current position's autocomplete argument list,
# track that we've used it already. Unless this is the current token, then keep it.
if not is_last_token and token in arg_choices:
consumed_arg_values.setdefault(pos_action.dest, [])
consumed_arg_values[pos_action.dest].append(token)
- def process_action_nargs(arg_action: argparse.Action, arg_state: AutoCompleter._ArgumentState) -> None:
- """Process the current argparse Action and initialize the ArgumentState object used
- to track what arguments we have processed for this action"""
+ def process_argument_nargs(arg_action: argparse.Action, arg_state: AutoCompleter._ArgumentState) -> None:
+ """Use argument's nargs value to set related values in its ArgumentState object"""
+
+ # Check if nargs is a range
nargs_range = getattr(arg_action, ATTR_NARGS_RANGE, None)
if nargs_range is not None:
arg_state.min = nargs_range[0]
arg_state.max = nargs_range[1]
arg_state.variable = True
- if arg_state.min is None or arg_state.max is None:
- if arg_action.nargs is None:
- arg_state.min = 1
- arg_state.max = 1
- elif arg_action.nargs == argparse.ONE_OR_MORE:
- arg_state.min = 1
- arg_state.max = float('inf')
- arg_state.variable = True
- elif arg_action.nargs == argparse.ZERO_OR_MORE or arg_action.nargs == argparse.REMAINDER:
- arg_state.min = 0
- arg_state.max = float('inf')
- arg_state.variable = True
- if arg_action.nargs == argparse.REMAINDER:
- remainder['action'] = arg_action
- remainder['arg'] = arg_state
- elif arg_action.nargs == argparse.OPTIONAL:
- arg_state.min = 0
- arg_state.max = 1
- arg_state.variable = True
- else:
- arg_state.min = arg_action.nargs
- arg_state.max = arg_action.nargs
+
+ # Otherwise check against argparse types
+ elif arg_action.nargs is None:
+ arg_state.min = 1
+ arg_state.max = 1
+ elif arg_action.nargs == argparse.ONE_OR_MORE:
+ arg_state.min = 1
+ arg_state.max = float('inf')
+ arg_state.variable = True
+ elif arg_action.nargs == argparse.ZERO_OR_MORE or arg_action.nargs == argparse.REMAINDER:
+ arg_state.min = 0
+ arg_state.max = float('inf')
+ arg_state.variable = True
+ if arg_action.nargs == argparse.REMAINDER:
+ remainder['action'] = arg_action
+ remainder['arg'] = arg_state
+ elif arg_action.nargs == argparse.OPTIONAL:
+ arg_state.min = 0
+ arg_state.max = 1
+ arg_state.variable = True
+ else:
+ arg_state.min = arg_action.nargs
+ arg_state.max = arg_action.nargs
# This next block of processing tries to parse all parameters before the last parameter.
# We're trying to determine what specific argument the current cursor position should be
@@ -333,6 +337,7 @@ class AutoCompleter(object):
elif is_potential_flag(token, self._parser) and not skip_remaining_flags:
# reset some tracking values
flag_arg.reset()
+
# don't reset positional tracking because flags can be interspersed anywhere between positionals
flag_action = None
@@ -345,8 +350,11 @@ class AutoCompleter(object):
flag_action = self._flag_to_action[candidates_flags[0]]
if flag_action is not None:
- # resolve argument counts
- process_action_nargs(flag_action, flag_arg)
+ process_argument_nargs(flag_action, flag_arg)
+
+ # It's possible we already have consumed values for this flag if it was used earlier
+ # in the command line. Reset them now for this use of the flag.
+ consumed_arg_values[flag_action.dest] = []
# Keep track of what flags have already been used
# Flags with action set to append, append_const, and count can be reused
@@ -389,7 +397,7 @@ class AutoCompleter(object):
return sub_completers[token].complete_command(tokens, text, line,
begidx, endidx)
pos_action = action
- process_action_nargs(pos_action, pos_arg)
+ process_argument_nargs(pos_action, pos_arg)
consume_positional_argument()
elif not is_last_token and pos_arg.max is not None:
@@ -434,8 +442,8 @@ class AutoCompleter(object):
# we're not at a positional argument, see if we're in a flag argument
if not current_is_positional:
if flag_action is not None:
- consumed = consumed_arg_values[flag_action.dest]\
- if flag_action.dest in consumed_arg_values else []
+ consumed = consumed_arg_values[flag_action.dest] if flag_action.dest in consumed_arg_values else []
+
completion_results = self._complete_for_arg(flag_action, text, line, begidx, endidx, consumed)
if not completion_results:
self._print_arg_hint(flag_action)
@@ -445,8 +453,8 @@ class AutoCompleter(object):
# ok, we're not a flag, see if there's a positional argument to complete
else:
if pos_action is not None:
- pos_name = pos_action.dest
- consumed = consumed_arg_values[pos_name] if pos_name in consumed_arg_values else []
+ consumed = consumed_arg_values[pos_action.dest] if pos_action.dest in consumed_arg_values else []
+
completion_results = self._complete_for_arg(pos_action, text, line, begidx, endidx, consumed)
if not completion_results:
self._print_arg_hint(pos_action)