diff options
Diffstat (limited to 'doc/ref/script-getopt.texi')
-rw-r--r-- | doc/ref/script-getopt.texi | 435 |
1 files changed, 435 insertions, 0 deletions
diff --git a/doc/ref/script-getopt.texi b/doc/ref/script-getopt.texi new file mode 100644 index 000000000..474394af7 --- /dev/null +++ b/doc/ref/script-getopt.texi @@ -0,0 +1,435 @@ +@page +@node Command Line Handling +@chapter Handling Command Line Options and Arguments + +@c This chapter was written and contributed by Martin Grabmueller. + +The ability to accept and handle command line arguments is very +important when writing Guile scripts to solve particular problems, such +as extracting information from text files or interfacing with existing +command line applications. This chapter describes how Guile makes +command line arguments available to a Guile script, and the utilities +that Guile provides to help with the processing of command line +arguments. + +@menu +* Command Line Args:: Using command line arguments. +* getopt-long:: The (ice-9 getopt-long) module. +@end menu + + +@node Command Line Args +@section Using Command Line Arguments + +When a Guile script is invoked, Guile makes the command line arguments +accessible via the procedure @code{command-line}, which returns the +arguments as a list of strings. + +For example, if the script + +@example +#! /usr/local/bin/guile -s +!# +(write (command-line)) +(newline) +@end example + +@noindent +is saved in a file @file{cmdline-test.scm} and invoked using the command +line @code{./cmdline-test.scm bar.txt -o foo -frumple grob}, the output +is + +@example +("./cmdline-test.scm" "bar.txt" "-o" "foo" "-frumple" "grob") +@end example + +If the script invocation includes a @code{-e} option, specifying a +procedure to call after loading the script, Guile will call that +procedure with @code{(command-line)} as its argument. So a script that +uses @code{-e} doesn't need to refer explicitly to @code{command-line} +in its code. For example, the script above would have identical +behaviour if it was written instead like this: + +@example +#! /usr/local/bin/guile \ +-e main -s +!# +(define (main args) + (write args) + (newline)) +@end example + +(Note the use of the meta switch @code{\} so that the script invocation +can include more than one Guile option: @xref{The Meta Switch}.) + +These scripts use the @code{#!} POSIX convention so that they can be +executed using their own file names directly, as in the example command +line @code{./cmdline-test.scm bar.txt -o foo -frumple grob}. But they +can also be executed by typing out the implied Guile command line in +full, as in: + +@example +$ guile -s ./cmdline-test.scm bar.txt -o foo -frumple grob +@end example + +@noindent +or + +@example +$ guile -e main -s ./cmdline-test2.scm bar.txt -o foo -frumple grob +@end example + +Even when a script is invoked using this longer form, the arguments that +the script receives are the same as if it had been invoked using the +short form. Guile ensures that the @code{(command-line)} or @code{-e} +arguments are independent of how the script is invoked, by stripping off +the arguments that Guile itself processes. + + +@node getopt-long +@section The (ice-9 getopt-long) Module + +A script is free to parse and handle its command line arguments in any +way that it chooses. Where the set of possible options and arguments is +complex, however, it can get tricky to extract all the options, check +the validity of given arguments, and so on. This task can be greatly +simplified by taking advantage of the module @code{(ice-9 getopt-long)}, +which is distributed with Guile. + +The @code{(ice-9 getopt-long)} module exports two procedures: +@code{getopt-long} and @code{option-ref}. + +@itemize @bullet +@item +@code{getopt-long} takes a list of strings --- the command line +arguments --- and an @dfn{option specification}. It parses the command +line arguments according to the option specification and returns a data +structure that encapsulates the results of the parsing. + +@item +@code{option-ref} then takes the parsed data structure and a specific +option's name, and returns information about that option in particular. +@end itemize + +To make these procedures available to your Guile script, include the +expression @code{(use-modules (ice-9 getopt-long))} somewhere near the +top, before the first usage of @code{getopt-long} or @code{option-ref}. + +@menu +* getopt-long Example:: A short getopt-long example. +* Option Specification:: How to write an option specification. +* Command Line Format:: The expected command line format. +* getopt-long Reference:: Full documentation for @code{getopt-long}. +* option-ref Reference:: Full documentation for @code{option-ref}. +@end menu + + +@node getopt-long Example +@subsection A Short getopt-long Example + +This subsection illustrates how @code{getopt-long} is used by presenting +and dissecting a simple example. The first thing that we need is an +@dfn{option specification} that tells @code{getopt-long} how to parse +the command line. This specification is an association list with the +long option name as the key. Here is how such a specification might +look: + +@lisp +(define option-spec + '((version (single-char #\v) (value #f)) + (help (single-char #\h) (value #f)))) +@end lisp + +This alist tells @code{getopt-long} that it should accept two long +options, called @emph{version} and @emph{help}, and that these options +can also be selected by the single-letter abbreviations @emph{v} and +@emph{h}, respectively. The @code{(value #f)} clauses indicate that +neither of the options accepts a value. + +With this specification we can use @code{getopt-long} to parse a given +command line: + +@lisp +(define options (getopt-long (command-line) option-spec)) +@end lisp + +After this call, @code{options} contains the parsed command line and is +ready to be examined by @code{option-ref}. @code{option-ref} is called +like this: + +@lisp +(option-ref options 'help #f) +@end lisp + +@noindent +It expects the parsed command line, a symbol indicating the option to +examine, and a default value. The default value is returned if the +option was not present in the command line, or if the option was present +but without a value; otherwise the value from the command line is +returned. Usually @code{option-ref} is called once for each possible +option that a script supports. + +The following example shows a main program which puts all this together +to parse its command line and figure out what the user wanted. + +@lisp +(define (main args) + (let* ((option-spec '((version (single-char #\v) (value #f)) + (help (single-char #\h) (value #f)))) + (options (getopt-long args option-spec)) + (help-wanted (option-ref options 'help #f)) + (version-wanted (option-ref options 'version #f))) + (if (or version-wanted help-wanted) + (begin + (if version-wanted + (display "getopt-long-example version 0.3\n")) + (if help-wanted + (display "\ +getopt-long-example [options] + -v, --version Display version + -h, --help Display this help +"))) + (begin + (display "Hello, World!") (newline))))) +@end lisp + + +@node Option Specification +@subsection How to Write an Option Specification + +An option specification is an association list (@pxref{Association +Lists}) with one list element for each supported option. The key of each +list element is a symbol that names the option, while the value is a +list of option properties: + +@lisp +OPTION-SPEC ::= '( (OPT-NAME1 (PROP-NAME PROP-VALUE) @dots{}) + (OPT-NAME2 (PROP-NAME PROP-VALUE) @dots{}) + (OPT-NAME3 (PROP-NAME PROP-VALUE) @dots{}) + @dots{} + ) +@end lisp + +Each @var{opt-name} specifies the long option name for that option. For +example, a list element with @var{opt-name} @code{background} specifies +an option that can be specified on the command line using the long +option @code{--background}. Further information about the option --- +whether it takes a value, whether it is required to be present in the +command line, and so on --- is specified by the option properties. + +In the example of the preceding subsection, we already saw that a long +option name can have a equivalent @dfn{short option} character. The +equivalent short option character can be set for an option by specifying +a @code{single-char} property in that option's property list. For +example, a list element like @code{'(output (single-char #\o) @dots{})} +specifies an option with long name @code{--output} that can also be +specified by the equivalent short name @code{-o}. + +The @code{value} property specifies whether an option requires or +accepts a value. If the @code{value} property is set to @code{#t}, the +option requires a value: @code{getopt-long} will signal an error if the +option name is present without a corresponding value. If set to +@code{#f}, the option does not take a value; in this case, a non-option +word that follows the option name in the command line will be treated as +a non-option argument. If set to the symbol @code{optional}, the option +accepts a value but does not require one: a non-option word that follows +the option name in the command line will be interpreted as that option's +value. If the option name for an option with @code{'(value optional)} +is immediately followed in the command line by @emph{another} option +name, the value for the first option is implicitly @code{#t}. + +The @code{required?} property indicates whether an option is required to +be present in the command line. If the @code{required?} property is +set to @code{#t}, @code{getopt-long} will signal an error if the option +is not specified. + +Finally, the @code{predicate} property can be used to constrain the +possible values of an option. If used, the @code{predicate} property +should be set to a procedure that takes one argument --- the proposed +option value as a string --- and returns either @code{#t} or @code{#f} +according as the proposed value is or is not acceptable. If the +predicate procedure returns @code{#f}, @code{getopt-long} will signal an +error. + +By default, options do not have single-character equivalents, are not +required, and do not take values. Where the list element for an option +includes a @code{value} property but no @code{predicate} property, the +option values are unconstrained. + + +@node Command Line Format +@subsection Expected Command Line Format + +In order for @code{getopt-long} to correctly parse a command line, that +command line must conform to a standard set of rules for how command +line options are specified. This subsection explains what those rules +are. + +@code{getopt-long} splits a given command line into several pieces. All +elements of the argument list are classified to be either options or +normal arguments. Options consist of two dashes and an option name +(so-called @dfn{long} options), or of one dash followed by a single +letter (@dfn{short} options). + +Options can behave as switches, when they are given without a value, or +they can be used to pass a value to the program. The value for an +option may be specified using an equals sign, or else is simply the next +word in the command line, so the following two invocations are +equivalent: + +@example +$ ./foo.scm --output=bar.txt +$ ./foo.scm --output bar.txt +@end example + +Short options can be used instead of their long equivalents and can be +grouped together after a single dash. For example, the following +commands are equivalent. + +@example +$ ./foo.scm --version --help +$ ./foo.scm -v --help +$ ./foo.scm -vh +@end example + +If an option requires a value, it can only be grouped together with other +short options if it is the last option in the group; the value is the +next argument. So, for example, with the following option +specification --- + +@lisp +((apples (single-char #\a)) + (blimps (single-char #\b) (value #t)) + (catalexis (single-char #\c) (value #t))) +@end lisp + +@noindent +--- the following command lines would all be acceptable: + +@example +$ ./foo.scm -a -b bang -c couth +$ ./foo.scm -ab bang -c couth +$ ./foo.scm -ac couth -b bang +@end example + +But the next command line is an error, because @code{-b} is not the last +option in its combination, and because a group of short options cannot +include two options that both require values: + +@example +$ ./foo.scm -abc couth bang +@end example + +If an option's value is optional, @code{getopt-long} decides whether the +option has a value by looking at what follows it in the argument list. +If the next element is a string, and it does not appear to be an option +itself, then that string is the option's value. + +If the option @code{--} appears in the argument list, argument parsing +stops there and subsequent arguments are returned as ordinary arguments, +even if they resemble options. So, with the command line + +@example +$ ./foo.scm --apples "Granny Smith" -- --blimp Goodyear +@end example + +@noindent +@code{getopt-long} will recognize the @code{--apples} option as having +the value "Granny Smith", but will not treat @code{--blimp} as an +option. The strings @code{--blimp} and @code{Goodyear} will be returned +as ordinary argument strings. + + +@node getopt-long Reference +@subsection Reference Documentation for @code{getopt-long} + +@deffn procedure getopt-long args grammar +Parse the command line given in @var{args} (which must be a list of +strings) according to the option specification @var{grammar}. + +The @var{grammar} argument is expected to be a list of this form: + +@code{((@var{option} (@var{property} @var{value}) @dots{}) @dots{})} + +where each @var{option} is a symbol denoting the long option, but +without the two leading dashes (e.g. @code{version} if the option is +called @code{--version}). + +For each option, there may be list of arbitrarily many property/value +pairs. The order of the pairs is not important, but every property may +only appear once in the property list. The following table lists the +possible properties: + +@table @asis +@item @code{(single-char @var{char})} +Accept @code{-@var{char}} as a single-character equivalent to +@code{--@var{option}}. This is how to specify traditional Unix-style +flags. +@item @code{(required? @var{bool})} +If @var{bool} is true, the option is required. @code{getopt-long} will +raise an error if it is not found in @var{args}. +@item @code{(value @var{bool})} +If @var{bool} is @code{#t}, the option accepts a value; if it is +@code{#f}, it does not; and if it is the symbol @code{optional}, the +option may appear in @var{args} with or without a value. +@item @code{(predicate @var{func})} +If the option accepts a value (i.e. you specified @code{(value #t)} for +this option), then @code{getopt-long} will apply @var{func} to the +value, and throw an exception if it returns @code{#f}. @var{func} +should be a procedure which accepts a string and returns a boolean +value; you may need to use quasiquotes to get it into @var{grammar}. +@end table +@end deffn + +@code{getopt-long}'s @var{args} parameter is expected to be a list of +strings like the one returned by @code{command-line}, with the first +element being the name of the command. Therefore @code{getopt-long} +ignores the first element in @var{args} and starts argument +interpretation with the second element. + +@code{getopt-long} signals an error if any of the following conditions +hold. + +@itemize @bullet +@item +The option grammar has an invalid syntax. + +@item +One of the options in the argument list was not specified by the +grammar. + +@item +A required option is omitted. + +@item +An option which requires an argument did not get one. + +@item +An option that doesn't accept an argument does get one (this can only +happen using the long option @code{--opt=@var{value}} syntax). + +@item +An option predicate fails. +@end itemize + + +@node option-ref Reference +@subsection Reference Documentation for @code{option-ref} + +@deffn procedure option-ref options key default +Search @var{options} for a command line option named @var{key} and +return its value, if found. If the option has no value, but was given, +return @code{#t}. If the option was not given, return @var{default}. +@var{options} must be the result of a call to @code{getopt-long}. +@end deffn + +@code{option-ref} always succeeds, either by returning the requested +option value from the command line, or the default value. + +The special key @code{'()} can be used to get a list of all +non-option arguments. + + +@c Local Variables: +@c TeX-master: "guile.texi" +@c End: |