# getoptlong.sh

**Note:** This manual is generated by AI and may contain inaccuracies. Please use it with caution and refer to the source code or examples for definitive information.

`getoptlong.sh` is a Bash library for parsing command-line options in shell scripts. It provides a flexible way to handle options including followings.

- Clear and expressive option syntax
- Supports both short options (e.g., `-h`) and long options (e.g., `--help`)
- Allows options and non-option arguments to be freely mixed on the command line (PERMUTE)
- Supports flag type incremental option as well as required arguments, optional arguments, array-type, and hash-type options
- Provides validation for integer, floating-point, and custom regular expression patterns
- Enables registration of callback functions for each option for flexible processing
- Supports multiple calls, which enables to use different options in subcommands or perform own option analysis within functions
- Automatic generation of help option and help messages. Help option is implemented without explicit definition. Help message is generated from the option definition.

## Table of Contents

- [1. Introduction](#1-introduction)
- [2. Installation](#2-installation)
- [3. Basic Usage](#3-basic-usage)
  - [3.1. Simplified Usage (One-liner)](#31-simplified-usage-one-liner)
  - [3.2. Standard Multi-step Usage](#32-standard-multi-step-usage)
    - [3.2.1. Creating the Option Definition Array](#321-creating-the-option-definition-array)
    - [3.2.2. Sourcing the Library](#322-sourcing-the-library)
    - [3.2.3. Initializing getoptlong](#323-initializing-getoptlong)
    - [3.2.4. Parsing Command-Line Arguments](#324-parsing-command-line-arguments)
    - [3.2.5. Setting Parsed Results to Variables](#325-setting-parsed-results-to-variables)
    - [3.2.6. Accessing and Using Variables](#326-accessing-and-using-variables)
- [4. Detailed Option Definition](#4-detailed-option-definition)
  - [4.1. Basic Syntax](#41-basic-syntax)
  - [4.2. Option Types and Type Specifiers](#42-option-types-and-type-specifiers)
    - [4.2.1. Flag Options (No Suffix or `+`)](#421-flag-options-no-suffix-or-)
    - [4.2.2. Required Argument Options (`:`)](#422-required-argument-options--)
    - [4.2.3. Optional Argument Options (`?`)](#423-optional-argument-options--)
    - [4.2.4. Array Options (`@`)](#424-array-options--)
    - [4.2.5. Hash Options (`%`)](#425-hash-options--)
    - [4.2.6. Callback Options (`!`)](#426-callback-options--)
  - [4.3. Specifying Destination Variable Name](#43-specifying-destination-variable-name)
  - [4.4. Value Validation](#44-value-validation)
    - [4.4.1. Integer Validation (`=i`)](#441-integer-validation-i)
    - [4.4.2. Float Validation (`=f`)](#442-float-validation-f)
    - [4.4.3. Custom Regex Validation (`=(<regex>)`](#443-custom-regex-validation-regex)
- [5. Help Message Generation and Customization](#5-help-message-generation-and-customization)
  - [5.1. Automatic Help Option](#51-automatic-help-option)
  - [5.2. Help Message Content](#52-help-message-content)
    - [5.2.1. Option Descriptions (Comments `#`)](#521-option-descriptions-comments-)
    - [5.2.2. Type-Based Automatic Messages](#522-type-based-automatic-messages)
    - [5.2.3. Displaying Initial (Default) Values](#523-displaying-initial-default-values)
    - [5.2.4. Treating Flag Options as Counters](#524-treating-flag-options-as-counters)
  - [5.3. Overall Help Message Format](#53-overall-help-message-format)
    - [5.3.1. Customizing Synopsis (`USAGE` Setting)](#531-customizing-synopsis-usage-setting)
    - [5.3.2. Manual Display with `getoptlong help`](#532-manual-display-with-getoptlong-help)
  - [5.4. Help Message Structure](#54-help-message-structure)
- [6. Advanced Topics](#6-advanced-topics)
  - [6.1. Callback Function Details](#61-callback-function-details)
    - [6.1.1. Normal Callbacks (Post-processing)](#611-normal-callbacks-post-processing)
    - [6.1.2. Pre-processing Callbacks (`--before` / `-b`)](#612-pre-processing-callbacks---before---b)
    - [6.1.3. Error Handling in Callback Functions](#613-error-handling-in-callback-functions)
    - [6.1.4. Custom Validation using Callbacks](#614-custom-validation-using-callbacks)
  - [6.2. Specifying Destination Variable](#62-specifying-destination-variable)
  - [6.3. Option Pass-through](#63-option-pass-through)
  - [6.4. Runtime Configuration Changes (`getoptlong configure`)](#64-runtime-configuration-changes-getoptlong-configure)
  - [6.5. Dumping Internal State (`getoptlong dump`)](#65-dumping-internal-state-getoptlong-dump)
- [7. Command Reference](#7-command-reference)
  - [7.1. `getoptlong init <opts_array_name> [CONFIGURATIONS...]`](#71-getoptlong-init-opts_array_name-configurations)
  - [7.2. `getoptlong parse "$@"`](#72-getoptlong-parse--)
  - [7.3. `getoptlong set`](#73-getoptlong-set)
  - [7.4. `getoptlong callback [-b|--before] <opt_name> [callback_function] ...`](#74-getoptlong-callback--b---before-opt_name-callback_function--)
  - [7.5. `getoptlong configure <CONFIG_PARAM=VALUE> ...`](#75-getoptlong-configure-config_paramvalue--)
  - [7.6. `getoptlong dump [-a|--all]`](#76-getoptlong-dump--a---all)
  - [7.7. `getoptlong help <SYNOPSIS>`](#77-getoptlong-help-synopsis)
- [8. Practical Examples](#8-practical-examples)
  - [8.1. Combining Required Options and Optional Arguments](#81-combining-required-options-and-optional-arguments)
  - [8.2. Script with Subcommands (Simple Version)](#82-script-with-subcommands-simple-version)
  - [8.3. Sample Scripts in `ex/` Directory](#83-sample-scripts-in-ex-directory)
- [9. Configuration Keys](#9-configuration-keys)
- [10. See Also](#10-see-also)

## 1. Introduction

`getoptlong.sh` is a Bash library designed for parsing command-line options within shell scripts. It offers a robust and flexible alternative to the built-in `getopts` command, providing support for GNU-style long options, option permutation, various argument types (required, optional, array, hash), data validation, callback mechanisms, and automatic help message generation.  Its goal is to simplify the often complex task of command-line argument processing in Bash, making scripts more user-friendly and maintainable.

## 2. Installation

You can use `getoptlong.sh` by sourcing it directly from GitHub without downloading the file.

### Using curl

```bash
# Latest stable version (recommended)
source <(curl -fsSL https://raw.githubusercontent.com/tecolicom/getoptlong/dist/getoptlong.sh)

# Specific version
source <(curl -fsSL https://raw.githubusercontent.com/tecolicom/getoptlong/v0.2/getoptlong.sh)

# Latest major version (always gets the newest 0.x release)
source <(curl -fsSL https://raw.githubusercontent.com/tecolicom/getoptlong/v0/getoptlong.sh)
```

### Local Installation

You can also download and use it locally:

```bash
# Download to your project
curl -fsSL https://raw.githubusercontent.com/tecolicom/getoptlong/dist/getoptlong.sh -o getoptlong.sh

# Source from your script
. ./getoptlong.sh
```

## 3. Basic Usage

`getoptlong.sh` offers two primary ways to integrate option parsing into your scripts: a simplified one-liner approach and a standard multi-step approach.

### 3.1. Simplified Usage (One-liner)

For many common use cases, `getoptlong.sh` can be invoked with a single line that sources the library, defines options, parses arguments, and sets variables. This is the quickest way to get started.

**Steps:**

1.  **Define your options array:** Create a Bash associative array (e.g., `OPTS`) that holds your option definitions.

2.  **Source and execute:** Use the `.` (source) command followed by `getoptlong.sh`, the name of your options array, and `"$@"`.

**Example:**

```bash
#!/usr/bin/env bash

# 1. Define the options array

declare -A OPTS=(
    [ trace     | x  ]=  # Simple flag, sets 'trace' variable to 1 if present
    [ debug     | d  ]=0 # Simple flag, with '0' as an initial value
    [ count     | c: ]=1 # Option with a required argument, sets 'count' variable
)

# 2. Source getoptlong.sh, passing the OPTS array and script arguments

. getoptlong.sh OPTS "$@"

# 3. Use the parsed options

(( debug > 0 )) && echo "Debug mode is ON"

# 4. Process non-option parameter

echo "$@"
```

**How it Works:**

When `getoptlong.sh` is sourced with the options array name and arguments (`. getoptlong.sh OPTS "$@"`), it performs the following internally:

*   Sources itself, making its functions available.
*   Initializes using the provided `OPTS` array.
*   Parses the `"$@"` arguments.
*   Sets the corresponding shell variables and updates positional parameters.

This approach is concise and sufficient for many scripts. If you need more control over the parsing process (e.g., custom error handling after parsing, or re-initializing with different options for subcommands), the standard multi-step usage described next might be more suitable.

### 3.2. Standard Multi-step Usage

This method breaks down the process into distinct steps, offering more flexibility.

#### 3.2.1. Creating the Option Definition Array

First, define the options your script will accept as a Bash associative array.  The array name is arbitrary.  For the format of each option key and the available types, refer to Section "4. Detailed Option Definition".

```bash
declare -A OPTS=(
    [verbose |v+ # Increase verbosity (cumulative)       ]=0
    [output  |o: # Specify output file                   ]=/dev/stdout
    [config  |c? # Specify configuration file (optional) ]=
    [library |L@ # Add library path                      ]=()
    [define  |D% # Define a variable (e.g., key=val)     ]=()
)
```

**Note:** A help option (defaulting to `--help`, `-h`) is automatically available.  See Section "5. Help Message Generation and Customization" for details on its behavior and customization. You can also define it explicitly if needed, as shown in the example above.

#### 3.2.2. Sourcing the Library

Next, source the `getoptlong.sh` file from within your script using the `source` command (or the `.` command). This makes the `getoptlong` function and its subcommands available.

```bash
. $(dirname $0)/getoptlong.sh # Replace with the actual path to getoptlong.sh
# Or, if getoptlong.sh is in your execution path:
# . getoptlong.sh
```

#### 3.2.3. Initializing getoptlong

Pass the defined option array to the `getoptlong init` command to initialize the library.

```bash
getoptlong init OPTS
```

During initialization, you can also specify various configurationp parameters that control option parsing behavior. See Section "7.1. `getoptlong init ...`" for details.

Example: Store non-option arguments in the `ARGS` array and prevent the script from exiting on a parse error.

```bash
declare -a ARGS # It's good practice to declare the array specified by PERMUTE beforehand
getoptlong init OPTS PERMUTE=ARGS EXIT_ON_ERROR=0
```

#### 3.2.4. Parsing Command-Line Arguments

Pass all script arguments (`"$@"`) to the `getoptlong parse` command to parse them based on your definitions.

```bash
if ! getoptlong parse "$@"; then
    # Handle parse error (if EXIT_ON_ERROR=0)
    echo "Failed to parse arguments." >&2
    getoptlong help "Usage: $(basename "$0") [options] arguments..." # Display help on error
    exit 1
fi
```

`getoptlong parse` returns an exit code of `0` on successful parsing and non-zero otherwise. If `EXIT_ON_ERROR` is `1` (default), the script will automatically exit on a parse error.

#### 3.2.5. Setting Positional Parameters

After `getoptlong parse` successfully processes the command-line arguments, shell variables for options are automatically set during parsing. The `getoptlong set` command is used with `eval` to update only the positional parameters:

```bash
eval "$(getoptlong set)"
```

This re-sets the script's positional parameters (`$1`, `$2`, etc.) to the remaining non-option arguments as determined by the parsing process (respecting `PERMUTE` behavior if configured). For example, if `myscript --opt val arg1 arg2` was called, after `eval "$(getoptlong set)"`, `$1` would be `arg1` and `$2` would be `arg2`.

#### 3.2.6. Accessing and Using Variables

Option variables are automatically set during `getoptlong parse`. Use these variables in your script to perform actions based on the options.

*   **Variable Assignment Details:**
    *   Flag options (e.g., `[verbose|v]`) set the variable to `1` on first use, increment on subsequent uses.
    *   Array options (e.g., `[library|L@]`) populate a Bash array (e.g., `"${library[@]}"`).
    *   Hash options (e.g., `[define|D%]`) populate a Bash associative array.
    *   Hyphens (`-`) in default option variable names are converted to underscores (`_`) (e.g., `--long-option` results in `$long_option`).

```bash
# If the help option was processed (automatically or manually),
# the script usually exits during 'getoptlong parse' or 'getoptlong set',
# but you can also check explicitly (e.g., for custom help processing).
if [[ -n "${help:-}" ]]; then
    # (Usually not reached if 'getoptlong help' was called)
    # Custom help display processing, etc.
    exit 0
fi

echo "Verbose output level: ${verbose:-0}" # Display 0 if not set

if [[ "$output" != "/dev/stdout" ]]; then
    echo "Output destination: $output"
fi

if [[ -n "${config:-}" ]]; then # Check if config is not an empty string or unset
    echo "Loading configuration file: $config..."
    # source "$config" or other processing
elif [[ -v config ]]; then # If config option was specified but has no value (set to empty string)
    echo "Configuration file specified, but path is missing."
else
    echo "Using default configuration."
fi

if (( ${#library[@]} > 0 )); then
    echo "Library paths:"
    for libpath in "${library[@]}"; do
        echo "  - $libpath"
    done
fi

if (( ${#define[@]} > 0 )); then
    echo "Defined variables:"
    for key in "${!define[@]}"; do
        echo "  - $key = ${define[$key]}"
    done
fi

# Non-option arguments are available as positional parameters ($1, $2, etc.)
# after `eval "$(getoptlong set)"`.
# If PERMUTE=<array_name> was used during `getoptlong init` (or via &PERMUTE in OPTS),
# those non-option arguments are also available in the specified array.
if (( $# > 0 )); then
    echo "Remaining arguments ($#):"
    for arg in "$@"; do # Loop through positional parameters
        echo "  - $arg"
    done
fi
```

## 4. Detailed Option Definition

Command-line options for `getoptlong.sh` are defined using a Bash associative array. This section explains the detailed definition method and available option types.

### 4.1. Basic Syntax

Options are defined as keys in an associative array. The key string takes the following format:

`name[|aliases...][<type>[<modifier>]][destination][=<validation>] # description`

The value corresponding to this key in the associative array specifies the initial value of the option. Anything after a `#` in the key string is treated as a comment and used as the description in the auto-generated help message.

Example:

```bash
declare -A OPTS=(
    # NAME         ALIAS
    # |            | TYPE [:?@%]
    # |            | |MODIFIER [!>]
    # |            | ||VALIDATION
    # |            | |||      DESCRIPTION                    INITIAL VALUE
    # |            | |||      |                              |
    [ verbose    | v          # Output verbose information  ]=
    [ output     | o :        # Specify output file         ]=/dev/stdout
    [ mode       | m ?        # Operation mode (optional)   ]=
    [ include    | i @        # Include path (multiple ok)  ]=()
    [ define     | D %        # Definition (KEY=VALUE)      ]=()
    [ execute    | x  !       # Execute command             ]=my_execute_function
    [ count      | N : =i     # Number of iterations (int)  ]=1
    [ ratio      | r : =f     # Ratio (float)               ]=0.5
    [ id         | K : =(^[a-z0-9_]+$) # ID (alphanum & _)  ]=default_id
)
```

*   **`name`:** (Required) The long option name following `--` (e.g., `verbose`).  Can contain hyphens (e.g., `very-verbose`). This is also the default base for the variable name where the option's value is stored (hyphens replaced by underscores), unless a `destination_var` is provided (see Section 3.3).

*   **`aliases`:** (Optional) One or more option aliases, each following a `-` (e.g., `v`).  Multiple aliases can be specified, separated by `|` (e.g., `long|s|t`).  If only a short name is defined (e.g., `[s:]`), it also serves as the base for the variable name, unless a `destination_var` is provided (see Section 3.3).

*   **`type` (Type Specifier):** (Optional) A single character that specifies how the option handles arguments. If omitted, it defaults to `+` (flag/counter type).  Possible values are:
    *   `+`: Flag option. See section 3.2.1 for behavior.
    *   `:`: Option requires an argument.
    *   `?`: Option takes an optional argument.
    *   `@`: Option can be specified multiple times; values are stored in an array.
    *   `%`: Option takes `key=value` pairs, stored in an associative array.

*   **`modifier`:** (Optional) Special characters that alter the option's behavior, immediately following the `type` (if any):

    *   `!`: Callback. The specified function (or a default one based on the option name or `destination`) is called when this option is parsed. See Section 3.3 if specifying a destination variable.

    *   `>`: Passthrough. The option and its argument (if any) are collected into a specified array. This must follow a `type`. See Section "5.3. Option Pass-through".

    These can be combined (e.g., `!>`).

*   **`destination`:** (Optional) Specifies a custom variable name where the option's value will be stored. This name appears directly after the `type_char` and any `modifiers`.  See Section "3.3. Specifying Destination Variable Name" for full details and examples.

*   **`=<validation>`:** (Optional) Specifies validation for the argument's value. This follows the `destination` if present, or the `type`/`modifier` otherwise.  See details in Section "4.4. Value Validation". Examples: `=i` (integer), `=f` (float), `=(<regex>)`.

*   **`# description`:** Text following `#` is used as the option's description in the help message.

*   **INITIAL VALUE:** Specified as the value of the associative array element.  This becomes the default value if the option is not provided on the command line.  Behavior varies by type if not specified (e.g., flags default to empty string, arrays to empty array).

After parsing with `getoptlong parse` and setting variables with `eval "$(getoptlong set)"`, shell variables corresponding to the options (either default names or custom `destination` names) are populated.  The `PREFIX` configuration can add a common prefix to these variable names.  Hyphens (`-`) in `name` are converted to underscores (`_`) for default variable names (e.g., `--very-verbose` becomes `$very_verbose` or `$PREFIX_very_verbose`).

### 4.2. Option Types and Type Specifiers

#### 4.2.1. Flag Options (No Suffix or `+`)

Act as switches that do not take arguments and can be used as both simple flags and counters. The `+` type specifier is the default if no other type specifier is provided.

*   **Definition Examples:**
    *   `[verbose|v  # Verbose output ]=` (Equivalent to `[verbose|v+]`)
    *   `[debug|d+   # Debug level    ]=0` (Initial value for easier variable reference)
    *   `[feature|f  # Enable feature ]=`

*   **How to Specify:** `-v`, `--verbose`, `--debug`, `-d`, `--feature`

*   **Variable Behavior:**
    *   First specification: Variable is set to `1`
    *   Multiple specifications (e.g., `-vvv` or `--debug --debug`): Variable value increments
    *   Specifying with `no-` prefix (e.g., `--no-debug`): Variable is reset to empty string

*   **Use Cases:** Boolean flags, verbosity levels, debug levels. Setting an initial numeric value (e.g., `]=0`) makes variable reference simpler in arithmetic contexts like `(( debug > 0 ))`.

#### 4.2.2. Required Argument Options (`:`)

Options that always require a value.

*   **Definition Example:** `[output|o: # Output file]`

*   **How to Specify Value:**
    *   Long option: `--output=value`, `--output value`
    *   Short option: `-ovalue`, `-o value`
    *   Note: The `-o=value` form is not supported for short options.

*   **Variable Storage:** The specified value is stored as a string in the variable (e.g., `$output`).

*   **Initial Value:** Results in an error if not specified, but an initial value can be set during definition (e.g., `]=/dev/stdout`).

*   **Negation with `no-` Prefix:** Specifying with `--no-output` sets the variable to an empty string without requiring an argument. This is useful for options like `--pager` where `--no-pager` can disable the pager.

*   **Use Cases:** Specifying file paths, required parameters.

#### 4.2.3. Optional Argument Options (`?`)

Options that can take a value or be specified without one.

*   **Definition Example:** `[mode|m? # Operation mode]`

*   **How to Specify Value:**
    *   Long option:
        *   `--mode=value`: Variable `$mode` is set to `value`.
        *   `--mode`: Variable `$mode` is set to an empty string `""`.
    *   Short option:
        *   `-m`: Variable `$mode` is set to an empty string `""`.
        *   Note: Directly appending a value like `-mvalue` is not supported for short options. Use the long option if you need to specify a value.

*   **Variable Storage:**
    *   If a value is specified: That value is stored in the variable.
    *   If the option is specified without a value: An empty string `""` is stored in the variable.
    *   If the option is not specified: The variable remains unset (if no initial value was defined). Existence can be checked with `${variable+_}` or `[[ -v variable ]]`.

*   **Initial Value:** Can be set during definition (e.g., `]=default_mode`).

*   **Use Cases:** Optional configuration values, parameters valid only in certain cases.

#### 4.2.4. Array Options (`@`)

Accept multiple values as an array.

*   **Definition Example:** `[include|I@ # Include path]`

*   **How to Specify Values:**
    *   Specify the option multiple times: `--include /path/a --include /path/b`, `-I /path/a -I /path/b`
    *   Specify multiple values with a single option (delimiter controlled by `DELIM` setting; defaults to comma, space, tab):
        *   `--include /path/a,/path/b`
        *   `--include "/path/a /path/b"`
        *   `-I /path/a,/path/b`

*   **Variable Storage:** Specified values are stored in a Bash array (e.g., `"${include[@]}"`).

*   **Initial Value:** Usually an empty array. An initial value can be set during definition (e.g., `]=(/default/path1 /default/path2)`).

*   **Resetting with `no-` Prefix:** Specifying with `--no-include` resets the array to empty. This is useful for overriding default values. For example, `--no-include --include /new/path` clears any initial values and sets only `/new/path`.

*   **Use Cases:** Multiple input files, multiple configuration items.

#### 4.2.5. Hash Options (`%`)

Accept `key=value` pairs as an associative array (hash).

*   **Definition Example:** `[define|D% # Macro definition (e.g., KEY=VALUE)]`

*   **How to Specify Values:**
    *   Specify the option multiple times: `--define OS=Linux --define VER=1.0`, `-D OS=Linux -D VER=1.0`
    *   Specify multiple pairs with a single option (delimiter controlled by `DELIM` setting; defaults to comma):
        *   `--define OS=Linux,VER=1.0`
        *   `-D OS=Linux,VER=1.0`
    *   If the value (`=VALUE`) is omitted, it's treated as if `=1` was specified (e.g., `--define DEBUG` is interpreted as `DEBUG=1`).

*   **Variable Storage:** Specified keys and values are stored in a Bash associative array (e.g., `declare -A define_map="${define[@]}"; echo "${define_map[OS]}"`).

*   **Initial Value:** Usually an empty associative array. An initial value can be set during definition (e.g., `]=([USER]=$(whoami))`).

*   **Resetting with `no-` Prefix:** Specifying with `--no-define` resets the associative array to empty. This is useful for overriding default values. For example, `--no-define --define KEY=val` clears any initial values and sets only `KEY=val`.

*   **Use Cases:** Environment variable-like settings, information managed as key-value pairs.

#### 4.2.6. Callback Options (`!`)

When the option is parsed, the specified callback function is called. This `!` specifier can be appended to any of the above option types (`+`, `:`, `?`, `@`, `%`).

*   **Definition Examples:**
    *   `[execute|x! # Execute a command]` (flag type callback)
    *   `[config|c:! # Load a configuration file]` (required argument type callback)

*   **Behavior:**
    *   When the option is specified on the command line, the associated callback function is executed.
    *   By default, the callback function name is the same as the option's long name (hyphens converted to underscores). An arbitrary function name can be specified using the `getoptlong callback` command.
    *   For callback function invocation timing and arguments, see Section "7.4. `getoptlong callback ...`" and "5.1. Callback Function Details".

*   **Use Cases:** Executing custom actions during option parsing, complex value processing, immediate configuration changes.

### 4.3. Specifying Destination Variable Name

By default, `getoptlong.sh` stores the value of a parsed option (e.g., `--my-option value`) into a shell variable derived from the option's long name (e.g., `$my_option`, with hyphens replaced by underscores).  However, you can specify a custom variable name for an option's value directly within its definition string.

This is achieved by writing the desired variable name directly after the option type specifier (e.g., `+`, `:`, `?`, `@`, `%`) and any modifiers (e.g., `!`, `-`).

*   **Syntax in Option Definition:** Refer back to Section "4.1. Basic Syntax" for the full structure: `long_name[|short_name...][<type_char>[<modifiers>]][DEST_VAR_NAME][=<validation_type>] # Description` The `DEST_VAR_NAME` is the custom variable name.

*   **Example from `ex/dest.sh`:**
    The script `ex/dest.sh` demonstrates this feature:
    ```bash
    declare -A OPTS=(
        [ count     | c :COUNT=i # repeat count              ]=1
        [ sleep     | i @SLEEP=f # interval time             ]=
        [ paragraph | p ?PARA    # print newline after cycle ]=
        [ trace     | x !TRACE   # trace execution           ]= # TRACE becomes var name for callback context
        [ debug     | d +DEBUG   # debug level               ]=0
        [ message   | m %MSG=(^(BEGIN|END|EACH)=) # print message at BEGIN|END|EACH ]=
    )
    ```
    In this example:
    *   `[count|c:COUNT=i]`: Stores the value of `--count` into `COUNT` (validated as integer).
    *   `[sleep|i@SLEEP=f]`: Stores values for `--sleep` into array `SLEEP` (validated as floats).
    *   `[paragraph|p?PARA]`: Stores optional arg of `--paragraph` into `PARA`.
    *   `[debug|d+DEBUG]`: Stores incrementing value of `--debug` into `DEBUG`.
    *   `[message|m%MSG=(...)]`: Stores key-value pairs from `--message` into associative array `MSG`.

*   **Behavior:**
    *   After `getoptlong parse "$@"` and `eval "$(getoptlong set)"`, the specified variables (`COUNT`, `SLEEP`, `PARA`, `DEBUG`, `MSG` in the example) will contain the parsed values.
    *   This per-option destination variable specification overrides the default variable naming convention based on `long_name` or `short_name`.
    *   The `PREFIX` configuration setting (see Section "7.1. `getoptlong init ...`") will also apply to these custom variable names. For example, if `PREFIX=MY_` and an option is `[opt:VAR]`, the value will be stored in `$MY_VAR`.

*   **Use Cases:**
    *   Using more descriptive or conventional variable names (e.g., `ALL_CAPS` for global settings).
    *   Avoiding naming conflicts with other variables or functions.
    *   Improving code readability by explicitly showing where an option's value is stored.

### 4.4. Value Validation

There is a feature to validate the values of arguments passed to options. Validation is specified by appending `=<validation_type>` to the end of the option definition.

#### 4.4.1. Integer Validation (`=i`)

Validates if the argument is an integer.

*   **Definition Example:** `[count|c:COUNT=i # Number of iterations]` (assuming COUNT is the destination variable) or `[count|c:=i # Number of iterations]` (if using default variable name).

*   **Behavior:** If the argument is not an integer, an error message is displayed, and the script exits (default behavior, if `EXIT_ON_ERROR=1`).

*   Applicable to array options (`@...=i`) and the value part of hash options (`%...=i`).

#### 4.4.2. Float Validation (`=f`)

Validates if the argument is a floating-point number.

*   **Definition Example:** `[ratio|r:RATIO=f # Ratio]` or `[ratio|r:=f # Ratio]`

*   **Behavior:** If the argument is not a floating-point number (e.g., `123.45` is OK, `1.2e-3` may not be supported), an error message is displayed, and the script exits.

*   Applicable to array options (`@...=f`) and the value part of hash options (`%...=f`).

#### 4.4.3. Custom Regex Validation (`=(<regex>)`)

Validates if the argument matches the specified Bash extended regular expression (ERE). The regex is from the `(` immediately following `=` to the corresponding final `)`.

*   **Definition Examples:**
    *   `[mode|m:=(^(fast|slow|debug)$)]` (one of fast, slow, debug)
    *   `[name|N@=(^[A-Za-z_]+$)]` (each element contains only letters and underscores)
    *   `[param|P%:=(^[a-z_]+=[0-9]+$)]` (key is lowercase letters and _, value is numbers)

*   **Behavior:** If the argument does not match the regex, an error message is displayed, and the script exits.

*   Applicable to array and hash options. For arrays, each element is validated. For hashes, each `key=value` pair as a whole is validated against the regex.

## 5. Help Message Generation and Customization

`getoptlong.sh` provides a powerful feature to automatically generate help messages that show users how to use the script. This significantly reduces the developer's effort in manually managing help text. The generated help message displays options in alphabetical order of their long names (or short names if long names don't exist).

### 5.1. Automatic Help Option

`getoptlong.sh` automatically provides a help option (or options) that, when invoked,
displays a generated help message and exits the script.

*   **Default Behavior:**

    *   By default, `--help` and `-h` are recognized as help options.
    *   If not defined in your `OPTS` array, `getoptlong.sh` implicitly adds `help|h#show help`.
    *   When parsed, the help message is shown, and the script exits with status 0.

*   **Customization:** You can change the name, alias, and description of this automatic help option using:

    1.  **`&HELP` key in `OPTS` array (Highest Precedence):**

        ```bash
        declare -A OPTS=(
            [&HELP]="show-usage|u#Displays usage information and exits."
            # ... other option definitions ...
        )
        getoptlong init OPTS
        ```

        Now, `--show-usage` or `-u` will trigger the help message.

    2.  **`HELP` parameter in `getoptlong init` (Lower Precedence):**

        ```bash
        getoptlong init OPTS HELP="manual|m#Show the full manual."
        ```

        If `&HELP` is not set in `OPTS`, then `--manual` or `-m` will trigger help.

    *   If neither `&HELP` nor `HELP` is specified, the default `help|h#show help` is used.
    *   Explicitly defining an option with the same name (e.g., `[help|h #... ]=`) in `OPTS` will also override the default, effectively acting like `&HELP`.

*   **Disabling Automatic Help:** To completely disable the automatic help option, you can set `HELP` to an empty string and ensure no `&HELP` key or conflicting option definition exists:

    ```bash
    getoptlong init OPTS HELP=""
    ```

### 5.2. Help Message Content

#### 5.2.1. Option Descriptions (Comments `#`)

The description for each option displayed in the help message is written after a `#` at the end of the key string for each option definition in the option definition array.

```bash
declare -A OPTS=(
    [output|o:   # Specify the output file path. ]=/dev/stdout
    [verbose|v+  # Enable verbose logging (multiple increases level). ]=0
)
```

Defined as above, the help message will display something like (order depends on sorting by option name):

```
  -o, --output <value>     Specify the output file path. (default: /dev/stdout)
  -v, --verbose            Enable verbose logging (multiple increases level). (default: 0)
```

#### 5.2.2. Type-Based Automatic Messages

If no description is provided via `#` in the option definition, `getoptlong.sh` will auto-generate a basic description based on the option's type information (whether it takes an argument, argument type, etc.).

For example:

*   `[input|i:]` (no description) → `  -i, --input <value>        Requires an argument.`

*   `[force|f]` (no description) → `  -f, --force                Flag option.`

Using long, descriptive long option names (e.g., `--backup-location`) improves the readability of auto-generated messages.

#### 5.2.3. Displaying Initial (Default) Values

If an initial value is specified during option definition (e.g., `[count|c:=i]=1`), that default value is displayed in the help message like `(default: <value>)`.

```bash
declare -A OPTS=(
    [mode|m?     # Specify operation mode (fast, normal, slow) ]=normal
    [retries|r:=i # Maximum number of retries ]=3
)
```

Example help message display:

```
  -m, --mode [<value>]     Specify operation mode (fast, normal, slow) (default: normal)
  -r, --retries <value>    Maximum number of retries (default: 3)
```

#### 5.2.4. Treating Flag Options as Counters

If a numeric initial value is specified for a flag option (no type suffix, or `+`) (e.g., `[debug|d+]=0`), that option is treated as a counter.  The help message will also display this initial value.

### 5.3. Overall Help Message Format

#### 5.3.1. Customizing Synopsis (Usage Line)

The synopsis, or usage line (e.g., "Usage: myscript [options] <file>"), displayed at the beginning of the help message can be customized.

*   **Methods for Customization:**

    1.  **`&USAGE` key in `OPTS` array (Highest Precedence):**

        ```bash
        declare -A OPTS=(
            [&USAGE]="Usage: $(basename "$0") [OPTIONS] SOURCE_FILE DEST_FILE"
            # ... other option definitions ...
        )
        getoptlong init OPTS
        ```

    2.  **`USAGE` parameter in `getoptlong init` (Lower Precedence):**

        ```bash
        getoptlong init OPTS USAGE="Correct usage: myscript -i <input> -o <output> [options]"
        ```

    *   If neither `&USAGE` (in `OPTS`) nor `USAGE` (in `init`) is specified, a synopsis line is not displayed by default when help is triggered automatically. However, see `getoptlong help` below.

*   **Dynamic Synopsis with `getoptlong help`:**
    The `getoptlong help` command can also provide a synopsis dynamically (see next section).

#### 5.3.2. Manual Display with `getoptlong help [SYNOPSIS_ARGUMENT]`

You can manually display the help message from anywhere in your script using the `getoptlong help` command. This is useful for showing help on specific errors or via a custom help flag not handled by the automatic mechanism.

*   **Command:** `getoptlong help [SYNOPSIS_ARGUMENT]`

*   **Behavior:**

    *   Displays the formatted help message based on current option definitions and settings.

    *   **`[SYNOPSIS_ARGUMENT]`:** (Optional) If provided, this string is used as the synopsis line for this specific invocation of the help message. It takes precedence over any `&USAGE` or `USAGE` settings.

        ```bash
        if [[ "$some_error_condition" == "true" ]]; then
            getoptlong help "Error: Invalid input. Usage: $(basename "$0") --input <file>" >&2
            exit 1
        fi
        ```

    *   If `[SYNOPSIS_ARGUMENT]` is *not* provided to `getoptlong help`:

        *   The synopsis defined by `&USAGE` (in `OPTS`) or `USAGE` (in `init`) is used.
        *   If neither of those is set, no synopsis line is displayed, only the options list.

    *   The automatic help option (e.g., `--help`) internally calls `getoptlong help` without a `SYNOPSIS_ARGUMENT`, so it relies on `&USAGE` or `USAGE` for the synopsis.

### 5.4. Help Message Structure

The generated help message generally has the following structure:

1.  **Synopsis Line:** (If specified by `USAGE` setting or `getoptlong help` argument)

2.  **Options List:**

    *   Each option is displayed with its short option (if any), long option (if any), argument placeholder (e.g., `<value>`), and description.

    *   Options are sorted alphabetically by their long name. If no long name, sorted by short name.

    *   The description may include the initial value (`(default: ...)`).

```
(Synopsis line, e.g., Usage: myscript [options] <file>)

Options:
  -h, --help                 Show this help message and exit.
  -f, --file <path>          Specify the input file. (default: input.txt)
      --force                Force operation without confirmation.
  -n, --count <number>       Number of times to operate. (integer, default: 1)
  -v, --verbose              Enable verbose output. (counter, default: 0)
      --version              Show version information.
```

(The above is just a general example of a help message. The actual display will vary based on option definitions and settings.)

## 6. Advanced Topics

This section covers more advanced uses and convenient features of `getoptlong.sh`.

### 6.1. Callback Function Details

Callback functions allow you to execute arbitrary shell functions when specific options are parsed. This enables complex processing beyond simple value setting to be integrated into option parsing.  Callback functions are registered by adding a `!` suffix in the option definition or by using the `getoptlong callback` command.

#### 6.1.1. Normal Callbacks (Post-processing)

By default, callback functions are called **after** the option's value has been internally set.

*   **Call Format:** `callback_function "option_name" "option_value" [registered_arg1 registered_arg2 ...]`

    *   `$1`: The long name of the option (e.g., `my-option`).

    *   `$2`: The parsed value of the option. For flags, it's `1` (or an empty string if specified with `no-`). For options taking arguments, it's the argument value. For arrays or hashes, it's the last parsed element or pair.

    *   `$3...`: If additional arguments were specified during registration with `getoptlong callback <opt_name> <func_name> arg1 arg2...`, they are passed here.

*   **Example:**

    ```bash
    declare -A OPTS=(
        [process-item|p:! # Process an item]=
    )

    process_item_callback() {
        local opt_name="$1"
        local item_id="$2"
        echo "Callback: Option '$opt_name' was specified with value '$item_id'."
        # Perform processing using item_id here
        if [[ ! -f "$item_id" ]]; then
            echo "Error: File '$item_id' not found." >&2
            # exit 1 # Exit with error if necessary
        fi
    }
    # getoptlong callback process-item process_item_callback # Registered by default, but can be explicit
    # getoptlong callback process-item process_item_callback "Additional arg 1" # Can also pass extra args

    getoptlong init OPTS
    getoptlong parse "$@" && eval "$(getoptlong set)"
    ```

#### 6.1.2. Pre-processing Callbacks (`--before` / `-b`)

By specifying the `--before` (or `-b`) option with the `getoptlong callback` command, you can call the callback function **before** the option's value is internally set.

*   **Call Format:** `callback_function "option_name" [registered_arg1 registered_arg2 ...]`

    *   `$1`: The long name of the option.

    *   `$2...`: If additional arguments were specified during registration with `getoptlong callback -b <opt_name> <func_name> arg1 arg2...`, they are passed here.

    *   **Note:** The option's value is not passed to pre-processing callbacks. They are not intended for value processing but are suitable for state changes or preparation before the value is set.

*   **Use Cases:**

    *   Clearing the values of an array option before processing.

    *   Dynamically changing other default values when a specific option is specified.

    *   State initialization.

*   **Example: Pre-clearing an Array Option**

    ```bash
    declare -A OPTS=(
        [append-list|a@ # Append to list (can be cleared each time) ]=()
    )

    clear_append_list() {
        echo "Callback (--before): Clearing append_list (${append_list[*]})"
        append_list=() # Directly manipulate the global variable
    }
    # Call clear_append_list just before the append-list option is parsed
    getoptlong callback --before append-list clear_append_list

    getoptlong init OPTS
    # Example: ./myscript.sh --append-list x --append-list y
    # clear_append_list is called twice, and append_list will only contain "y" in the end.
    # Without --before, it would contain "x" "y".
    getoptlong parse "$@" && eval "$(getoptlong set)"

    echo "Final append_list: ${append_list[*]}"
    ```

#### 6.1.3. Error Handling in Callback Functions

If an error occurs within a callback function, the function itself is responsible for handling it. Typically, this involves outputting an error message to standard error and then deciding whether to `exit` the script with a non-zero status.

`getoptlong.sh`'s main error handling (like `EXIT_ON_ERROR`) applies to parsing errors detected by `getoptlong.sh` itself (e.g., undefined option, missing required argument). It does not automatically catch errors or non-zero exit statuses from user-defined callback functions. Therefore, if a callback needs to halt the script on error, it should explicitly call `exit`.

#### 6.1.4. Custom Validation using Callbacks

Complex validation that cannot be handled by the option definition's validation features (`=i`, `=f`, `=(regex)`) can be implemented using callback functions. Typically, a normal (post-processing) callback receives the value and executes the validation logic.

### 6.3. Option Pass-through

Sometimes you want to pass some of the options received by your script directly to another internal or external command. `getoptlong.sh` offers two main ways to achieve this: general argument pass-through and specific option collection.

#### 6.3.1. General Argument Pass-through (using `PERMUTE` and `--`)

This method is suitable when you want to pass all arguments after a certain point, or all non-option arguments, to another command.

*   **`PERMUTE` and `--` (Double Dash):**

    *   Setting `PERMUTE` like `getoptlong init OPTS PERMUTE=RESTARGS` causes arguments not interpreted as options (non-option arguments) to be stored in the specified array (`RESTARGS`) in order.

    *   When `--` (double dash) appears in the command-line arguments, all subsequent arguments are not interpreted as options and are stored directly in the array specified by `PERMUTE` (or the default `GOL_ARGV`). This is the standard way to pass options to subsequent commands.

*   **Handling Undefined Options:**

    *   By default, if an option not defined in the `OPTS` array is passed, it results in an error (if `EXIT_ON_ERROR=1`).

    *   By setting `EXIT_ON_ERROR=0` and checking the return value of `getoptlong parse`, you can process an argument list containing undefined options. `getoptlong.sh` does not have a direct feature to "ignore undefined options and collect them into a specific array." In this case, you need to use `PERMUTE` and `--`, or preprocess the argument list yourself.

*   **How to Achieve Pass-through (General Approaches):**

    1.  **Using `--`:** Instruct users of your script to place `--` before the options they want to pass to the downstream command.

        ```bash
        # ./myscript.sh --my-opt val -- --downstream-opt --another val
        declare -a PassThroughArgs
        getoptlong init OPTS PERMUTE=PassThroughArgs
        getoptlong parse "$@" && eval "$(getoptlong set)"
        # PassThroughArgs will contain "--downstream-opt" "--another" "val" (when using PERMUTE)
        # other_command "${PassThroughArgs[@]}"
        ```

    2.  **Usage as a Wrapper Script and Manual Splitting:** If your script is a wrapper for a specific command, process its own options, then pass the remaining or transformed arguments to that command. Using `--` for explicit separation is robust.  (Example code omitted for brevity, see previous version if needed)

#### 6.3.2. Specific Option Collection (using `>` in Option Definition)

This method allows you to collect specific options, along with their potential values, into a designated array as they are parsed. This is useful when you want to gather certain options for later processing or to pass them selectively to another function or command.

To use this feature, append a greater-than symbol (`>`) to the option type specifier in your option definition.

*   **Basic Usage:**

    When an option is defined with a trailing `>`, the option itself (e.g., `--option-name`, `--no-option-name`, or `-o`) and its value (if it takes one) are added as consecutive elements to a specified array.

    ```bash
    declare -A OPTS=(
        [collect-this|c:>my_collection_array # Collect this option and its value]=
        [ another-opt|a:>my_collection_array # Collect this one too, into the same array]=
        [flag-collect|f:>flag_array          # Collect this flag]=
    )
    declare -a my_collection_array=()
    declare -a flag_array=()

    getoptlong init OPTS
    # Example: ./myscript.sh --collect-this foo -a bar --flag-collect
    # After parsing:
    # my_collection_array would contain: ("--collect-this" "foo" "-a" "bar")
    # flag_array would contain: ("--flag-collect")
    ```

*   **Destination Array:**

    *   The array where options are collected is determined by the string following the `>` (and other type specifiers like `!` or `:`).  For example, in `[myopt|m:>destination_array]`, options will be collected into the `destination_array`.
    *   If no array name is specified after the `>` (e.g., `[myopt|m:>]`), the options are collected into an array named after the option's long name, with hyphens converted to underscores (e.g., `myopt` would collect into `myopt` array, or if defined as `my-opt`, it would collect into `my_opt` array).

*   **Combining with Other Types:** The `>` specifier must appear *after* any primary type specifier (`+`, `:`, `?`, `@`, `%`).  It can be combined with the callback modifier `!`. The primary type specifier cannot be omitted when using `>`, as this would make it ambiguous with a hyphen in a long option name.

    *   Correct: `[myopt|m:!>log_array # Log this option then collect it (flag type)]`
        The `+` (flag type) is explicitly stated. The callback `!` executes, then the option is passed to `log_array`.
    *   Correct: `[myopt|m::my_params # Collect parameter and its required value]` becomes `[myopt|m:>my_params # Collect parameter and its required value]` if it's meant to be a passthrough for a required arg. If it was `[param|p:my_params]`, it implies a required argument for `p` stored in `my_params` (standard behavior, not passthrough). If passthrough is intended for a required argument, it should be `[param|p:>my_params]`.
    *   Incorrect: `[myopt|m:>:destination_array]` (extra colon). Corrected: `[myopt|m:>destination_array]` (assuming a default type like `+` is implied, so `[myopt|m:+ >destination_array]`). Or, if it takes an argument: `[myopt|m:>destination_array]`.
    *   Incorrect: `[myopt|m:>!:log_array]`. Corrected, assuming flag type: `[myopt|m:+!>log_array]`. If it takes a required argument: `[myopt|m:!>log_array]`. The `!` (callback) and `>` (passthrough) are modifiers to a primary type.

    Let's clarify the combination with `!` and a primary type:
    *   `[cbpassthrough|c:+!>COLLECT_ARRAY]`
        - `+`: Flag type.
        - `!`: Callback is triggered.
        - `>COLLECT_ARRAY`: The option name (`--cbpassthrough` or `-c`) is passed to `COLLECT_ARRAY`.
    *   `[argcbpass|a:!>COLLECT_ARRAY]`
        - `:`: Required argument.
        - `!`: Callback is triggered (receives option name and value).
        - `>COLLECT_ARRAY`: The option name and its value are passed to `COLLECT_ARRAY`.

*   **Help Message:** Options defined with the `>` passthrough specifier will be described in the help message typically as "passthrough to ARRAY_NAME", where `ARRAY_NAME` is the name of the collection array in uppercase.

This specific option collection provides a flexible way to gather arguments that might not be directly used by the script's main logic but are important for other parts of the process or for passing to sub-commands.

### 6.4. Runtime Configuration Changes (`getoptlong configure`)

Some parameters set with `getoptlong init` can be changed later using the `getoptlong configure` command.

*   **Command:** `getoptlong configure <CONFIG_PARAM=VALUE> ...`

*   **Example:**

    ```bash
    getoptlong init OPTS EXIT_ON_ERROR=1
    # ... some processing ...
    # Temporarily prevent exiting on error
    getoptlong configure EXIT_ON_ERROR=0
    # The following parse will not exit on error (check return value of parse for success)
    if ! getoptlong parse "${some_args[@]}"; then
        echo "Warning: Parsing some_args failed but script continues." >&2
    fi
    # Revert
    getoptlong configure EXIT_ON_ERROR=1
    ```

*   **Note:** Not all parameters are suitable for runtime changes. It's safest to use this for changing flags that control parsing behavior (`EXIT_ON_ERROR`, `SILENT`, `DEBUG`, `DELIM`). Parameters like `PREFIX` or those affecting option definitions themselves might not work as expected if changed after `init`.

### 6.5. Dumping Internal State (`getoptlong dump`)

For debugging purposes, you may want to inspect the option definition information and current values held internally by `getoptlong.sh`. Use the `getoptlong dump` command.

*   **Command:**

    *   `getoptlong dump`: Displays parsed option names, corresponding shell variable names, and their current values.

    *   `getoptlong dump -a` or `getoptlong dump --all`: Displays all internal management parameters and more detailed option information.

*   **Example:**

    ```bash
    declare -A OPTS=([file|f:]=foobar.txt [verbose|v+]=0)
    getoptlong init OPTS
    getoptlong parse --verbose --file new.txt -v

    # Display status of variables $file and $verbose, etc.
    getoptlong dump >&2
    # Example output (format depends on actual implementation):
    # file (file) = 'new.txt'
    # verbose (verbose) = '2'

    eval "$(getoptlong set)"
    echo "File is: $file, Verbose level is: $verbose"
    ```

*   **Use Cases:**
    *   Verifying if options are parsed correctly.
    *   Debugging if variables are set as expected.
    *   Checking the current option state within callback functions.

## 7. Command Reference

This section describes the main commands (functions) provided by `getoptlong.sh`.

### 7.1. `getoptlong init <opts_array_name> [CONFIGURATIONS...]`

Initializes the library, loading option definitions and settings. This command must be executed before calling `getoptlong parse`.

*   **`<opts_array_name>`**: (Required) Specifies the name of the Bash associative array containing option definitions (e.g., `OPTS`).

*   **`[CONFIGURATIONS...]`**: Optional configuration parameters specified in `KEY=VALUE` format. Key settings include:

    *   **`PERMUTE=<array_name>`**: Specifies the name of a Bash regular array to store arguments not interpreted as options (non-option arguments).  For example, with `PERMUTE=REMAINING_ARGS`, in `myscript --opt arg1 arg2`, `arg1` and `arg2` would be stored in the `REMAINING_ARGS` array.  If not specified or an empty string is provided, parsing stops at the first non-option argument (behavior similar to `POSIXLY_CORRECT`).  Default is `GOL_ARGV` (an internal library array name, usually not user-facing).

    *   **`PREFIX=<string>`**: Specifies a prefix to be added to variable names set by `getoptlong set`. For example, with `PREFIX=MYAPP_` and an option `--option`, the variable `$MYAPP_option` would be set.  Default is an empty string (no prefix).

    *   **`HELP=<SPEC>`**: Customizes the automatically added help option. See Section "4.1. Automatic Help Option" for details. Default: `help|h#show help`.

    *   **`USAGE=<string>`**: Specifies the synopsis string for the help message. See Section "4.3.1. Customizing Synopsis (`USAGE` Setting)" for details. If not set, the synopsis is typically not displayed unless `getoptlong help` is called with an argument.

    *   **`EXIT_ON_ERROR=<BOOL>`**: Whether to exit the script on a parse error (`1` to exit, `0` not to exit).  Default is `1` (exit). If `0`, you must check the return value of `getoptlong parse` to detect errors.

    *   **`DELIM=<string>`**: Specifies the set of characters used to delimit multiple values or pairs within a single argument string for array (`@`) or hash (`%`) options.  Default is space, tab, comma (behavior similar to Bash's IFS). For example, `DELIM=,:` would delimit by comma and colon.

    *   **`SILENT=<BOOL>`**: Whether to suppress error messages (`1` to suppress, `0` to display).  Default is `0` (display).

    *   **`DEBUG=<BOOL>`**: Whether to enable debug messages (`1` to enable, `0` to disable).  Default is `0` (disable).

### 7.2. `getoptlong parse "$@"`

Parses command-line arguments according to the defined options.

*   **`"$@"`**: (Required) Pass all arguments passed to the script, exactly as received. It's important to enclose it in double quotes.

*   **Return Value**:

    *   Returns exit code `0` on successful parsing.
    *   Returns a non-zero exit code on parsing failure (undefined option, missing required argument, etc.).
    *   If `EXIT_ON_ERROR=1` (default), this command will cause the script to exit on a parse error, so checking the return value is usually unnecessary.
    *   If `EXIT_ON_ERROR=0`, you must check the return value of this command to handle errors.

### 7.3. `getoptlong set`

Generates a series of `eval`-able shell command strings to standard output, which set corresponding shell variables based on parsed option values.

*   Typically used as `eval "$(getoptlong set)"`. This sets variables corresponding to options in the current shell environment.  (e.g., `--file /tmp/f` → `file="/tmp/f"`)

### 7.4. `getoptlong callback [-b|--before] <opt_name> [callback_function] ...`

Registers a callback function for a specified option or modifies the settings of an already registered callback.

*   **`-b` or `--before`**:

    If this flag is specified, the callback function is called **before** the option's value is internally set.  The option's value is not passed to pre-processing callbacks. See Section "5.1.2. Pre-processing Callbacks" for details.

*   **`<opt_name>`**: (Required) The long name of the option to register the callback for (e.g., `my-option`).

*   **`[callback_function]`**:

    The name of the shell function to call.  If omitted or if `-` is specified, a function name is automatically generated from `<opt_name>` (hyphens `-` converted to underscores `_`, e.g., `my_option`) and becomes the default callback function name.  If the `!` suffix was used in the option definition, the callback is automatically registered with this default name.

*   **`[...]`**: (Optional) Additional fixed arguments to be passed to the callback function. These arguments are passed after the option name and option value (for normal callbacks) when the callback function is invoked.

### 7.5. `getoptlong configure <CONFIG_PARAM=VALUE> ...`

Dynamically changes global configuration parameter values (set by `getoptlong init`) during parsing or at other points.

*   **`<CONFIG_PARAM=VALUE>`**: (Required) Specifies a configuration parameter available in `getoptlong init` and its new value (e.g., `EXIT_ON_ERROR=0`).

*   **Note**: Not all parameters are suitable for runtime modification. It's safest to change flags controlling parsing behavior (`EXIT_ON_ERROR`, `SILENT`, `DEBUG`, `DELIM`). Parameters like `PREFIX` or those related to option definitions themselves might not work as expected if changed after `init`.

### 7.6. `getoptlong dump [-a|--all]`

Dumps (displays) the internal state of `getoptlong.sh` (option definitions, current values, settings, etc.) to standard error output. Primarily used for debugging.

*   **`-a` or `--all`**: If specified, displays more detailed internal information (including management parameters). If not specified, primarily shows parsed option names, corresponding shell variable names, and current values.

### 7.7. `getoptlong help [SYNOPSIS]`

Manually displays the generated help message based on the current option definitions and configurations.  See Section "4.3.2. Manual Display with `getoptlong help`" for full details on its behavior, including how the optional `SYNOPSIS` argument is handled.

This command is also executed internally when the automatic help option (e.g., `--help`) is invoked.

## 8. Practical Examples

Previous sections have explained individual features of `getoptlong.sh`.  This section shows some practical examples and usage in more complex scenarios.  Also, refer to the `ex/` directory for more sample scripts.

### 8.1. Combining Required Options and Optional Arguments

```bash
#!/usr/bin/env bash

# Assume getoptlong.sh is in PATH or current directory
if ! . getoptlong.sh; then echo "Error: getoptlong.sh not found." >&2; exit 1; fi

# Option definitions
declare -A OPTS=(
    [input|i:    # Specify input file (required) ]=
    [output|o:   # Specify output file (required) ]=
    [format|f?   # Output format (optional, expects value if given) ]= # Using without value is discouraged
    [compress|c  # Compress output (flag) ]=
    [level|l:=i  # Compression level (integer, only if compress is used) ]=1
    [verbose|v+  # Verbosity level ]=0
    [&USAGE]="Usage: $(basename "$0") -i <input> -o <output> [-f <format>] [-c [-l <level>]] [-v]"
    [&HELP]="process-data|H#Help for the data processing script"
)

# Callback function (e.g., uppercase the format if specified)
# Since '!' is not on the format option, register with getoptlong callback
format_callback() {
    local opt_name="$1"
    local val="$2"
    if [[ -n "$val" ]]; then
        format="${val^^}" # Directly modify the global 'format' variable
        (( verbose > 0 )) && echo "Debug: Format set to '$format' via callback." >&2
    else
        echo "Warning: Format option used without a value." >&2
    fi
}
getoptlong callback format format_callback

# Initialize getoptlong
getoptlong init OPTS

# Parse arguments
if ! getoptlong parse "$@"; then
    exit 1
fi
eval "$(getoptlong set)"

# Check for required options
if [[ -z "$input" ]] || [[ -z "$output" ]]; then
    echo "Error: Input file (-i) and output file (-o) are required." >&2
    getoptlong help # Display help on error
    exit 1
fi

# Main processing
echo "Input file: $input"
echo "Output file: $output"

if [[ -v format ]]; then # If format option was used (with value or empty string)
    if [[ -n "$format" ]]; then
        echo "Output format: $format"
    else
        echo "Output format: (not specified)" # Case of --format only
    fi
fi

if [[ -n "$compress" ]]; then
    echo "Compression: Enabled (Level: $level)"
    # Compression processing...
else
    echo "Compression: Disabled"
fi

echo "Verbosity level: $verbose"

# ...actual processing...
echo "Processing complete."
```

**Key points in this example:**

*   Checking for required options (`input`, `output`).

*   Handling optional arguments (`format`) and value processing via callback.

*   Combining a flag option (`compress`) with another related option (`level`).

*   Customizing the help message using `&USAGE` and `&HELP`.

### 8.2. Script with Subcommands (Simple Version)

`getoptlong.sh` can call `init` and `parse` multiple times. This can
be used to define and process different option sets for subcommands.

```bash
#!/bin/bash
if ! . getoptlong.sh; then echo "Error: getoptlong.sh not found." >&2; exit 1; fi

# Global options
declare -A GlobalOPTS=(
    [verbose|v+ # Verbose output ]=0
    [help|h     # Display help ]=
)
getoptlong init GlobalOPTS
declare -a RemainingArgs
# Parse only global options. Do not exit on error, store the rest in RemainingArgs.
getoptlong configure EXIT_ON_ERROR=0 PERMUTE=RemainingArgs
getoptlong parse "$@"
eval "$(getoptlong set)" # Set variables for global options

# If global help requested or no subcommand, show overall help
if [[ -n "$help" ]] || (( ${#RemainingArgs[@]} == 0 )); then
    echo "Usage: $(basename "$0") [global_options] <subcommand> [subcommand_options]"
    echo ""
    echo "Global Options:"
    getoptlong help # Help for GlobalOPTS
    echo ""
    echo "Subcommands:"
    echo "  commit    Record changes to the repository"
    echo "  push      Update remote refs along with associated objects"
    exit 0
fi

subcommand="${RemainingArgs[0]}"
# Subcommand arguments are RemainingArgs excluding the subcommand itself
SubcommandArgs=("${RemainingArgs[@]:1}")

case "$subcommand" in
    commit)
        declare -A CommitOPTS=(
            [message|m: # Commit message ]=
            [all|a      # Stage all changes ]=
            [help|h     # Help for commit subcommand ]= # Per-subcommand help
        )
        getoptlong init CommitOPTS # Re-initialize with new option set
        # Parse only subcommand arguments
        if ! getoptlong parse "${SubcommandArgs[@]}"; then exit 1; fi
        eval "$(getoptlong set)" # Set variables for commit

        if [[ -n "$help" ]]; then # Subcommand help
             getoptlong help "Usage: $(basename "$0") commit [options]"
             exit 0
        fi

        echo "Subcommand: commit"
        [[ -n "$message" ]] && echo "  Message: $message"
        [[ -n "$all" ]] && echo "  All: enabled"
        (( verbose > 0 )) && echo "  Verbose (global): $verbose"
        # e.g., execute git commit
        ;;
    push)
        declare -A PushOPTS=(
            [remote|r:  # Remote repository ]=origin
            [force|f   # Force push       ]=
            [help|h    # Help for push subcommand ]=
        )
        getoptlong init PushOPTS
        if ! getoptlong parse "${SubcommandArgs[@]}"; then exit 1; fi
        eval "$(getoptlong set)"

        if [[ -n "$help" ]]; then
             getoptlong help "Usage: $(basename "$0") push [options]"
             exit 0
        fi

        echo "Subcommand: push"
        echo "  Remote: ${remote}"
        [[ -n "$force" ]] && echo "  Force: enabled"
        (( verbose > 0 )) && echo "  Verbose (global): $verbose"
        # e.g., execute git push
        ;;
    *)
        echo "Error: Unknown subcommand '$subcommand'" >&2
        getoptlong init GlobalOPTS # Revert to GlobalOPTS for help display
        getoptlong help "Usage: $(basename "$0") [global_options] <subcommand> [subcommand_options]"
        exit 1
        ;;
esac
```

**Key points in this example:**

*   Separation of global options and subcommand-specific options.

*   Calling `getoptlong init` and `parse` multiple times.

*   Using `PERMUTE` to separate the subcommand and its arguments.

*   Consideration for per-subcommand help display (defining `help|h` in each OPTS).

*   **Note:** This example illustrates the basic idea. Real subcommand processing needs to consider more edge cases and error handling. A more detailed example can be found in `ex/subcmd.sh`.

### 8.3. Sample Scripts in `ex/` Directory

The `getoptlong.sh` repository includes sample scripts in the `ex/` directory that demonstrate various features. These are very helpful for learning more specific use cases and advanced techniques.

*   **`ex/repeat.sh`**: Shows basic usage of various option types (array, hash, incremental flags, etc.).

*   **`ex/prefix.sh`**: Example of `PREFIX` setting usage.

*   **`ex/cmap`**: A colorizing mapper. Good example of complex option parsing, callbacks, and data processing.

*   **`ex/cmap-prefix`**: `cmap` example with `PREFIX` applied.

*   **`ex/md`**: Sample Markdown parser.

*   **`ex/silent.sh`**: Example of `SILENT` setting usage.

*   **`ex/subcmd.sh`**: A more sophisticated example of a script with subcommands, including handling of global and local options, and shared help.

It's recommended to try running these samples and reading their code.

## 9. Configuration Keys

Within the option definition array (`OPTS`), you can use special keys in the format `&KEY=VALUE` to configure the behavior of `getoptlong.sh`, separate from regular option definitions.  These settings take precedence over identically named settings specified as arguments to the `getoptlong init` command.

*   **`&HELP=<SPEC>`**

    *   Description: Customizes the definition of the auto-generated help option.  Overrides the `HELP` parameter of `getoptlong init`.  See Section "4.1. Automatic Help Option" for more details.

    *   Example: `[&HELP]="show-usage|u#Usage guide"`

    *   Default: `help|h#show help`

*   **`&USAGE=<string>`**

    *   Description: Specifies the usage (Synopsis) string to be displayed at the beginning of the help message. Overrides the `USAGE` parameter of `getoptlong init`.  See Section "4.3.1. Customizing Synopsis (`USAGE` Setting)" for more details.

    *   Example: `[&USAGE]="Usage: $(basename "$0") [OPTIONS] SOURCE DEST"`

    *   Default: Not specified (Synopsis is not displayed unless an argument is passed to `getoptlong help`).

*   **`&REQUIRE=<version>`**

    *   Description: Specifies the minimum required version of `getoptlong.sh`. If the current version is older than the specified version, the script will exit with an error message.

    *   Example: `[&REQUIRE]="0.2"`

    *   Default: Not specified (no version check).

    *   Note: Version comparison correctly handles numeric ordering (e.g., `0.2 < 0.10 < 1.0`).

*   **Other Configuration Keys:**

    *   The current documentation does not explicitly mention other `&KEY` format settings, but depending on the library version, other settings (e.g., `&DELIM`, `&PREFIX`) might be supported. For accurate information, please check the documentation or source code corresponding to the version of `getoptlong.sh` you are using.

## 10. See Also

Other tools with similar purposes to `getoptlong.sh`, and related resources:

-   **GNU `getopt`**: The command-line utility version of the C library's `getopt_long` function. It is used for parsing complex options but may require extra effort to use in shell scripts.
-   **Bash `getopts`**: A Bash built-in command. It supports only POSIX-style short options and does not handle long options or the free ordering of options (permutation).
-   **Perl `Getopt::Long`**: A widely used command-line option parsing module in Perl. `getoptlong.sh` has been influenced by this module in some aspects.
-   **Python `argparse`**: A standard Python library module for parsing command-line arguments, known for its power and flexibility.
-   [`getoptions` (ko1nksm/getoptions)](https://github.com/ko1nksm/getoptions): Another powerful option parser for shell scripts, which inspired some features in `getoptlong.sh`.
-   [`argh` (adrienverge/argh)](https://github.com/adrienverge/argh): A minimalist argument handler for bash.

[end of README.md]
