(
SYNTAX
command-line
program-name-expr argv-expr clause ···
)
Parses a command line according to the specification in the
clause
s. The program-name-expr
should produce a string to be used as the
program name for reporting errors when the command-line is
ill-formed. The argv-expr
must evaluate to a vector of
strings; typically, it is (
.current-command-line-arguments
)
The command-line is disassembled into flags (possibly with flag-specific arguments) followed by (non-flag) arguments. Command-line strings starting with ``-'' or ``+'' are parsed as flags, but arguments to flags are never parsed as flags, and integers and decimal numbers that start with ``-'' or ``+'' are not treated as flags. Non-flag arguments in the command-line must appear after all flags and the flags' arguments. No command-line string past the first non-flag argument is parsed as a flag. The built-in -- flag signals the end of command-line flags; any command-line string past the -- flag is parsed as a non-flag argument.
For defining the command line, each clause
has one of the following forms:
(multi
flag-spec ···) (once-each
flag-spec ···) (once-any
flag-spec ···) (final
flag-spec ···) (help-labels
string ···) (args
arg-formals body-expr ···1) (=> finish-proc-expr arg-help-expr help-proc-expr unknown-proc-expr) flag-spec is one of (flags variable ··· help-str body-expr ···1) (flags => handler-expr help-expr) flags is one of flag-str (flag-str ···1) arg-formals is one of variable (variable ···) (variable ···1 . variable)
A multi
, once-each
, once-any
, or final
clause introduces a set of command-line flag specifications. The
clause tag indicates how many times the flag can appear on the
command line:
multi
-- Each flag specified in the set can be
represented any number of times on the command line; i.e., the flags
in the set are independent and each flag can be used multiple times.
once-each
-- Each flag specified in the set can be
represented once on the command line; i.e., the flags in the set are
independent, but each flag should be specified at most once. If a
flag specification is represented in the command line more than once,
the exn:fail
exception is raised.
once-any
-- Only one flag specified in the set can
be represented on the command line; i.e., the flags in the set are
mutually exclusive. If the set is represented in the command line
more than once, the exn:fail
exception is raised.
final
-- Like multi
, except that no
argument after the flag is treated as a flag. Note that multiple
final
flags can be specified if they have short names; for
example, if -a is a final
flag, then --aa combines
two instances of -a in a single command-line argument.
A normal flag specification has four parts:
flags
-- a flag string, or a set of flag strings. If a
set of flags is provided, all of the flags are equivalent. Each flag
string must be of the form "-
or x
""+
for
some character x
"x
, or "--
or x
""++
for
some sequence of characters x
"x
. An x
cannot contain only
digits or digits plus a single decimal point, since simple (signed)
numbers are not treated as flags. In addition, the flags "--"
,
"-h"
, and "--help"
are predefined and cannot be changed.
variable
s -- variables that are bound to the flag's
arguments. The number of variables specified here determines how many
arguments can be provided on the command line with the flag, and the
names of these variables will appear in the help message describing
the flag. The variable
s are bound to string values in the
body-expr
s for handling the flag.
help-str
-- a string that describes the flag. This
string is used in the help message generated by the handler for the
built-in -h (or --help) flag.
body-expr
s -- expressions that are evaluated when one of
the flags
appears on the command line. The flags are parsed
left-to-right, and each sequence of body-expr
s is evaluated as
the corresponding flag is encountered. When the body-expr
s are
evaluated, the variable
s are bound to the arguments provided
for the flag on the command line.
A flag specification using =>
escapes to a more general method
of specifying the handler and help strings. In this case, the handler
procedure and help string list returned by handler-expr
and
help-expr
are embedded directly in the table for
parse-command-line
, the procedure used to implement
command-line parsing.
A help-labels
clause inserts text lines into the help table of
command-line flags. Each string in the clause provides a separate
line of text.
An args
clause can be specified as the last clause. The
variables in arg-formals
are bound to the leftover command-line
strings in the same way that variables are bound to the formals
of a lambda
expression. Thus, specifying a single
variable
(without parentheses) collects all of the leftover
arguments into a list. The effective arity of the arg-formals
specification determines the number of extra command-line arguments
that the user can provide, and the names of the variables in
arg-formals
are used in the help string. When the command-line
is parsed, if the number of provided arguments cannot be matched to
variables in arg-formals
, the exn:fail
exception is raised. Otherwise,
args
clause's body-expr
s are evaluated to handle the
leftover arguments, and the result of the last body-expr
is the
result of the command-line
expression.
Instead of an args
clause, the =>
clause can be used
to escape to a more general method of handling the leftover
arguments. In this case, the values of the expressions with
=>
are passed on directly as arguments to
parse-command-line
. The help-proc-expr
and
unknown-proc-expr
expressions are optional.
Example:
(command-line "compile" (current-command-line-arguments
) (once-each
[("-v" "--verbose") "Compile with verbose messages" (verbose-mode #t)] [("-p" "--profile") "Compile with profiling" (profiling-on #t)]) (once-any
[("-o" "--optimize-1") "Compile with optimization level 1" (optimize-level 1)] ["--optimize-2" "Compile with optimization level 2" (optimize-level 2)]) (multi
[("-l" "--link-flags") lf ; flag takes one argument "Add a flag for the linker" "flag" (link-flags (cons
lf (link-flags)))]) (args
(filename) ; expects one command-line argument: a filename filename)) ; return a single filename to compile
(parse-command-line
progname argv table finish-proc arg-help
[help-proc unknown-proc
])
PROCEDURE
Parses a command-line using the specification in table
. For an
overview of command-line parsing, see the command-line
form.
The table
argument to this procedural form encodes the
information in command-line
's clauses, except for the args
clause. Instead, arguments are handled by the finish-proc
procedure, and help information about non-flag arguments is provided
in arg-help
. In addition, the finish-proc
procedure receives
information accumulated while parsing flags. The help-proc
and
unknown-proc
arguments allow customization that is not
possible with command-line
.
When there are no more flags, the finish-proc
procedure is called
with a list of information accumulated for command-line flags (see
below) and the remaining non-flag arguments from the command-line. The
arity of the finish-proc
procedure determines the number of non-flag
arguments accepted and required from the command-line. For example, if
finish-proc
accepts either two or three arguments, then either one or
two non-flag arguments must be provided on the command-line. The
finish-proc
procedure can have any arity (see section 3.10.1 in PLT MzScheme: Language Manual) except
0
or a list of 0
s (i.e., the procedure must at least
accept one or more arguments).
The arg-help
argument is a list of strings identifying the
expected (non-flag) command-line arguments, one for each argument. (If
an arbitrary number of arguments are allowed, the last string in
arg-help
represents all of them.)
The help-proc
procedure is called with a help string if the
-h or --help flag is included on the command line. If
an unknown flag is encountered, the unknown-proc
procedure is
called just like a flag-handling procedure (as described below); it
must at least accept one argument (the unknown flag), but it may also
accept more arguments. The default
help-proc
displays the string and exits and the default
unknown-proc
raises the exn:fail
exception.
A table
is a list of flag specification sets. Each set is
represented as a list of two items: a mode symbol and a list of
either help strings or flag specifications. A mode symbol is one of
'once-each
, 'once-any
, 'multi
,
'final
, or 'help-labels
, with the same
meanings as the corresponding clause tags in
command-line
. For the 'help-labels
mode, a list of
help string is provided. For the other modes, a list of flag
specifications is provided, where each specification maps a number of
flags to a single handler procedure. A specification is a list of
three items:
A list of strings for the flags defined by the spec. See
command-line
for information about the format of flag strings.
A procedure to handle the flag and its arguments when one of
the flags is found on the command line. The arity of this handler
procedure determines the number of arguments consumed by the flag: the
handler procedure is called with a flag string plus the next few
arguments from the command line to match the arity of the handler
procedure. The handler procedure must accept at least one argument to
receive the flag. If the handler accepts arbitrarily many arguments,
all of the remaining arguments are passed to the handler. A handler
procedure's arity must either be a number or an
arity-at-least
value (see section 3.10.1 in PLT MzScheme: Language Manual).
The return value from the handler is added to a list that is
eventually passed to finish-proc
. If the handler returns
void, no value is added onto this list. For all non-void
values returned by handlers, the order of the values in the list is
the same as the order of the arguments on the command-line.
A non-empty list of strings used for constructing help information for the spec. The first string in the list describes the flag, and additional strings name the expected arguments for the flag. The number of extra help strings provided for a spec must match the number of arguments accepted by the spec's handler procedure.
The following example is the same as the example for
command-line
, translated to the procedural form:
(parse-command-line
"compile" (current-command-line-arguments
) `((once-each [("-v" "--verbose") ,(lambda (flag) (verbose-mode #t)) ("Compile with verbose messages")] [("-p" "--profile") ,(lambda (flag) (profiling-on #t)) ("Compile with profiling")]) (once-any [("-o" "--optimize-1") ,(lambda (flag) (optimize-level 1)) ("Compile with optimization level 1")] [("--optimize-2") ,(lambda (flag) (optimize-level 2)) ("Compile with optimization level 2")]) (multi [("-l" "--link-flags") ,(lambda (flag lf) (link-flags (cons
lf (link-flags)))) ("Add a flag for the linker" "flag")])) (lambda (flag-accum file) file) ; return a single filename to compile '("filename")) ; expects one command-line argument: a filename