gauche.parseopt- Parsing command-line options
This module defines a convenient way to parse command-line options. The interface is hinted by Perl, and conveniently handles long-format options with multiple option arguments.
Actually, you have a few choices to parse command-line
options in Gauche.
SRFI-37 (see A program argument processor) provides
functional interface to parse POSIX/GNU compatible argument syntax.
Required features may differ from application to application,
so choose whichever fits your requirement.
This macro captures the most common pattern of argument processing. It takes a list of arguments, args, and scans it to find Unix-style command-line options and binds their values to local variables according to bind-spec, then executes body ….
Let’s look at a simple example first, which gives you a good idea of what this form does. (See the “Examples” section below for more examples).
(define (main args) (let-args (cdr args) ((verbose "v|verbose") (outfile "o|outfile=s") (debug-level "d|debug-level=i" 0) (help "h|help" => (cut show-help (car args))) . restargs ) ....)) (define (show-help progname) ...)
The local variable verbose will be bound to
a command-line argument
--verbose is given,
The variable output is specified to take one option argument;
if the command-line arguments are given like
"out.txt". The debug-level one is similar, but the
option argument is coerced to an integer, and also it has default
value 0 when the option isn’t given. The help clause
invokes an action rather than merely binding the value.
let-args does not distinguish so-called
short and long options, e.g.
--v have the same
effect, so as
--verbose. In future we
may add an option to make it compatible with
The final restargs variable after the dot receives a list of non-optional command-line arguments.
Let’s look at bind-spec in detail. It must be one of the following forms.
1. (var option-spec) 2. (var option-spec default) 3. (var option-spec => callback) 4. (var option-spec default => callback) 5. (else => handler) 6. (else formals body ...)
A list of command-line arguments passed to args are parsed according to option-specs. If the corresponding option is given, a variable var is bound to a value as follows:
(a) If the bind-spec is 1. or 2., then (a1) If option-spec doesn't require an argument, then
#t: (a2) If option-spec requires one argument, then the value of the argument: (a3) If option-spec requires more than one argument, the list of the values of the arguments. (b) If the bind-spec is 3. or 4., then callback is called with the value(s) of arguments, and its return value.
We’ll explain the details of option-spec later.
As a special case, var can be
#f, in which case
the value is ignored. It is only useful for side effects in
If the corresponding option is not given in args,
var is bound to default if it is given, or
The last bind-spec may be the form 5 or 6. in which case
the clause is selected when no other option-spec matches
a given command-line option.
In the form 5, handler will be called with three arguments;
the given option, a list of remaining command-line arguments,
and a continuation procedure. The handler
is supposed to handle the given option, and it may call the
continuation procedure with the remaining arguments to continue
processing, or it may return a list of arguments which will
be treated as non-optional command-line arguments.
The form 6 is a shorthand notion of
(else => (lambda formals body ...)).
The bind-spec list can be an improper list, whose last cdr is a symbol. In which case, a list of the rest of the command-line arguments is bound to the variable named by the symbol.
Note that the default, callback, and forms in
clause is evaluated outside of the scope of binding of vars
(as the name
getopt_long implementation in C,
let-args does not permute the given command-line arguments.
It stops parsing when it encounters a non-option argument (argument without
starting with a minus sign).
If the parser encounters an argument with only two minus signs ‘
it stops argument parsing and returns a list of arguments after ‘
After all the bindings is done, body … are evaluated. Body may began with internal define forms.
option-spec is a string that specifies the name of the option and
how the option takes the arguments. An alphanumeric characters, underscore,
plus and minus sign is allowed for option’s names, except that
minus sign can’t be the first character, i.e. the valid option name
matches a regexp
If the option takes argument(s), it can be specified by attaching equal character and a character (or characters) that represents the type of the argument(s) after the name. The option can take more than one arguments. The following characters are recognized as a type specifier of the option’s argument.
Real number (coerced to flonum).
Symbol (argument is converted by
Let’s see some examples of option-spec:
Specifies option name, that doesn’t take any argument.
Option name takes one argument, and it is passed as a string.
Option name takes one argument, and it is passed as an exact integer.
Option name takes two arguments, both string.
Option name takes three integer arguments.
Option name takes two arguments, the first is a string and the second is a number.
If the option has alternative names, they can be concatenated by "|".
For example, an option spec
"h|help" will match both
"h" and "help".
In the command line, the option may appear with preceding
single or double minus signs. The option’s argument may be combined
by the option itself with an equal sign. For example, all the following
command line arguments match an option spec
-prefix /home/shiro -prefix=/home/shiro --prefix /home/shiro --prefix=/home/shiro
let-args encounters an argument that cannot be
processed as specified by option specs, an error of condition type
<parseopt-error> is raised. The cases include
when a mandatory option argument is missing, or when
an option argument has a wrong type.
(let-args '("-a" "foo") ((a "a=i")) ; option a requires integer (list a)) ⇒ parseopt-error
Note that this condition is about parsing the given args. If an invalid option-spec is given, an ordinary error is thrown.
This example is taken from
The mode option takes numbers in octal, so it
uses the callback procedure to convert it.
See also the
else clause how to handle unrecognized option.
(let-args (cdr args) ((#f "c") ;; ignore for historical reason (mkdir "d|directory") (mode "m|mode=s" #o755 => (cut string->number <> 8)) (owner "o|owner=s") (group "g|group=s") (srcdir "S|srcdir=s") (target "T|target=s") (utarget "U|uninstall=s") (shebang "shebang=s") (verb "v") (dry "n|dry-run") (#f "h|help" => usage) (else (opt . _) (print "Unknown option : " opt) (usage)) . args) ...)
The next example is a small test program to show the usage of
else clause. It gathers all options into the variable r,
except that when it sees
-c it stops argument processing and
binds the rest of the arguments to restargs.
(use gauche.parseopt) (define (main args) (let1 r '() (let-args (cdr args) ((else (opt rest cont) (cond [(equal? opt "c") rest] [else (push! r opt) (cont rest)])) . restargs) (print "options: " (reverse r)) (print "restargs: " restargs) 0)))
Sample session of the above script (suppose it is saved as example).
$ ./example -a -b -c -d -e foo options: (a b) restargs: (-d -e foo) $ ./example -a -b -d -e foo options: (a b d e) restargs: (foo)
The followings are lower-level API used to build
args is an expression that contains a list of command-line arguments.
This macro scans the command-line options (an argument that begins with
-’) and processes it as specified in option-clauses, then
returns the remaining arguments.
Each option-clause is consisted by a pair of option-spec and its action.
If a given command-line option matches one of option-spec, then the associated action is evaluated. An action can be one of the following forms.
bind-spec body …
bind-spec is a proper or dotted list of variables like lambda-list. The option’s arguments are bound to bind-spec, then then body … is evaluated.
If a command-line option matches option-spec, calls a procedure proc with a list of the option’s arguments.
If a symbol
else is at the position of option-spec,
the clause is selected when no other option clause matches a given
command-line option. Three “arguments” are associated to
the clause; the unmatched option, the rest of arguments, and
a procedure that represents the option parser.
This is a lower-level interface. option-clauses are the
parse-options. This macro returns a procedure
that can be used later to parse the command line options.
The returned procedure takes one required argument and one
optional argument. The required argument is a list of strings,
for given command-line arguments. The optional argument may
be a procedure that takes more than three arguments, and if given,
the procedure is used as if it is the body of
else option clause.