argparse Autocompleter integration into cmd2#366
Conversation
…s. Not all tests are passing yet.
…e AutoCompleter by default.
Codecov Report
@@ Coverage Diff @@
## master #366 +/- ##
=========================================
- Coverage 91.23% 91.1% -0.14%
=========================================
Files 3 3
Lines 2271 2236 -35
=========================================
- Hits 2072 2037 -35
Misses 199 199
Continue to review full report at Codecov.
|
| * All ``cmd2`` code should be ported to use the new ``argparse``-based decorators | ||
| * See the [Argument Processing](http://cmd2.readthedocs.io/en/latest/argument_processing.html) section of the documentation for more information on these decorators | ||
| * Alternatively, see the [argparse_example.py](https://github.com/python-cmd2/cmd2/blob/master/examples/argparse_example.py) | ||
| * Deleted ``cmd_with_subs_completer``, ``get_subcommands``, and ``get_subcommand_completer`` |
There was a problem hiding this comment.
I like this. It makes it easier for the vast majority of cases.
| Also, a convenience function called ``cmd_with_subs_completer`` is available to easily add tab completion to functions | ||
| that implement subcommands. By setting this as the completer of the base command function, the correct completer for | ||
| the chosen subcommand will be called. | ||
| You may add multiple layers of sub-commands for your command. Cmd2 will automatically traverse and tab-complete |
There was a problem hiding this comment.
Thanks for updating the docs
| parser_bar.add_argument('z', help='string') | ||
| parser_bar.set_defaults(func=base_bar) | ||
|
|
||
| bar_subparsers = parser_bar.add_subparsers(title='layer3', help='help for 3rd layer of commands') |
There was a problem hiding this comment.
And thanks for updating the relevant examples
|
@kmvanbrunt If you aren't too busy I would appreciate your review of this one since you are much more familiar with the idiosyncrasies of readline tab completion than I am. |
| @@ -268,21 +269,7 @@ def cmd_wrapper(instance, cmdline): | |||
|
|
|||
| # Mark this function as having an argparse ArgumentParser (used by do_help) | |||
There was a problem hiding this comment.
Since this isn't just used by do_help anymore, maybe update this comment to say something like "Used to tab complete this command and its subcommands"
This comment appears twice in the file so update both.
| compfunc = functools.partial(self._autocomplete_default, | ||
| argparser=argparser) | ||
| else: | ||
| compfunc = self.completedefault |
There was a problem hiding this comment.
Can has_parser ever be False if the command uses argparse? If not, can that attribute be removed and this code simplified to be:
try:
compfunc = getattr(self, 'complete_' + command)
except AttributeError:
# There's no completer function, next see if we should switch to the default argparse completer
try:
cmd_func = getattr(self, 'do_' + command)
argparser = getattr(cmd_func, 'argparser')
compfunc = functools.partial(self._autocomplete_default, argparser=argparser)
except AttributeError:
compfunc = self.completedefault| cmd_func = getattr(self, 'do_' + command) | ||
| parser = getattr(cmd_func, 'argparser') | ||
| completer = AutoCompleter(parser) | ||
| matches = completer.complete_command_help(tokens[1:], text, line, begidx, endidx) |
There was a problem hiding this comment.
Assuming has_parser can be removed since it appears to always be True in an argparse command, simplify the code to something like
elif index >= subcmd_index:
# If this command uses an argparser, then complete its subcommands if any exist
try:
cmd_func = getattr(self, 'do_' + tokens[cmd_index])
parser = getattr(cmd_func, 'argparser')
completer = AutoCompleter(parser)
matches = completer.complete_command_help(tokens[cmd_index:], text, line, begidx, endidx)
except AttributeError:
pass| index_dict = {1: self.shell_cmd_complete} | ||
| return self.index_based_complete(text, line, begidx, endidx, index_dict, self.path_complete) | ||
|
|
||
| def cmd_with_subs_completer(self, text, line, begidx, endidx): |
There was a problem hiding this comment.
Wow, this function had the shortest lifespan of anything I've ever written!!
There was a problem hiding this comment.
If it makes you feel any better - with the revelation that I can just tag the completer on each argparse argument action object I think can remove all of the complicated nested dictionary stuff that I did to pass that over to the AutoCompleter.
| return completion_results | ||
|
|
||
| def complete_command_help(self, tokens: List[str], text: str, line: str, begidx: int, endidx: int) -> List[str]: | ||
| """Supports the completion of sub-commands for commands thhrough the cmd2 help command.""" |
If a command uses argparse and doesn't define a completion function, cmd2 now provides a default implementation that uses AutoCompleter.
Added support for decorating individual argparse actions with a completion collection or function. This should make it unnecessary to implement a completion function if a command uses argparse.
This closes #349