On this page:
command-line
parse-command-line
Version: 4.1

14.8 Command-Line Parsing

 (require scheme/cmdline)

The bindings documented in this section are provided by the scheme/cmdline and scheme libraries, but not scheme/base.

(command-line optional-name-expr optional-argv-expr

              flag-clause ...

              finish-clause)

 

optional-name-expr

 

=

 

 

 

|

 

#:program name-expr

 

 

 

 

 

optional-argv-expr

 

=

 

 

 

|

 

#:argv argv-expr

 

 

 

 

 

flag-clause

 

=

 

#:multi flag-spec ...

 

 

|

 

#:once-each flag-spec ...

 

 

|

 

#:once-any flag-spec ...

 

 

|

 

#:final flag-spec ...

 

 

|

 

#:help-labels string ...

 

 

 

 

 

flag-spec

 

=

 

(flags id ... help-spec body ...+)

 

 

|

 

(flags => handler-expr help-expr)

 

 

 

 

 

flags

 

=

 

flag-string

 

 

|

 

(flag-string ...+)

 

 

 

 

 

help-spec

 

=

 

string

 

 

|

 

(string-expr ...+)

 

 

 

 

 

finish-clause

 

=

 

 

 

|

 

#:args arg-formals body ...+

 

 

|

 

#:handlers handlers-exprs

 

 

 

 

 

arg-formals

 

=

 

id

 

 

|

 

(id ...)

 

 

|

 

(id ...+ . id)

 

 

 

 

 

handlers-exprs

 

=

 

finish-expr arg-strings-expr

 

 

|

 

finish-expr arg-strings-expr help-expr

 

 

|

 

finish-expr arg-strings-expr help-expr

unknown-expr

Parses a command line according to the specification in the flag-clauses.

The name-expr, if provided, should produce a path or string to be used as the program name for reporting errors when the command-line is ill-formed. It defaults to (find-system-path 'run-file). When a path is provided, only the last element of the path is used to report an error.

The argv-expr, if provided, must evaluate to a list or a vector of strings. It defaults to (current-command-line-arguments).

The command-line is disassembled into flags, each 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.

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:

A normal flag specification has four parts:

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 used as in the table argument of parse-command-line.

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.

After the flag clauses, a final clause handles command-line arguments that are not parsed as flags:

Example:

  (define verbose-mode (make-parameter #f))

  (define profiling-on (make-parameter #f))

  (define optimize-level (make-parameter 0))

  (define link-flags (make-parameter null))

  

  (define file-to-compile

    (command-line

     #:program "compiler"

     #: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"        (; show help on separate lines

                             "Compile with optimization level 2,"

                             "which includes all of level 1")

                            (optimize-level 2)]

     #:multi

     [("-l" "--link-flags") lf ; flag takes one argument

                            "Add a flag <lf> for the linker"

                            (link-flags (cons lf (link-flags)))]

     #:args (filename) ; expect one command-line argument: <filename>

     ; return the argument as a filename to compile

     filename))

(parse-command-line

 

name

 

 

 

 

 

 

argv

 

 

 

 

 

 

table

 

 

 

 

 

 

finish-proc

 

 

 

 

 

 

arg-help-strs

 

 

 

 

 

 [

help-proc

 

 

 

 

 

 

unknown-proc])

 

 

any

  name : (or/c string? path?)

  argv : (or/c (listof string?) (vectorof string?))

  table : (listof (list/c symbol? list?))

  finish-proc : ((list?) () #:rest list? . ->* . any)

  arg-help-strs : (listof string?)

  help-proc : (string? . -> . any) = (lambda (str) ....)

  unknown-proc : (string? . -> . any) = (lambda (str) ...)

Parses a command-line using the specification in table. For an overview of command-line parsing, see the command-line form, which provides a more convenient notation for most purposes.

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-strs. 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, finish-proc 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 finish-proc 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 procedure-arity) except 0 or a list of 0s (i.e., the procedure must at least accept one or more arguments).

The arg-help-strs 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-strs 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:

The following example is the same as the core 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,"

          "which implies all optimizations of level 1"))])

      (multi

       [("-l" "--link-flags")

        ,(lambda (flag lf) (link-flags (cons lf (link-flags))))

        ("Add a flag <lf> for the linker" "lf")]))

     (lambda (flag-accum file) file)

     '("filename"))