Automatic command-line verb and argument parsing using smart reflection.
Inspired by the ASP.NET MVC Controller-Actions, finally – a kick-ass command-line parser. The last one you will ever need!
Update: Part 2 of the CLAP introduction is here
- Source code and binaries at github: https://github.com/adrianaisemberg/CLAP
- NuGet: Install-Package CLAP
Consider the following method:
The Print method is marked with the [Verb] attribute which defines method as valid entry points for the application.
Each of the method’s arguments are automatically mapped to command-line input arguments, regardless of their order.
Notice that all names, both for verbs and parameter names are case-insensitive.
Let’s change our Main method to use the parser:
After successfully compiling, we can now run our application, providing a verb and arguments:
More Verbs for the same program
A class may contain more than one verb.
In the following example, “print” and “login” are two different entry-points for the application, each with a different set of arguments:
A Default Verb
One of the verbs, or even the single one if no more than one are available, can be defined as the default verb using the [DefaultVerb] attribute above the class.
In the following example, “print” is the default verb, so if the user doesn’t provide a verb in the command-line, “print” will be called:
In that case, we can call:
A verb can have more than one name. The first name is the method’s name but additional names can be defined using the Aliases property.
In the following example, “p” is an additional name for the “print” verb and both “l” and “log” are additional names for the “login” verb:
Parameters are automatically detected according to their names. Additional options can be defined for parameters using more attributes.
As a verb, parameters can also have additional names when marked with the [Parameter] attribute.
In the following example, both “name” and “n” are additional names for the “userName” parameter and both “pass” and “p” are for the “password” parameter:
A parameter can be omitted from the input. If a parameter is omitted, it’s value will have the type’s default (null for reference types, zero for value types).
A default value can be defined for a parameter to override the type’s default.
In the following example, “Hello” is the default for the prefix parameter and 5 for count:
Now we can run:
And get this result:
Boolean types are treated as switches.
A switch is an argument that doesn’t need a value. If the argument exists – the value is true, otherwise – it is false.
In the following example, the “upper” parameter is a boolean, and therefore – a switch. In-addition, it has an additional, shorter name: “u”:
Now we can run:
The supported parameter types are:
- Numeric Types (int, float, …)
- Boolean – can be used as switches but also with “true”/”false” input
- Any Enum (input is case-sensitive)
- Arrays of all the above
Arrays are called as comma-separated values. For example:
A parameter can be marked as required. A missing argument will throw a MissingRequiredArgumentException.
In the following example, the “name” parameter is required:
Trying to run the program without providing a value for “name” will throw an exception.
In this example, the exception is not caught and therefore, the application crashes and the stack-trace is printed to the console:
Validation attributes can be specified for parameters.
Current available attributes are:
Providing a value that doesn’t pass validation will throw a ValidationException.
In the following example, “count” is validated to be more than 3:
Additional validation attributes can be defined for the same parameter. Validation passes only if all validators pass (AND).
In the following example, “count” is validated to be more than 3 and less-or-equal to 20:
The following is a list of all the exceptions that might be thrown when failing to parse the command-line.
Notice that all exception derive from the abstract CommandLineException.
- The input does not contain a verb and no default verb was defined.
- Solution: Either input a verb or define one using the [DefaultVerb] attribute.
- The input contains a verb but no method matches it.
- Solution: Check that the method is marked with the [Verb] attribute or that the input verb is one of the verb’s aliases.
- A required argument is missing.
- Solution: If the parameter is marked as [Parameter(Required = true)], check that an argument is actually passed for that parameter.
- A value argument is missing from a parameter input, and the parameter is not a switch (the type is not a boolean).
- Solution: Make sure the argument value is passed in the form of: -name:value
- A parameter does not have a prefix of either “-“ or “/”.
- Solution: Make sure to prefix all parameters with a valid prefix.
- An argument value does not pass validation.
- Solution: Make sure the value passes the defined validation.
- An argument value cannot be converted to the parameter’s type, for example: A string input for an int type.
- Solution: Make sure the input value matches the parameter’s type.
This post introduced the Command-Line Auto Parser and provided examples for:
- Defining verbs
- Defining parameters
- Default verbs and additional names
- Default values
- Supported parameter types
- Using built-in validation
- Exceptions and how to handle them
In the next post, additional features are introduced:
- Global parameter handlers
- Custom validation
- Providing help to the user