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

15.9 Command-Line Parsing

 (require racket/cmdline) package: base
The bindings documented in this section are provided by the racket/cmdline and racket libraries, but not racket/base.

syntax

(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 ...
  | #:usage-help string ...
  | #:help-labels string ...
  | #:ps 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 = rest-id
  | (arg ...)
  | (arg ...+ . rest-id)
     
arg = id
  | [id default-expr]
     
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 #:usage-help clause inserts text lines immediately after the usage line. Each string in the clause provides a separate line of text.

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.

A #:ps clause inserts text lines at the end of the help output. 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))

procedure

(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 (cons/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 pair 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, 'help-labels, 'usage-help, or 'ps with the same meanings as the corresponding clause tags in command-line. For the 'help-labels, 'usage-help or 'ps mode, a list of help strings 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"))