|
synopsis − parse command line options into Bash
(and others) code |
|
synopsis [options] usages
parse arguments |
|
The purpose of this set of commands is to help the developer in the tedious and repetitive task of parsing the actual arguments of a shell command. Synopsis, usage, and match significantly reduce the effort that is required to implement a set of features commonly needed when implementing shell commands (programmed in Bash or other scripting languages). Specifically: |
|
- |
to accept options and arguments |
|
independently of their ordering; |
|
- |
to test the well-formedness of arguments either with the Bash built-in test, with regular expressions and with the external command file. |
|||
|
- |
to automatically generate a standard help message when one of ’-h’, ’--help’, or ’-?’ is given as an option or when the command is invoked with malformed arguments; |
|||
|
- |
to automatically expand lists of options written in the condensed syntax (e.g. ’tar -cvzf’ reads ’tar -c -v -z -f’). |
|
While the external command synopsis is a generic compiler, the shell functions usage and match are specialized for the target language Bash. Both encapsulate and manage a call of synopsis. Using these functions the output is not printed on stdout, but is directly interpreted by the internal command source, affecting in this way the current shell environment. Please notice that except for the difference outlined above, the behaviour of usage and match is the same of synopsis. Therefore, the examples given in the rest of this manual are equally applicable to all the commands. |
|
synopsis |
|
The command synopsis parses the arguments according to the set of specified usages, then it builds a source code in the target language (by default Bash) and prints the generated code on stdout. The generated code will fit the given arguments into the appropriate capture variables defined by the usages. For instance, the call: synopsis ’a?’ ’b?’ ’c?’ ’!ARG’ parse -b -a /etc/profile prints the following code on stdout: OPTION_b=1 Additionally, the command synopsis is able to automatically generate a minimal help about the usage of the script or the function where synopsis is used. This feature is meant for freeing the developer of the task of writing basic help messages, usually associated to the options ’-h’, ’--help’, or ’-?’. Actually, synopsis reads the given usages in order to automatically generate the help message whenever one of the options ’-h’, ’--help’, or ’-?’ appears among the given arguments. The sole exception to this behaviour is when the developer explicitly specify a different treatment of these options. For instance, the call: synopsis -n mycommand ’o?’ ’-yes?’ ’?ARG1:d’ ’!ARG2:f’ parse -h prints the following message on stderr: Usage: mycommand [-o] [--yes] [<dir>] <file> |
|
usage |
|
The function usage is intended to be called at the
beginning of a script or a function, simply using
"$@" in place of arguments. In this way,
the well-formedness of the actual arguments is checked
w.r.t. to the expected usages. When this matching
succeed, the actual arguments are fitted into variables
which will be used in the rest of the script or
function. |
|
match |
|
The meaning of match is very close to usage. Abstracting from their syntax, the main difference between them is the role of the stdin. While usage reads its stdin only for providing help informations to the user, match searches the actual arguments in the stdin when arguments and the keyword with are both omitted in the command line. In this way, match may be directly used in a Bash pipe, while usage needs to be used with the command xargs. |
|
The commands synopsis, usage and match exit with status 0 if usages is correctly defined and if the arguments successfully fit into the expected usages. They exit with a status greater than 0 if errors occur. |
|
The options of synopsis, usage and
match which no need an argument, must be intended as
boolean switches and they are disable by default. |
|
Behaviour tuning |
|
The following options alter the behaviour of the command. |
|
−n name |
|
Set the name of the script or function for which we are defining the usage. This name will appear in the help message explaining the correct synopsis. The commands usage and match automatically set this value to the name of the script or function in which they are contained. |
|
−p |
When errors occur, print on the stderr a human readable message explaining briefly the expected usages. |
|||
|
−r |
Reverse both the arguments and the usages description. Activating this option, the sequence of actuals arguments will be read and interpreted from the last to the first. |
|||
|
−s |
Suppress parsing error messages. |
|
−t language |
|
Set the target programming language (only for synopsis). The output fitting the arguments into the capture variables will be written in this language. Currently, Bash is the unique supported language. |
|
−x |
Exit the current shell on error (only for usage and match). |
|
Bash code tuning |
|
The following options may be used only when the target language is Bash. Otherwise are not meaningful. They allow to improve the Bash code resulting from the parsing process. |
|
−a |
Use Bash arrays instead of simple variables for containing sequences of arguments (separated by a delimiter). |
|||
|
−l |
First declare local all capture variables. This option is suitable in writing functions in order to avoid conflicts with global homonymous variables. |
|
−d delimiter |
|
Delimiter for all Bash variables expected to contain a sequence of arguments. This kind of variables are related with a capture directive with the operators ’*’ or ’+’ (see the USAGE section below). The delimiter by default is the blank character, and the behaviour by default is to escape all blank characters occurring in the arguments fitting the variables. Defining a new delimiter one disable this behaviour: arguments will be placed just as they are in the variables and will be separated by the new delimiter. This option is not meaningful when the switch -a (arrays) is enable. |
|
−e |
Export all capture variables in the environment (by the internal command export). |
|||
|
−u |
First unset all capture variables. This option is suitable in writing scripts in order to avoid conflicts with homonymous variables in the shell environment. |
|
This section describe the syntax and the meaning of the arguments and the usages. |
|
Arguments |
|
The arguments are simply an arbitrary sequence of words. However, one make here the most of the expansion mechanisms provided by Bash. Actually, typically arguments are "$@" (especially for usage) or * (especially for match). |
|
Usages |
|
In the Unix world, the actual arguments of a command are
commonly separate in three classes. Each argument may be an
option, an option-related argument or a
stand-alone argument. For instance, in the following
call of the well-known tar command: Syntax of a directive directive ::=
[optname]operator[varname][:testexpr][=regexpr] For instance, the capture directive ’o?DEST:f=[a-z]*.txt’ define a variable DEST appointed to capture the argument related to the option -o, if both (the option and its argument) will be found among the actual arguments. The symbol ? means that the presence of the pair -o <argument> among the actual arguments is optional, not mandatory. Because the directive contains a varname, if the option -o is encoutered, it must be followed by an <argument> which will be stored precisely in this varname. Moreover, this argument must be checked. Firstly, it must satisfy the Bash command ’test -f’ (see ’man test’ for more details). Secondly, it must exactly (because =) match the regular expression [a-z]*.txt. The directive matches, and the variable DEST is affected, only if the argument satisfy all conditions. The operator of a directive specify if the presence of the stand-alone option, the option and its argument, or the stand-alone argument is optional (?), mandatory (!), multiple (*), or multiple but almost one (+): operator ::= ? | ! | * |
+ | *(range) |
+(range) Syntax of a kit kit ::= directive [kit] A kit allow to define a set of allowed and/or request
options, option-related and stand-alone arguments
abstracting the order of appearance in the command line. For
instance, suppose to call the command usage at the
beginning of a script or function named
’mycommand’: A kit is an ordered set of directives. When several
directives refer to the same option (for instance
’o?D:d’ and ’o?F:f’) or refer to
stand-alone arguments (for instance ’*D:d’ and
’*F:f’), we will say that they have the same
domain. In this case, the order of appearence in the
kit became relevant because it express the priority between
the directives of the same domain. Actually, parsing actual
arguments with a kit, we will try to match a directive from
the left to the right of the kit. For instance, the
call: Given an actual argument, we will say that a kit captures the argument if it contains a directive that capture it. We will say that a kit is satisfied by a sequence of actual arguments if it capture all the arguments of the sequence satisfying the directives as many time as requested by the operators ! (one time), + (almost one time), *(range) and +(range) (a number of times in the range). Otherwise we will say that the kit fails. Syntax of an usage We will say that an usage is satisfied by a sequence of actual arguments if the sequence may be divided into sub-sequences wich satisfy the sequence of kits constituting the usage. Otherwise we will say that the usage fails. Syntax of alternative usages Several usages may be defined using the keyword or: usages ::= usage [or usages] The symbol + may be used instead of the keyword or. Given a sequence of actual arguments, the or-separated list of usages are tryed from the left to the right, searching for the first usage wich can be satisfied by the actual arguments. |
|
(1) Forbidding options |
|
Suppose a script requiring only stand-alone arguments. We can begin writing: #!/bin/bash In this way, all the given actual arguments will be put into the variable ARGS. Options, which are arguments beginning with a dash, will be forbidden because there isn’t any directive starting with an option name. In the rest of the code, the developer will use the variable ARGS, for instance, as follow: ... |
|
(2) Classifying names in a directory hierarchy |
|
The following command fits the sequences of the regular file names and directory names of the current directory hierarchy respectively into the variables F and D: find | match ’*F:f’ ’*D:d’ ’*TRASH’ |
|
directive ::= varname |
|
Example: a wrapper for find |
|
This wrapper enable the user to call the command find with an unique argument. If this name doesn’t exist in the current working directory, find returns an error. Instead, with this wrapper, this unique and non existing argument will be interpreted as the name to find in the directory hierarchy starting from the current working directory: #!/bin/bash |
|
bash(1) - for the internal command test. getopt(1) |
|
The external command synopsis is a software implemented in OCaml, a functional and strictly typed programming language (see http://caml.inria.fr/), in order to minimize the number of bugs. A large number of bugs has been already discovered and corrected at the compile-time. Anyway, you are encouraged to use this program, which is delivered without any warranty, in order to discover inevitable survivors. |
|
Copyright © 2006 Jean-Vincent Loddo Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies. Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one. Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions, except that this permission notice may be stated in a translation approved by the Free Software Foundation, Inc. |