# Packages
# README
argparse
A type safe, extensible CLI argument parsing utility package.
https://github.com/barbell-math/util/blob/9948c0045f7246acb5c2827ea4b34cb4919fcae9/src/argparse/examples/SimpleExamples_test.go#L48-L73 Example usage of the argparse package
Usage
The above example shows the general usage of this package. In the example there are three main parts to consider:
- An
ArgBuilder
is created and it is populated with arguments. This stage is where the vast majority of your interaction with the package will take place, and is explained in more detail in the next section. - The
ArgBuilder
makes aParser
. Optionally this is where sub parsers could be added if you were using them. - The
Parser
is then used to parse a slice of strings which is translated into a sequence of tokens.
Argument Builder: Primitive Types
Primitive types are the most straight forward. Shown below is how to add an
integer argument. The translators.BuiltinInt
type is responsible for parsing
an integer from the string value supplied by the CLI. Analogous types are
available for all primitive types, all following the Builtin<type>
format.
https://github.com/barbell-math/util/blob/9948c0045f7246acb5c2827ea4b34cb4919fcae9/src/argparse/examples/SimpleExamples_test.go#L19-L20 Integer argument
The above example provides an argument with no options, meaning all the default options will be used. Shown below is how to provide your own set of options.
https://github.com/barbell-math/util/blob/9948c0045f7246acb5c2827ea4b34cb4919fcae9/src/argparse/examples/SimpleExamples_test.go#L54-L60 Integer argument with options
The following options can be provided all through setter methods similar to the ones shown in the example above:
shortName
: The single character flag that the argument can be specified with as a short hand for the provided long name.description
: The description that will be printed on the help menu.required
: A boolean indicating if the argument is required or not.defaultVal
: The value that should be returned if the argument is not provided on the CLI.translator
: The translator that should be used when translating the CLI string to the appropriately typed value.argType
: The type of argument. This value tells the parser what semantics are valid for the argument.
The available argument types are as follows:
ValueArgType
: Represents a flag type that must accept a single value as an argument and must only be supplied once.MultiValueArgType
: Represents a flag type that can accept many values as an argument and must only be supplied once. At least one argument must be supplied.FlagArgType
: Represents a flag type that must not accept a value and must only be supplied once.MultiFlagArgType
: Represents a flag type that must not accept a value and may be supplied many times.
Argument Builder: Out of the Box Argument Types
The ArgBuilder
also has several helper functions and translators for common
CLI argument types.
- Flag arguments. This will return true if the flag is provided. It does accept any values.
- Flag counter argument. This will return an integer equal to the number of times that the flag was provided. It does not accept any values.
- List argument. This will build up a list of all the values that were provided with the argument. Many values can be provided with a single argument or many flags can be provided with a single argument, as shown in the example arguments below the argument example.
https://github.com/barbell-math/util/blob/9948c0045f7246acb5c2827ea4b34cb4919fcae9/src/argparse/examples/SimpleExamples_test.go#L170-L187 https://github.com/barbell-math/util/blob/9948c0045f7246acb5c2827ea4b34cb4919fcae9/src/argparse/examples/SimpleExamples_test.go#L192
- List argument with a predefined set of allowed values. This will build up a list of all the values that were provided with the argument, provided that they are in the allowed list of values. Many values can be provided with a single argument or many flags can be provided with a single argument, as shown in the example arguments below the argument example. Note that given the design of this translator the list can contain any type, as long as the underlying type has a translator of it's own.
https://github.com/barbell-math/util/blob/9948c0045f7246acb5c2827ea4b34cb4919fcae9/src/argparse/examples/SimpleExamples_test.go#L211-L231 https://github.com/barbell-math/util/blob/9948c0045f7246acb5c2827ea4b34cb4919fcae9/src/argparse/examples/SimpleExamples_test.go#L238
- Selector argument. This will accept a single value as long as that value is in the predefined set of allowed values. As with the list argument, the selector translator can work with any type as long as it has an underlying translator of it's own.
- File argument. This will accept a single string value and verify that the supplied string is a path that exists as a file.
- Directory argument. This will accept a single string value and verify that the supplied string is a path that exists as a directory.
- File open argument. This will accept a single string value and will attempt to make the supplied file with the given file mode and permissions.
- Mkdir argument. This will accept a single string value and will attempt to make the directory(s) that are denoted by the string value.
Argument Builder: Custom Types
Due to using generics, the argument builder can accept arguments of custom types
as long as there is a translator for that type. For examples of how to implement
translators refer to the
stateless translator example
as well as the
stateful translator example.
Any custom types defined outside of this package will use the AddArg
function
to add arguments.
To support a custom type the Translate
method on the translator will simply
need to return the custom type. Support for custom translators and types allows
for a completely type safe translation of the CLI arguments into values that
your program can work with.
Argument Builder: Computed Arguments
Computed arguments provide a way for the argument parser to set values that were not directly provided by the CLI, potentially computing values based on the provided CLI arguments. The example below shows how to add a computed argument to the parser.
Much like translators for arguments, computers are needed to set computed values. Also like translators, computers are expected to return a value, this time the value that is returned is the result of a computation rather than a translation. Yet another similarity is that computed arguments support custom types in all the same ways that translators do. For an example of how to implement a custom computer refer to the custom computer example.
Computed arguments do have one advantage over normal (translated) arguments. All computed arguments are added to a tree like data structure following the same ordering that any sub-parsers were added in. Given this tree like data structure computed arguments are then evaluated bottom up, left to right. With this organized evaluation ordering it is possible to evaluate arbitrary expressions. This will likely never be useful and an argument could be made that this should never be done, but the capability is there. For an example of this evaluation refer to the sub-parsers examples.
Sub-Parsers
Several different parsers, each with there own set of arguments, can be separately built and then combined into one larger parser. When adding one parser to another the parsers are added as children, or sub parsers, to the main parser. A couple examples of sub-parsers are shown in the sub-parsers examples file. There are a couple rules that dictate what happens when sub-parsers are added:
- All non-computed arguments are added to one single global namespace. This means that all long argument and short argument names must be unique among all of the sub-parers.
- Computed arguments are added in a tree like data structure that mirrors the structure created by the function calls for adding sub-parsers. The advantage of this is explained in the previous section.
There are several sub-parsers that are provided out-of-the-box for common CLI needs.
- Help: this adds the
-h
and--help
flag arguments which when encountered will stop all further parsing and print the help menu. - Verbosity: this adds the
-v
and--verbose
flag counter arguments which can be used to set a verbosity level for a running application.