summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd2/argparse_completer.py56
-rw-r--r--cmd2/argparse_custom.py99
2 files changed, 101 insertions, 54 deletions
diff --git a/cmd2/argparse_completer.py b/cmd2/argparse_completer.py
index 1393db0e..579d8029 100644
--- a/cmd2/argparse_completer.py
+++ b/cmd2/argparse_completer.py
@@ -2,60 +2,8 @@
# flake8: noqa C901
# NOTE: Ignoring flake8 cyclomatic complexity in this file
"""
-This module adds tab completion to argparse parsers within cmd2 apps.
-
-AutoCompleter interprets the argparse.ArgumentParser internals to automatically
-generate the completion options for each argument.
-
-How to supply completion options for each argument:
- argparse Choices
- - pass a list of values to the choices parameter of an argparse argument.
- ex: parser.add_argument('-o', '--options', dest='options', choices=['An Option', 'SomeOtherOption'])
-
- arg_choices dictionary lookup
- arg_choices is a dict() mapping from argument name to one of 3 possible values:
- ex:
- parser = argparse.ArgumentParser()
- parser.add_argument('-o', '--options', dest='options')
- choices = {}
- mycompleter = AutoCompleter(parser, cmd2_app, completer, 1, choices)
-
- - static list - provide a static list for each argument name
- ex:
- choices['options'] = ['An Option', 'SomeOtherOption']
-
- - choices function - provide a function that returns a list for each argument name
- ex:
- def generate_choices():
- return ['An Option', 'SomeOtherOption']
- choices['options'] = generate_choices
-
- - custom completer function - provide a completer function that will return the list
- of completion arguments
- ex 1:
- def my_completer(text: str, line: str, begidx: int, endidx:int):
- my_choices = [...]
- return my_choices
- choices['options'] = (my_completer)
- ex 2:
- def my_completer(text: str, line: str, begidx: int, endidx:int, extra_param: str, another: int):
- my_choices = [...]
- return my_choices
- completer_params = {'extra_param': 'my extra', 'another': 5}
- choices['options'] = (my_completer, completer_params)
-
-How to supply completion choice lists or functions for sub-commands:
- subcmd_args_lookup is used to supply a unique pair of arg_choices and subcmd_args_lookup
- for each sub-command in an argparser subparser group.
- This requires your subparser group to be named with the dest parameter
- ex:
- parser = ArgumentParser()
- subparsers = parser.add_subparsers(title='Actions', dest='action')
-
- subcmd_args_lookup maps a named subparser group to a subcommand group dictionary
- The subcommand group dictionary maps subcommand names to tuple(arg_choices, subcmd_args_lookup)
-
- For more details of this more complex approach see tab_autocompletion.py in the examples
+This module defines the AutoCompleter class which provides argparse-based tab completion to cmd2 apps.
+See the header of argparse_custom.py for instructions on how to use these features.
"""
import argparse
diff --git a/cmd2/argparse_custom.py b/cmd2/argparse_custom.py
index 5e3ed7f5..342360ae 100644
--- a/cmd2/argparse_custom.py
+++ b/cmd2/argparse_custom.py
@@ -1,4 +1,103 @@
# coding=utf-8
+"""
+This module adds capabilities to argparse by patching a few of its functions. It also defines a parser
+class called Cmd2ArgParser which improves error and help output over normal argparse. All cmd2 code uses
+this parser and it is recommended that developers of cmd2-based apps either use it or write their own parser
+that inherits from it. This will give a consistent look-and-feel between the help/error output of built-in
+cmd2 commands and the app-specific commands.
+
+Since the new capabilities are added by patching at the argparse API level, they are available whether or
+not Cmd2ArgParser is used. However, the help output of Cmd2ArgParser is customized to notate nargs ranges
+whereas any other parser class won't be as explicit in the usage statement.
+
+############################################################################################################
+# Added capabilities
+############################################################################################################
+
+Extends argparse nargs functionality by allowing tuples which specify a range (min, max)
+ Example:
+ The following command says the -f argument expects between 3 and 5 values (inclusive)
+ parser.add_argument('-f', nargs=(3, 5))
+
+Tab Completion:
+ cmd2 uses its AutoCompleter class to enable argparse-based tab completion on all commands that use the
+ @with_argparse wrappers. Out of the box you get tab completion of commands, sub-commands, and flag names,
+ as well as instructive hints about the current argument that print when tab is pressed. In addition,
+ you can add tab completion for each argument's values using parameters passed to add_argument().
+
+ Below are the 5 add_argument() parameters for enabling tab completion of an argument's value. Only one
+ can be used at a time.
+
+ choices
+ Pass a list of values to the choices parameter.
+ Example:
+ parser.add_argument('-o', '--options', choices=['An Option', 'SomeOtherOption'])
+ parser.add_argument('-o', '--options', choices=my_list)
+
+ choices_function
+ Pass a function that returns choices. This is good in cases where the choice list is dynamically
+ generated when the user hits tab.
+
+ Example:
+ def my_choices_function):
+ ...
+ return my_generated_list
+
+ parser.add_argument('-o', '--options', choices_function=my_choices_function)
+
+ choices_method
+ This is exactly like choices_function, but the function needs to be an instance method of a cmd2-based class.
+ When AutoCompleter calls the method, it will pass the app instance as the self argument. This is good in
+ cases where the list of choices being generated relies on state data of the cmd2-based app
+
+ Example:
+ def my_choices_method(self):
+ ...
+ return my_generated_list
+
+ completer_function
+ Pass a tab-completion function that does custom completion. Since custom tab completion operations commonly
+ need to modify cmd2's instance variables related to tab-completion, it will be rare to need a completer
+ function. completer_method should be used in those cases.
+
+ Example:
+ def my_completer_function(text, line, begidx, endidx):
+ ...
+ return completions
+ parser.add_argument('-o', '--options', completer_function=my_completer_function)
+
+ completer_method
+ This is exactly like completer_function, but the function needs to be an instance method of a cmd2-based class.
+ When AutoCompleter calls the method, it will pass the app instance as the self argument. cmd2 provides
+ a few completer methods for convenience (e.g. path_complete, delimiter_complete)
+
+ Example:
+ This adds file-path completion to an argument
+ parser.add_argument('-o', '--options', completer_method=cmd2.Cmd.path_complete)
+
+
+ In all cases in which function/methods are passed you can use functools.partial() to prepopulate
+ values of the underlying function.
+
+ Example:
+ This says to call path_complete with a preset value for its path_filter argument.
+ completer_method = functools.partial(path_complete,
+ path_filter=lambda path: os.path.isdir(path))
+ parser.add_argument('-o', '--options', choices_method=completer_method)
+
+############################################################################################################
+# Patched argparse functions:
+###########################################################################################################
+argparse._ActionsContainer.add_argument - adds arguments related to tab completion and enables nargs range parsing
+ See _add_argument_wrapper for more details on these argument
+
+argparse.ArgumentParser._get_nargs_pattern - adds support to for nargs ranges
+ See _get_nargs_pattern_wrapper for more details
+
+argparse.ArgumentParser._match_argument - adds support to for nargs ranges
+ See _match_argument_wrapper for more details
+"""
+
import argparse
import re as _re
import sys