Unified command-line option parsing and config management.
The high-level interface. Given an application spec spec
,
parses the given command-line arguments args
into a config
object, prepended to the existing object config
if given.
Then runs the corresponding command (or sub-command) procedure
from spec
.
The app spec should be a list of the form:
(<command> [<doc-string>] <clauses> ...)
where clauses can be any of:
(@ <opt-spec>)
- option spec, described below(begin: <begin-proc>)
- procedure to run before main(end: <end-proc>)
- procedure to run after main(<proc> args ...)
- main procedure (args only for documentation)<app-spec>
- a subcommand described by the nested spec(or <app-spec> ...)
- an alternate list of subcommands
For subcommands the symbolic command name must match, though it is
ignored for the initial spec (i.e. the application name is not
checked). The begin
and end
procedures can be
useful for loading and saving state common to all subcommands.
The opt-spec
describes command-line options, and is a
simple list with each opt of the form:
(<name> <type> [(<aliases> ...)] [<doc-string>])
where <name>
is a symbol name, <aliases>
is an
optional list of strings (for long options) or characters (for
short options) to serve as aliases in addition to the exact name.
type
can be any of:
boolean
- boolean, associated value optional, allowing--noname
to indicate#false
char
- a single characterinteger
- an exact integerreal
- any real numbernumber
- any real or complex numbersymbol
- a symbolstring
- a stringsexp
- a sexp parsed withread
(list <type>)
- a comma-delimited list of types
Note that the options specs are composed entirely of objects that
can be read and written, thus for example optionally loaded from
files, whereas the app specs include embedded procedure objects so
are typically written with quasiquote
.
Complete Example:
(run-application
`(zoo
"Zookeeper Application"
(@
(animals (list symbol) "list of animals to act on (default all)")
(lions boolean (#l) "also apply the action to lions"))
(or
(feed "feed the animals" () (,feed animals ...))
(wash "wash the animals" (@ (soap boolean)) (,wash animals ...))
(help "print help" (,app-help-command))))
(command-line)
(conf-load (string-append (get-environment-variable "HOME") "/.zoo")))
The second and third arguments here are optional, provided to show the common pattern of allowing the same options to be specified either in a file and/or on the command-line. The above app can be run as:
Feed all animals, including lions:
zoo -l feed
Wash the elephants with soap:
zoo --animals=elephant wash --soap
Print help:
zoo help
The application procedures themselves are of the form:
(proc cfg spec args ...)
where cfg
is a config object from (chibi config)
holding the parsed option info, spec
is the original app
spec, and args
are the remaining non-option command-line
arguments.
To retrieve the options for the above example you can use:
(conf-get cfg 'animals)
(conf-get cfg 'lions)
(conf-get cfg '(command wash soap))
Notice that options for subcommands are nested under the
(command <name>)
prefix, so that you can use the same
name for different subcommands without conflict. This also means
the subcommand options are distinct from the top-level options, so
when using subcommands users must always write the command line
as:
app [<general options>] <subcommand> [<sub options>]
The ~/.zoo file could then hold an sexp of the form:
((animals (camel elephant rhinocerous))
(command
(wash
(soap #t))))
Parse a single command-line argument from args
according to
conf-spec
, and returns a list of two values: the
(name value)
for the option, and a list of remaining
unparsed args. name
will have the current prefix
prepended. If a parse error or unknown option is found, calls
fail
with a single string argument describing the error,
returning that result.
Parse a list of command-line arguments into a config object. Returns a list whose head is the resulting config object, and tail is the list of remaining non-option arguments. Calls fail on error and tries to continue processing from the result.
Parses a list of command-line arguments args
according to
the application spec opt-spec
. Returns a vector of five
elements:
proc
- procedure to run the applicationconfig
- a config object containing all parsed optionsargs
- a list of remaining unparsed command-line argumentsinit
- an optional procedure to call beforeproc
end
- an optional procedure to call afterproc
The config object is prepended to config
, with option names
all prefixed by prefix
. The original spec
is used for
app-help
.
Print a help summary for the given application spec spec
.
The subcommand form of app-help
. You can use this as a
subcommand in an application spec, for example as:
(help "print help" (,app-help-command args ...))