This is POSIX-compliant code for parsing shell script arguments. It helps you focus on writing the script logic by separating argument parsing and basic validation.
Include the `parser.sh` file in your script using [`dot`](https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#dot) or [`source`](https://www.gnu.org/software/bash/manual/bash.html#index-source).
```bash
#!/usr/bin/env sh
. parser.sh
```
Or copy the contents of the `parser.sh` file into your script.
## Usage
The parser provides functions for working with arguments. They become available after passing all script arguments to the parser using `_parse`:
```bash
#!/usr/bin/env sh
. parser.sh
# In most cases, all script arguments are passed to _parse: $@.
_parse --foo bar baz
_is_used_option '--foo' && echo "Option 'foo' is used"
_get_option_args_count '--foo'
_get_option_arg '--foo' 2
```
```
Option 'foo' is used
2
baz
```
### What's next?
1. [Learn about the argument syntax.](#argument-syntax-conventions)
2. [Configure the parser to suit your needs.](#configuration)
3. [Map commands.](#_map_command)
4. [Map options.](#_map_option)
5. [Learn about the functions for working with parsing results.](#functions-for-working-with-parsing-results)
## Argument Syntax Conventions
The argument syntax is based on, but does not fully comply with, the conventions used in POSIX <sup>[1](https://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html), [2](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html)</sup>.
### General
- Commands, options, and positional arguments are separated by spaces.
- All script arguments are case-sensitive.
### Commands
A command typically represents the core action performed by the script: `run`, `build`, `issue`, etc. If the script is designed to perform a single action, a command is generally not required.
- A script may or may not accept a command.
- If the script accepts a command, it must be the first argument.
- A command can contain Latin letters, digits, `-`, and `_`.
### Positional Arguments
- Positional arguments are placed after the command, if present.
- The presence and number of positional arguments are determined by the script's logic.
- After the special argument --, all arguments are considered positional. This allows passing arguments that start with a dash and might be confused with options.
### Options
Options are script parameters. Each option has at least one alias by which it can be specified in the command line. Options often have both short and long aliases, such as `-h` and `--help`.
- Short aliases start with `-` and consist of a single Latin letter;
- Long aliases start with `--` and consist of Latin letters, digits, `-`, and `_`;
- Short aliases can be used individually or combined. For example, `-b -a -r` is equivalent to `-bar`;
- Options may have arguments. The presence and number of arguments are determined by the specific option and the script's logic.
## Configuration
Configuration is defined by assigning values to variables before using the parser. For example:
```bash
_accept_command=true
```
Configuration variables must be assigned before calling `_parse`.
| Name | Default Value | Description |
| --- | --- | --- |
| _accept_command | `auto` | `any` — The script accepts a command.<br>`none` — The script does not accept a command.<br>`mapped_only` — The script accepts only a mapped command.<br>`auto` — The script accepts a command if at least one has been mapped. |
| _accept_options | `auto` | `any` — The script accepts any options.<br>`none` — The script does not accept any options.<br>`mapped_only` — The script accepts only mapped options.<br>`auto` — The script accepts only mapped options if at least one has been mapped. Otherwise, it accepts any options. |
| _default_max_positional_args | | Maximum number of positional arguments. A different value can be set for each command (see [_map_command](#_map_command)). |
| _default_min_positional_args | `0` | Minimum number of positional arguments. A different value can be set for each command (see [_map_command](#_map_command)). |
| _default_positional_arg_variable || Name of the variable that will store the single positional argument. Implicitly sets `_default_max_positional_args` and `_default_min_positional_args` to 1. Command-specific values for `max_args` and `arg_variable` disables this behavior. |
| _options_combination_allowed | `true` | `true` — Combining short option aliases into combinations is allowed.<br>`false` — Combining short option aliases is not allowed. |
| _options_combination_args_allowed | `true` | `true` — Passing arguments to the last option in a combination is allowed.<br>`false` — Passing arguments to the last option in a combination is not allowed. |
| _positional_args_placement | `any` | `any` — Positional arguments can be placed anywhere, including mixed with options.<br>`before_options` — Positional arguments are placed before options.<br>`after_options` — Positional arguments are placed after options. |
## Functions
#### _parse
Parses the provided arguments. Typically, takes all command-line arguments `$@` as input.
```bash
# Parser configuration, command and option mapping above
_parse $@
# Script logic below
```
### Functions for command and option mapping
Mapping functions are used to specify the available commands and options of the script, as well as for their basic validation. Mapping functions must be used before calling `_parse`.
#### _map_command
Maps a command. Takes key-value pairs as arguments. Key and values list are separated by `_mapping_key_value_delimiter`.
| Key | Description |
| --- | --- |
| name | Command name. Required key. |
| description | Command description. Currently not used. |
| min_args | Minimum number of positional arguments when using the command. |
| max_args | Maximum number of positional arguments when using the command. |
Maps an option. Takes key-value pairs as arguments. Key and values list are separated by `_mapping_key_value_delimiter`. Values of the same key are separated by `_mapping_values_delimiter`.
| Key | Description |
| --- | --- |
| aliases | List of option aliases. Required key. |
| description | Option description. Currently not used. |
| min_args | Minimum number of option arguments. |
| max_args | Maximum number of option arguments. |