What is your most used key on the command line?
Or: Why does writing command line apps still require so much work?
My answer to the first question would probably be: TAB. (Especially since I switched to zsh ~2 years ago.)
But more about that later. This is simply one of the reasons I started this project.
The ProblemWhen you start a command line tool you probably add Getopt::* as soon as you need options. Maybe Getopt::Long::Descriptive, so you can get a usage output. There's also App::Cmd, MooseX::App, MooseX::App::Cmd, MouseX::App::Cmd, MooX::Cmd and possibly more. Some can't do nested subcommands; they all look and work a bit different. Shell completion just exists for some and would have to be implemented for every single module.
And in the end you have to know about all, since you might work on projects from somebody else.
What they all do is create a commandline app from a specification, but the way you describe it is very different, although the basic concepts have a lot in common.
To get the specification of a tool, you have to run it. So the code for creating completion or usage, for example, has to be written for each of them. And the same for tools written in other languages.
A possible solution or just another reinvention of the wheel?
When I was working on an app which had subcommands and options generated automatically from another source, I had the option of generating a bunch of MooseX::App classes, which would still be lacking things I wanted. Better parameter validation, better completion, ...
So I thought of creating an intermediate format, a specification in text form. This resulted in Just Another Command Line Framwork, which I gave the boring but short name:
App::Spec is the class for representing the specification in perl, App::Spec::Run is the class you should inherit from which runs the actual app.
This is still a draft and I'm glad for any suggestions/wishes which help me to decide if it's worth, and about the necessary specification schema.
The features I want (some are roughly implemented):
- Have a specification file (currently in YAML) for your app which defines as much as possible
- Subcommands (nested), options, parameters
- A Perl 5 (and possibly other) app framework that calls the specified method, validates options and parameters, and generates help and usage error output.
- Create pod and man pages
- Create completion for bash and zsh which features completion of subcommands, options, option values, parameters, and dynamic value completion read from external commands
- A specification which also can be used for tools you only use, tools in other languages, for which you want to have (better) shell completion, generating a man page, or anything crazy which you would want to with it.
There is an example app examples/bin/myapp (Spec: examples/myapp-spec.yaml) which should cover the currently implemented features.
You can find out more on https://github.com/perlpunk/App-Spec-p5. There's also a todo list.
There is also a commandline tool called app-spec https://github.com/perlpunk/App-AppSpec-p5 which you currently can use for generating completion from a spec without having to run the app.
The Motivation / Inspiration
I started to use zsh as my terminal shell about two years ago and find that the completion system and other things are still much better than in bash.
A couple of months ago I started to use Ingy's useful git-hub tool https://github.com/ingydotnet/git-hub. I saw there was a wish for better completion, so I wrote my first zsh completion code and later also the bash part.
When looking at the code of git-hub I saw that Ingy already did a lot to automate generation of help, man-pages and completion. That resulted in a little bit of more work to add code to the completion scripts, but will save work when subcommands, options are changed/added.
What I also to started to work with this year is Swagger http://swagger.io/. It lets you define a specification (in JSON or YAML; use the YAML version if you hate forbidden trailing commas) for your API. It's useful for developing (validation, runtime generation of the routes for your API, testing your API from a HTML page) and for writing clients (users get a specification on how to use your API, and they can try it out on that same HTML page).
Writing an API client when you have to manually find out about about the endpoints and input formats by browsing through large/several HTML pages sucks. Swagger puts it all into one place.
You can also comment on reddit.com.
There is also Perinci::CmdLine, which is like Catalyst, but for command line applications. The features it has is insane.
Check out Perinci's author's blog for loads of tutorials: https://perlancar.wordpress.com/category/perlcmd-tut/