Parses a command line according to the specification in the clauses. The program-name-str string is 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, which is typically the value of argv as defined by the MzScheme stand-alone application.
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:
flag-spec is one of:
(flags variable help-str body-expr )
(flags => handler-expr help-expr)
flags is one of:
flag-str
(flag-str )
arg-formals is one of:
variable
(variable )
(variable . variable)
(multi flag-spec )
(once-each flag-spec )
(once-any flag-spec )
(args arg-formals body-expr )
(=> finish-proc-expr arg-help-expr help-proc-expr unknown-proc-expr)
A multi, once-each, or once-any clause introduces
a set of command-line flag specifications. The clause tag indicates
how many times the flag can appear 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.
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:user exception is raised. Otherwise, args clause's body-exprs are evaluated to handle the leftover arguments.
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 expresisons are optional.
Example:
(command-line "compile" argv (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
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 4.10.1) except 0 or a list of 0s (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:user 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 flag specifications. A mode symbol is one of 'once-each, 'once-any, or 'multi, with the same meanings as the corresponding clause tags in command-line. Each specification maps a number of flags to a single handler procedure. A specification is a list of three items:
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.
The following example is the same as the example for command-line, translated to the procedural form:
(parse-command-line "compile" argv `((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