The CLI package provides enhanced Posix+GNU command line parsing with the feature of commands that can be specified in a hierarchy.
See RFC-0038 for more background.
The general EBNF of a command line is:
command_line ::= root_command (option | command)* (option | arg)* command ::= alphanum_word alphanum_word ::= alphachar(alphachar | numchar | '_' | '-')* option ::= longoption | shortoptionset longoption ::= '--'alphanum_word['='arg | ' 'arg] shortoptionset := '-'alphachar[alphachar]...['='arg | ' 'arg] arg := boolarg | intarg | floatarg | stringarg boolarg := 'true' | 'false' intarg> := ['-'] numchar... floatarg ::= ['-'] numchar... ['.' numchar...] stringarg ::= anychar
The types in the cli package are broken down into three groups:
Pony programs use constructors to create the spec objects to specify their command line syntax. Many aspects of the spec are checked for correctness at compile time, and the result represents everything the parser needs to know when parsing a command line or forming syntax help messages.
Option and Arg value types¶
Options and Args parse values from the command line as one of four Pony types:
F64. Values of each of these types can then be
retrieved using the corresponding accessor funtions.
In addition, there is a string_seq type that accepts string values from the
command line and collects them into a sequence which can then be retrieved as
ReadSeq[String] using the
string_seq() accessor function.
Some specific details:
bool Options: have a default value of 'true' if no value is given. That is,
-fis equivalent to
string_seq Options: the option prefix has to be used each time, like:
--file=f1 --file=f2 --file=f3with the results being collected into a single sequence.
string_seq Args: there is no way to indicate termination, so a string_seq Arg should be the last arg for a command, and will consume all remaining command line arguments.
Programs then use the CommandSpec they've built to instantiate a parser to parse any given command line. This is often env.args(), but could also be commands from files or other input sources. The result of a parse is either a parsed command, a command help, or a syntax error object.
Programs then match the object returned by the parser to determine what kind it is. Errors and help requests typically print messages and exit. For commands, the fullname can be matched and the effective values for the command's options and arguments can be retrieved.
This program echos its command line arguments with the option of uppercasing them.
use "cli" actor Main new create(env: Env) => let cs = try CommandSpec.leaf("echo", "A sample echo program", [ OptionSpec.bool("upper", "Uppercase words" where short' = 'U', default' = false) ], [ ArgSpec.string_seq("words", "The words to echo") ])? .> add_help()? else env.exitcode(-1) // some kind of coding error return end let cmd = match CommandParser(cs).parse(env.args, env.vars) | let c: Command => c | let ch: CommandHelp => ch.print_help(env.out) env.exitcode(0) return | let se: SyntaxError => env.out.print(se.string()) env.exitcode(1) return end let upper = cmd.option("upper").bool() let words = cmd.arg("words").string_seq() for word in words.values() do env.out.write(if upper then word.upper() else word end + " ") end env.out.print("")