diff options
-rwxr-xr-x | cmd2.py | 22 | ||||
-rwxr-xr-x | examples/subcommands.py | 58 |
2 files changed, 78 insertions, 2 deletions
@@ -292,7 +292,12 @@ def with_argparser_and_unknown_args(argparser): argparser.description = func.__doc__ cmd_wrapper.__doc__ = argparser.format_help() + + # Mark this function as having an argparse ArgumentParser (used by do_help) + cmd_wrapper.__dict__['has_parser'] = True + return cmd_wrapper + return arg_decorator @@ -316,7 +321,12 @@ def with_argument_parser(argparser): argparser.description = func.__doc__ cmd_wrapper.__doc__ = argparser.format_help() + + # Mark this function as having an argparse ArgumentParser (used by do_help) + cmd_wrapper.__dict__['has_parser'] = True + return cmd_wrapper + return arg_decorator @@ -1198,8 +1208,16 @@ class Cmd(cmd.Cmd): # Getting help for a specific command funcname = self._func_named(arglist[0]) if funcname: - # No special behavior needed, delegate to cmd base class do_help() - cmd.Cmd.do_help(self, funcname[3:]) + # Check to see if this function was decorated with an argparse ArgumentParser + func = getattr(self, funcname) + if func.__dict__.get('has_parser', False): + # Function has an argparser, so get help based on all the arguments in case there are sub-commands + new_arglist = arglist[1:] + new_arglist.append('-h') + func(new_arglist) + else: + # No special behavior needed, delegate to cmd base class do_help() + cmd.Cmd.do_help(self, funcname[3:]) else: # Show a menu of what commands help can be gotten for self._help_menu() diff --git a/examples/subcommands.py b/examples/subcommands.py new file mode 100755 index 00000000..347cb61d --- /dev/null +++ b/examples/subcommands.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python +# coding=utf-8 +"""A simple example demonstrating how to use Argparse to support sub-commands. + + +This example shows an easy way for a single command to have many subcommands, each of which takes different arguments +and provides separate contextual help. +""" +import argparse + +import cmd2 +from cmd2 import with_argument_parser + + +class SubcommandsExample(cmd2.Cmd): + """ Example cmd2 application where we a base command which has a couple subcommands.""" + + def __init__(self): + cmd2.Cmd.__init__(self) + + # sub-command functions for the base command + def foo(self, args): + """foo subcommand of base command""" + print(args.x * args.y) + + def bar(self, args): + """bar sucommand of base command""" + print('((%s))' % args.z) + + # create the top-level parser + base_parser = argparse.ArgumentParser(prog='base') + base_subparsers = base_parser.add_subparsers(title='subcommands', help='subcommand help') + + # create the parser for the "foo" command + parser_foo = base_subparsers.add_parser('foo', help='foo help') + parser_foo.add_argument('-x', type=int, default=1, help='integer') + parser_foo.add_argument('y', type=float, help='float') + parser_foo.set_defaults(func=foo) + + # create the parser for the "bar" command + parser_bar = base_subparsers.add_parser('bar', help='bar help') + parser_bar.add_argument('z', help='string') + parser_bar.set_defaults(func=bar) + + @with_argument_parser(base_parser) + def do_base(self, args): + """Base command help""" + try: + # Call whatever sub-command function was selected + args.func(self, args) + except AttributeError: + # No sub-command was provided, so as called + self.do_help('base') + + +if __name__ == '__main__': + app = SubcommandsExample() + app.cmdloop() |