| Allegro CL version 10.0 Unrevised from 9.0 to 10.0. 9.0 version |
Arguments: ( &rest option-lists) (restvar &key command-line-arguments usage posixly-correct long-abbrev) &body body
This macro was redefined in release 6.2. The change is upward-compatible so that with-command-line-arguments calls defined using the earlier macro/description should work as before.
The old-format lambda list for this macro is:
Arguments: (optstring &rest varlist) (restvar &key command-line-arguments usage) &body body
Any arguments that followed the old format are accepted in the new macro (which accepts more than one option-list and accepts more keyword arguments).
This macro makes the task of parsing command line arguments easier, in the style similar to the UNIX getopt(3) and getopt(1). During parsing, command line arguments are scanned from left to right. An argument named -- terminates option scanning. This macro works on both UNIX and Windows platforms. It works on Windows as it does on UNIX. Windows users should, like UNIX users refer to UNIX documentation on this (you can enter getopt(1) and getopt(3) into the Google (tm) search engine to find such documentation). We believe, however, that this documentation is stand-alone and should be sufficient for you to understand all the issues surrounding command line arguments and their use.
The main task of with-command-line-arguments is to bind Lisp variables to the given command line arguments.
option-lists, the first argument, is a list of (for the old form) an option-string and any number of variable names or (for the new form) a list of lists described below. Note that with-command-line-arguments will signal an error if a command line argument (option) is found without a corresponding entry in the option-lists.
The old form, which preserves for compatibility with the older version of this macro, is therefore (in the lambda-list specification above, the parentheses around option-lists are the parentheses shown here):
(option-string [variable-names]*)
option-string is a getopt(3) style string describing the expected options. variable-names are the symbols to which values are bound. The order of the options in option-string is the order in which the variables are bound. From the complete example below, we have
("ab:c" aflag bflag cflag)
The getopt(3) allows one character for each option, so the
options in the example are `a', `b', and `c'. The corresponding
variables are aflag
, bflag
, and
cflag
.
In the first update (in March 2003), the new form specification was
(option style varname [companion])
. This has been
superseded as follows:
In the new form, option-lists is a list of items with the following form:
(name style varname [modifiers ...])
name is a string naming the argument, such as "a" or "foo".
style must be either :short
or
:long
. For :short
options, the
string must be of length 1 (e.g., "a" for the command line option
-a). For :long
options, the string can be
any length (e.g., "foo" for --foo). Long options are typically
specified on a command line preceded with two dashes (hence
--foo) while short options are preceded with one dash (hence
-a). However, the long-abbrev keyword
argument can allow single dashes to precede long options.
varname is a symbol to which a value is
bound. This should be a Lisp symbol, for example
aflag
or foo
.
modifiers may be unspecified or one or more of the following keyword selections:
:required-companion
(:required
is accepted to mean :required-companion
) or
:optional-companion
(:optional
is accepted to mean :optional-companion
), either of
which indicate a companion argument is accepted (and is required or
optional). A companion argument is often a value or a modifier of some
sort, see the examples below. If modifiers does
not include either :required-companion
or
:optional-companion
, the option cannot have a
companion argument.
:allow-multiple-options
: when this appears as a
modifier, the option being described can appear multiple times in the
command line. The value bound to varname will
reflect the presence or absence of this modifier as follows:
:required-companion
or
:optional-companion
is also a modifier, then
varname is bound to a list of the values
corresponding to the given command-line values.
:required-companion
or
:optional-companion
is also a modifier, then
varname is bound to a number indicating the
number of times the option is specified in the command line (or
nil
, not 0, if it does not appear at all).
If :allow-multiple-options
is not specified as a
modifier, an error is signaled if an option appears more than once.
Consider the following example which does not allow multiple options:
("foo" :long foo :required-companion) ("a" :short aflag :required-companion)
The required-companion arguments can be specified in the following ways:
--foo bar --foo=bar -abar -a bar
In each case the companion argument is "bar". Note that long form options are separated from their companions by a space or by =. Short form options are separated by a space or are not separated. The fact that no separation is allowed for short form options can lead to ambiguity. See the discussion of the long-abbrev keyword argument below for details.
Now consider these examples which do (for some options) allow multiple options:
;; Option `o' allows multiple options, and requires companions ;; so the `oflag' variable is bound to a list of the companion ;; values specified: cl-user(13): (sys:with-command-line-arguments (("o" :short oflag :required-companion :allow-multiple-options)) (rest :command-line-arguments '("-ofoo" "-o" "bar")) oflag) ("foo" "bar") ;; Option `x' does not allow multiple options but option `v' does. ;; Neither accepts companions. `xflag' is either T or NIL while ;; `vflag' is a number, indicating how many times it appears ;; (if it does not appear, `vflag' is NIL, not 0): cl-user(14): (sys:with-command-line-arguments (("x" :short xflag) ("v" :short vflag :allow-multiple-options)) (rest :command-line-arguments '("-v" "-x" "-v")) (list vflag xflag)) (2 t) cl-user(15): (sys:with-command-line-arguments (("x" :short xflag) ("v" :short vflag :allow-multiple-options)) (rest :command-line-arguments '("-x")) (list vflag xflag)) (nil t) ;; The same specification as just above, but `x' is specified ;; twice, causing an error: cl-user(16): (sys:with-command-line-arguments (("x" :short xflag) ("v" :short vflag :allow-multiple-options)) (rest :command-line-arguments '("-v" "-x" "-v" "-x")) (list vflag xflag)) Error: Option `x' cannot be specified more than once. Restart actions (select using :continue): 0: Return to Top Level (an "abort" restart). 1: Abort entirely from this process. [1] cl-user(17): :reset ;; The same specification as just above. `x' is not specified and ;; `v' is specified three times with `-vvv': cl-user(18): (sys:with-command-line-arguments (("x" :short xflag) ("v" :short vflag :allow-multiple-options)) (rest :command-line-arguments '("-vvv")) (list vflag xflag)) (3 nil) ;; Here `v' has an optional-companion, and appears as `"-v" "2" "-vv"'. ;; Note that `-vv' is `v' appearing once with companion "v" rather than ;; `v' appearing twice (an unavoidable ambiguity discussed further ;; below): cl-user(19): (sys:with-command-line-arguments (("x" :short xflag) ("v" :short vflag :optional-companion :allow-multiple-options)) (rest :command-line-arguments '("-v" "2" "-vv")) (list vflag xflag)) (("2" "v") nil) ;; Again `v' has an optional-companion and is specified with ;; and without a companion value. The unspecified value appears ;; as the empty string in the values of v list (`x' also appears ;; once): cl-user(20): (sys:with-command-line-arguments (("x" :short xflag) ("v" :short vflag :optional-companion :allow-multiple-options)) (rest :command-line-arguments '("-v" "2" "-v" "-x")) (list vflag xflag)) (("2" "") t) cl-user(23):
Although either form, old or new, can be used for the option-lists, the new form is preferred since it offers long form arguments and does not require positional synchronization of the options in option-string with the variables given by [variable-names]*.
restvar should be a symbol. It is bound to all command line arguments that are not options. A command line argument of -- terminates option scanning and causes all remaining arguments to be put into restvar. The order of arguments in restvar will have the same order as the arguments on the command line, or in the value of the keyword command-line-arguments.
The command-line-arguments keyword argument is
used to initialize the command line arguments. If not given, then the
function command-line-arguments, called with a true
value for the application keyword argument, is
used to retrieve the actual command line arguments given to the
invoked image. If command-line-arguments
is specified nil
, then the actual command
line arguments are not substituted in (as they are when no value for
this argument is specified). Instead, the with-command-line-arguments form is rendered
a no-op and does nothing. (Obviously there is no point in calling this
macro with :command-line-arguments nil
, but you
might call it with the value
of :command-line-arguments
a variable whose value
might happen to be nil
. If you do that, the
macro will do what you want when the variable has
value nil
as well as when it has a
non-nil
value.)
The posixly-correct keyword argument, ignored in
the old form, says what to do when a non-option is encountered in the
left to right scan of the command line arguments. If
posixly-correct is non-nil
, then processing of the command line terminates
when a non-option is seen, otherwise the non-option is put into
restvar.
The usage keyword argument, if specified, should be a string. This string is printed when errors are found while parsing the command line arguments according to the given specification. (Possible errors would be not supplying a companion argument, supplying an unknown command line argument, etc.)
The long-abbrev keyword argument, ignored in the old form, allows long form arguments to be specified with a single -. Otherwise they must be specified with double dashes, --.
Allowing a single dash to specify a long form argument can introduce ambiguity. Consider the following case illustrated by a partial with-command-line-arguments form:
(sys:with-command-line-arguments (("foo" :long foo :optional-companion) ("f" :short aflag :required-companion)) (:long-abbrev t) ...)
Now suppose the argument -foo is provided. Does this mean the
long form argument -foo or the short form argument -f
with companion (or value) oo? Both interpretations are valid,
and so the argument is ambiguous. When
long-abbrev is specified true, the system will
always assume that an argument is a long form argument if it can be so
intrepreted. If the argument cannot be interpreted as a long form
argument, the short form argument interpretation will be
used. Programmers should avoid any possibility of ambiguity, of
course. Again, if long-abbrev is nil
, short form and long form arguments are
designated differently and there can be no ambiguity in
interpretation. The downside is that it may be harder for users of an
application to specify arguments correctly (that is to remember which
require two dashes and which require one).
Here is the example above shown in a script:
cl-user(1): (system:with-command-line-arguments (("foo" :long foo :optional-companion) ("f" :short fflag :optional-companion)) (rest :command-line-arguments '("-foo") :long-abbrev nil) (list foo fflag rest)) (nil "oo" nil) ;; -foo is parsed as a short option since the long form "foo" ;; must be specified --foo. cl-user(2): (system:with-command-line-arguments (("foo" :long foo :optional-companion) ("f" :short fflag :optional-companion)) (rest :command-line-arguments '("-foo") :long-abbrev t) (list foo fflag rest)) (t nil nil) ;; -foo is parsed as a long option.
body is a list of forms, executed in a lexical environment where the variables discussed above are bound for use by the macro's body.
Here are some more examples of the new form:
cl-user(15): (sys:with-command-line-arguments (("foo" :long foo :required-companion) ("bar" :long bar :optional-companion) ("baz" :long baz nil) ("a" :short aflag :required-companion) ("b" :short bflag :optional-companion) ("c" :short cflag nil)) (rest :long-abbrev t :command-line-arguments '("--foo" "xxx" "--bar" "-afoo" "-b" "-c" "1" "2" "3")) (format t "foo=~a, bar=~a, baz=~a, a=~a, b=~a, c=~a, rest=~a~%" foo bar baz aflag bflag cflag rest)) foo=xxx, bar=t, baz=nil, a=foo, b=t, c=t, rest=(1 2 3) nil cl-user(16): (sys:with-command-line-arguments (("foo" :long foo :required-companion) ("bar" :long bar :optional-companion) ("baz" :long baz nil) ("a" :short aflag :required-companion) ("b" :short bflag :optional) ("c" :short cflag nil)) (rest :long-abbrev t :command-line-arguments '("--foo=xxx" "--bar" "-a" "foo" "-b" "-c" "1" "2" "3")) (format t "foo=~a, bar=~a, baz=~a, a=~a, b=~a, c=~a, rest=~a~%" foo bar baz aflag bflag cflag rest)) foo=xxx, bar=t, baz=nil, a=foo, b=t, c=t, rest=(1 2 3) nil cl-user(17): (sys:with-command-line-arguments (("foo" :long foo :required-companion) ("f" :short fflag :required-companion) ("foo2" :long foo2 :required-companion)) (rest :command-line-arguments '("--foo" "xxx" "--foo2=blah" "-foo" "foo")) (format t "foo=~a, foo2=~a, f=~a, rest=~a~%" foo foo2 fflag rest)) foo=xxx, foo2=blah, f=oo, rest=(foo) nil cl-user(18): (sys:with-command-line-arguments (("f" :short fflag :required-companion)) (rest :command-line-arguments '("-foo" "xxx" "foo")) (format t "f=~a, rest=~a~%" fflag rest)) f=oo, rest=(xxx foo) nil cl-user(19):
Note: the command-line-arguments keyword would normally not be used since the actual command line arguments would come from the command line of the running application.
Here is an example of the old form:
cl-user(18): (sys:with-command-line-arguments ("ab:c" aflag bflag cflag) (rest :command-line-arguments '("-a" "-b" "xxx" "1" "2" "3")) (format t "a=~a, b=~a, c=~a, rest=~a~%" aflag bflag cflag rest)) a=t, b=xxx, c=nil, rest=(1 2 3) nil cl-user(19):
See Command line arguments in startup.htm for a list of command-line arguments accepted by Allegro CL.
Copyright (c) 1998-2019, Franz Inc. Oakland, CA., USA. All rights reserved.
This page was not revised from the 9.0 page.
Created 2015.5.21.
| Allegro CL version 10.0 Unrevised from 9.0 to 10.0. 9.0 version |