-
Notifications
You must be signed in to change notification settings - Fork 1
UnixShellAPI
This document describes the functions and variables generated by [build-shellscript](https://github.com/noresources/ns-xml/wiki/build-shellscript)
- [UNIX shell command line parser API](#UNIX shell command line parser API)
- API
-
Tweaking
- [Subcommand option variable names](#Subcommand option variable names)
- Preprocessing
- [Code snippets](#Code snippets)
- [Calling the parser](#Calling the parser)
- [Accessing positional arguments](#Accessing positional arguments)
- [Dealing with exclusive groups](#Dealing with exclusive groups)
Any undocumented function you may find in a generated script should have to be considered as a private function.
Name | Parameters | Return value | Description | |
---|---|---|---|---|
`parse()` | `argv` | The number of error encountered | Parse the command line arguments and fill the options bound variable and the `$parser_values` array | |
`parse_displayerrors()` | None | 0 | Output all errors generated while parsing the command line | |
`usage()` | `[topic]` | 0 | Print the program help string, generated from the information gathered in the XML program description file. if *`topic`* is the name of a subcommand, `usage` will display the program's subcommand help string. |
Name | Type | Description | |
---|---|---|---|
`$parser_shell` | string | The name of the shell interpreter (example: `bash`) | |
`$parser_startindex` | int | Indicates what is the first valid index in a array variable (0 in [bash](http://www.gnu.org/software/bash/), 1 in [zsh](http://www.zsh.org/)) | |
`$parser_subcommand` | string | Name of the selected program subcommand. The name is always the one described by the `<name />` element even if one of it aliases was used on the command line | |
`$parser_values` | array | Array of positional arguments which are not subcommand names, option names, option arguments nor special markers |
For each program option defined in the program interface XML definition file where a variable name is defined,
#!xml
<!-- (...) -->
<databinding>
<variable>displayHelp</variable>
</databinding>
<!-- (...) -->
a shell variable of the same name is created with the following rules
Option type | Variable type | Default value | |
---|---|---|---|
Switch | Boolean | `false` | |
Single argument | String | Value of `<default/>` if any, Empty string otherwise | |
Multi argument | Array | Empty | |
Group | String | Empty string |
After parsing, variables are modified as is
Option type | Value | |
---|---|---|
Switch | `true` if the option is present on the command line | |
Single argument | Value of the option argument if the option is present on the command line. | |
Multi argument | Values of the option arguments if the option is present on the command line. | |
Group | If the group is exclusive: Name of the first sub option bound variable name found on the command line; Otherwise, an empty string |
The program interface definition schema allows options of two subcommands to share the same bound variable name. To avoid name aliasing while generating the bash code, the subcommand option variable names can be prefixed with the name of the subcommand using the --prefix-sc-variables
option of [build-shellscript](https://github.com/noresources/ns-xml/wiki/build-shellscript)
If the subcommand sub
has an option with a bound variable name myVar
, the variable name will become sub_myVar
.
Any option's bound variable can be modified prior to calling the parse
function. This can be useful to set a default value which depends on dynamic data
#!bash
# ... auto generated function and variables are above
# Set a default value for ${outputFile} using the current date
outputFile="/tmp/filename-$(date +%F).tmp"
# Call parser
if ! parse "${@}"
then
exit 1
fi
echo "outputFile = ${outputFile}"
exit 0
We assume the program has a --help
switch option with a bound variable name displayHelp
#!xml
<!-- (...) -->
<switch id="prg.option.displayHelp">
<databinding>
<variable>displayHelp</variable>
</databinding>
<documentation>
<abstract>Display program usage</abstract>
</documentation>
<names>
<long>help</long>
</names>
<ui mode="disabled" />
</switch>
<!-- (...) -->
The first lines of your program should looks like
#!bash
# Call the parser
if ! parse "${@}"
then
# If an error occurs but the --help switch is present, just print help
if ${displayHelp}
then
usage ${parser_subcommand}
exit 0
fi
# else, display errors and exit
parse_displayerrors
exit 1
fi
# Handle --help option
if ${displayHelp}
then
usage ${parser_subcommand}
exit 0
fi
# The real work begins...
Let's say we are re-coding the mv
utility. The n-1 positional arguments are the input files, the last positional argument is the output file or folder
#!xml
<!-- (...) -->
<!-- some options -->
<!-- (...) -->
<values>
<other>
<type>
<path access="r" />
</type>
</other>
</values>
<!-- (...) -->
To process positional arguments, use the ${parser_values}
array
#!bash
total_values=${#parser_values[*]}
if [ ${total_values} -lt 2 ]
then
echo "Missing arguments"
exit 2
fi
is_multi_copy=false
if [ ${total_values} -gt 2 ]
then
is_multi_copy=true
fi
# This is for Bash
output_index=$(expr ${total_values} - 1)
# And this is for Zsh
# output_index=${total_values}
output=${parser_values[${output_index}]}
if ${is_multi_copy} && [ ! -d "${output}" ]
then
echo "${output} have to be a folder"
exit 1
fi
for ((i=0;${i}<${output_index};i++))
do
echo "Moving ${parser_values[${i}]} to ${output}"
done
Three single-argument options in an exclusive group.
#!xml
<group type="exclusive">
<databinding>
<variable>groupVariable</variable>
</databinding>
<options>
<argument>
<databinding>
<variable>firstArg</variable>
</databinding>
<names>
<long>basic-argument</long>
</names>
</argument>
<argument>
<databinding>
<variable>secondArg</variable>
</databinding>
<names>
<long>string-argument</long>
</names>
<type>
<string/>
</type>
</argument>
<argument>
<databinding>
<variable>thirdArg</variable>
</databinding>
<names>
<long>argument-with-default</long>
</names>
<default>Default value</default>
</argument>
</options>
<group>
Since ${thirdArg}
will always have a non-null value (due to the <default/>
clause), we can't rely on variable emptyness to know which option the user selects. We have to use the group bound variable ${groupVariable}
#!bash
case "${groupVariable}" in
"firstArg")
echo "You select the first option: ${firstArg}"
;;
"secondArg")
echo "You select the second option: ${secondArg}"
;;
"thirdArg")
echo "You select the third option: ${thirdArg}"
;;
*)
echo "Well, since the group is not required, it's ok to select none"
;;
esac