Next in line to be tried is Command Line Parser.
Surely comes as a NuGet package but, surprisingly, project documentation in master points to a beta version, not the stable one. Until I noticed, it caused me a couple of head scratches and a certain deal of fist waving.
Hybrid-nature
During this walk-through, I will use the Beta version, not the latest stable one as support for verbs (a very central concept in our sample application) has improved drastically and because, well, it is what you are shown in the project documentation page.
The "hybrid" moniker comes from the fact that the definition of the arguments is detached from the command actions themselves. That is, one creates an argument object for each command and decorates it with attributes that provide the metadata for the command-line behavior: Verb
for the container and Option
for each property (with attribute properties to drive command-line behaviors: names, help text,...).
Once those verbs are ready, the arguments are parsed and mapped into each of the verbs where an action is provided for the execution when the command is dispatched.
Implementing our example
The implementation of our command options is simple and uncompromised:
Dispatching is also simple: instantiate, translate one argument object into another (redundant if we embraced the framework) and call the method.
Its attribute-driven nature makes things more difficult for localisation.
The Challenges
Mandatory Arguments
Mandatory arguments are not the default, but setting to true the Required
property of [Option]
does the trick without any fuss and enables easy reporting of missing mandatory attributes:
Extra, unmapped arguments will make an error appear, but that behavior can be changed.
Non-Textual arguments
Declaring the right type for the property works fine including flags (boolean properties).
Failures, are handled gracefully and dutifully reported:
Default values are provided as objects, instead of strings.
Multi-arguments
Bi-dimensional types are supported out of the box as long as the property is defined as IEnumerable<>
and the Separator
property is set on the [Option]
.
However, there is no help hint in regards of what that separator character might be when displaying help to the user.
For showing some common scenarios, the [Usage]
attribute can be used. But it would have been nice to show the separator character just default values are shown.
Showing Help
Running the program without arguments (or with the help verb) provides a nice auto-generated list of supported verbs:
And using the help verb on a verb, drills down to the verb-level documentation:
Command Dispatching
As mentioned previously, command definition happens by providing an action when parsing the arguments. The simplest would be using the default instance of Parser
just as we have done in our example: Parser.Default.ParseArguments<Something, SomethingElse>(args)
and then map the options object to an action via .Map()
.
There is no command object per-se so if we need some sort of dependency injection it can be easily achieved by calling the container from the command action.
Conclusion
CommandLineParser is a full featured framework that can do pretty much everything we need with command line arguments and, in its unstable version, supports all the scenarios from our baseline without any trouble.
It is both powerful and simple to get going. A nice tool to have in the console tool-belt.
Last Console Series
- The beginning
- GoCommando
- CommandLineParser (this)
- PowerArgs
- LBi.Cli.Arguments
- Command Line Utils
- CLAP
- Wrap-up