cmd2
cmd2 copied to clipboard
Document use of docopt-based parser for option processing
Hi, I like to use docopt for simple scripts. I wrote an integration with Cmd2 yearas ago and have been using it at work. I only noticed recently that there is an argparser integration in Cmd2 and then led me to search for something that converts docopt to argparser and that led me to argopt.
This allows you to write Cmd2 commands with usage-style docstrings and all the completion stuff etc just works.
@hasdocopt
def do_banana(self, opts):
'''Example programme description.
You should be able to do
args = argopt(__doc__).parse_args()
instead of
args = docopt(__doc__)
Usage:
banana [options] <x> [<y>...]
Arguments:
<x> A file.
--anarg=<a> Description here [default: 1e3:int].
-p PAT, --patts PAT Or [default: None:file].
--bar=<b> Another [default: something] should
auto-wrap something in quotes and assume str.
-f, --force Force.
'''
The implementation of the decorator is very straightforward
from argopt import argopt
def hasdocopt(f, *args, **kwargs):
parser=argopt(f.__doc__)
return with_argparser(parser)(f)
I have not tested this extensively but I was kind of surprised that it seems to work so well. I wanted to share the results here. Perhaps the recipe could be added to the documentation if you think it may be useful to others.
@phrrngtn This looks pretty great. Will have to play with this some and see how it goes. Does docopt allow sub-commands like argparse?
@jayrod You might like this too
No, I don't think docopt does but I did a quick search and found this https://github.com/abingham/docopt-subcommand which claims to support it.
I am not a huge fan of subcommands myself, so I tended to run a new nested Cmd2 for the odd time I wanted subcommands:
def do_maintenance(self, argstr):
c = Maintenance()
c.engine = self.engine
c.cmdloop()
This creates a top-level command, maintenance
, that drops down into a Cmd2 subclass with all my maintenance commands in there. In general, this kind of things was used to bump up the logging, enables some potentially dangerous commands etc.
In any case, I find the clarity of "usage message first" authoring of options to be a sufficient win for the reduction in expressive power of rolling the argparser by hand. There is something about seeing them all there together in a single block of text that enables me to think of the options as a set and see how the individual elements relate to each other. I have to admit that I rarely -- if ever -- refactor command signatures that are expressed in a non-declarative way. YMMV.
@phrrngtn Documenting this in an example would be useful. Please feel free to submit a PR to add an appropriate example.
Will do. I have not been doing anything other than dayjob for several months so it may be some time.
I'm going to close this. But @phrrngtn we would be very happy to accept a PR that adds and example to document this use case.