-
Notifications
You must be signed in to change notification settings - Fork 127
argparse Autocompleter integration into cmd2 #366
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
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.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Everything looks good to me.
Consider updating the tab_completion.py example, even if it is just to add a comment mentioning that there is a newer and better way of doing things shown in the tab_autocompletion.py example.
| * 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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. |
cmd2/cmd2.py
Outdated
| @@ -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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
cmd2/cmd2.py
Outdated
| 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow, this function had the shortest lifespan of anything I've ever written!!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
cmd2/argparse_completer.py
Outdated
| 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.""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix spelling of "through"
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