Top-level and nested subcommands.
$ welp login --username aanand -p s3cr3t
$ welp things
$ welp things create foo --size 3
$ welp things delete foo
$ welp sleeves unroll
Arguments which can be positional or named. Equivalent:
$ welp things create foo
$ welp things create --name foo
I can probably live without this one.
Optional default sub-sub-commands. Equivalent:
$ welp things
$ welp things ls
Note: optional. Other sub-commands might not have a default - e.g. typing welp sleeves
gets you the sleeves
help banner.
Singular/plural both work. Equivalent:
$ welp thing create
$ welp things create
Global options which can go anywhere. Equivalent:
$ welp --verbose thing create
$ welp thing --verbose create
$ welp thing create --verbose
Help. All of these get you the full, top-level help banner (usage, global options, most common subcommands):
$ welp
$ welp help
$ welp -h
$ welp --help
All of these get you the things
help banner:
$ welp help things
$ welp -h things
$ welp things -h
$ welp --help things
$ welp things --help
welp things help
should probably work too.
Ordered commands in the help banner. I want login
, things
, sleeves
, then help
. Under things
, I want ls
, create
, delete
. Don't sort them alphabetically. You are not helping me.
https://github.com/docopt/docopt
- Highly opinionated. The opinions are mostly good.
- You specify commands/options by writing the help banner. That's cool.
- Subcommands are a massive hack (see https://github.com/docopt/docopt/blob/master/examples/git/git.py).
- Global options are handled differently whether they appear before or after the subcommand name. If they go before, you have to figure out how dispatch them to the subcommand yourself.
- By default,
welp
with no args gets you just the usage pattern, not the full help banner, but this is easy to override.
http://opster.readthedocs.org/
-
Decorator-based.
-
Sorts commands alphabetically in the help banner :(
-
Boilerplate help for the
help
command, both at the top level and under subcommands. Don't know if it's configurable. -
Argument validation is hit and miss. Integer arguments validate nicely, but it seems impossible to mark an argument as required. You have to supply a default value, which is also how you specify the type of the argument.
-
Don't think the named-or-positional-argument thing is going to work.
-
Showstopper bug:
from opster import command, dispatch globaloptions = [ # Uncomment this line to break the login command # (it'll just fail with "invalid arguments", whatever you pass to it) # ('v', 'verbose', False, 'Show more output') ] @command() def login(username=('u', '', 'username to authenticate with'), password=('p', '', 'password to authenticate with')): """Login to welp""" print "login: arguments = (%s, %s)" % (username, password) if __name__ == "__main__": dispatch(globaloptions=globaloptions)
https://cliff.readthedocs.org/
- Highly engineered (
App
,CommandManager
,Command
,InteractiveApp
) - The demo app starts in "interactive mode" if you run
cliffdemo
with no args. Typinghelp
in interactive mode gets you a cryptic message that's not the same one as if you runcliffdemo -h
. What the fuck cliff. - If you run
cliffdemo files -h
, you get the global help message. You have to runcliffdemo help files
to get subcommand help. - The demo app raises an exception if you type an unknown command, or if you type only the first half of a two-word command (what? you want the user to type "show file", but raise an exception if they only type "show"?)