summaryrefslogtreecommitdiff
path: root/cmd2
diff options
context:
space:
mode:
Diffstat (limited to 'cmd2')
-rw-r--r--cmd2/argparse_completer.py50
-rw-r--r--cmd2/cmd2.py27
2 files changed, 37 insertions, 40 deletions
diff --git a/cmd2/argparse_completer.py b/cmd2/argparse_completer.py
index ac65185b..edfaeec4 100644
--- a/cmd2/argparse_completer.py
+++ b/cmd2/argparse_completer.py
@@ -667,7 +667,7 @@ class AutoCompleter(object):
if callable(arg_choices[0]):
completer = arg_choices[0]
- elif isinstance(arg_choices[0], str) and callable(getattr(self._cmd2_app, arg_choices[0])):
+ else:
completer = getattr(self._cmd2_app, arg_choices[0])
# extract the positional and keyword arguments from the tuple
@@ -678,19 +678,16 @@ class AutoCompleter(object):
list_args = arg_choices[index]
elif isinstance(arg_choices[index], dict):
kw_args = arg_choices[index]
- try:
- # call the provided function differently depending on the provided positional and keyword arguments
- if list_args is not None and kw_args is not None:
- return completer(text, line, begidx, endidx, *list_args, **kw_args)
- elif list_args is not None:
- return completer(text, line, begidx, endidx, *list_args)
- elif kw_args is not None:
- return completer(text, line, begidx, endidx, **kw_args)
- else:
- return completer(text, line, begidx, endidx)
- except TypeError:
- # assume this is due to an incorrect function signature, return nothing.
- return []
+
+ # call the provided function differently depending on the provided positional and keyword arguments
+ if list_args is not None and kw_args is not None:
+ return completer(text, line, begidx, endidx, *list_args, **kw_args)
+ elif list_args is not None:
+ return completer(text, line, begidx, endidx, *list_args)
+ elif kw_args is not None:
+ return completer(text, line, begidx, endidx, **kw_args)
+ else:
+ return completer(text, line, begidx, endidx)
else:
return self._cmd2_app.basic_complete(text, line, begidx, endidx,
self._resolve_choices_for_arg(action, used_values))
@@ -704,32 +701,17 @@ class AutoCompleter(object):
# is the argument a string? If so, see if we can find an attribute in the
# application matching the string.
if isinstance(args, str):
- try:
- args = getattr(self._cmd2_app, args)
- except AttributeError:
- # Couldn't find anything matching the name
- return []
+ args = getattr(self._cmd2_app, args)
# is the provided argument a callable. If so, call it
if callable(args):
try:
- try:
- args = args(self._cmd2_app)
- except TypeError:
- args = args()
+ args = args(self._cmd2_app)
except TypeError:
- return []
-
- try:
- iter(args)
- except TypeError:
- pass
- else:
- # filter out arguments we already used
- args = [arg for arg in args if arg not in used_values]
+ args = args()
- if len(args) > 0:
- return args
+ # filter out arguments we already used
+ return [arg for arg in args if arg not in used_values]
return []
diff --git a/cmd2/cmd2.py b/cmd2/cmd2.py
index a7b60b1a..3c1c8d2c 100644
--- a/cmd2/cmd2.py
+++ b/cmd2/cmd2.py
@@ -1362,16 +1362,13 @@ class Cmd(cmd.Cmd):
# Display matches using actual display function. This also redraws the prompt and line.
orig_pyreadline_display(matches_to_display)
- # ----- Methods which override stuff in cmd -----
-
- def complete(self, text: str, state: int) -> Optional[str]:
- """Override of command method which returns the next possible completion for 'text'.
+ def _complete_worker(self, text: str, state: int) -> Optional[str]:
+ """The actual worker function for tab completion which is called by complete() and returns
+ the next possible completion for 'text'.
If a command has not been entered, then complete against command list.
Otherwise try to call complete_<command> to get list of completions.
- This method gets called directly by readline because it is set as the tab-completion function.
-
This completer function is called as complete(text, state), for state in 0, 1, 2, …, until it returns a
non-string value. It should return the next possible completion starting with text.
@@ -1581,6 +1578,24 @@ class Cmd(cmd.Cmd):
except IndexError:
return None
+ def complete(self, text: str, state: int) -> Optional[str]:
+ """Override of cmd2's complete method which returns the next possible completion for 'text'
+
+ This method gets called directly by readline. Since readline suppresses any exception raised
+ in completer functions, they can be difficult to debug. Therefore this function wraps the
+ actual tab completion logic and prints to stderr any exception that occurs before returning
+ control to readline.
+
+ :param text: the current word that user is typing
+ :param state: non-negative integer
+ """
+ # noinspection PyBroadException
+ try:
+ return self._complete_worker(text, state)
+ except Exception as e:
+ self.perror(e)
+ return None
+
def _autocomplete_default(self, text: str, line: str, begidx: int, endidx: int,
argparser: argparse.ArgumentParser) -> List[str]:
"""Default completion function for argparse commands."""