Skip to content

Latest commit

 

History

History
160 lines (132 loc) · 5.9 KB

docopts.md

File metadata and controls

160 lines (132 loc) · 5.9 KB

6.2.4. docopts

Contents of test_docopts.sh
#!/usr/bin/env bash

# Usage:
#   test_docopts.sh [--verbose] [--exit] --age=AGE --name=NAME --role=ROLE [--] <source> <destination>
#   test_docopts.sh --help
#   test_docopts.sh --usage
#   test_docopts.sh --version
#
# Mandatory arguments to long options are mandatory for short options too.
#
# Positional arguments:
#   <source>              the template HTML file to fill in
#   <destination>         the output HTML file
#
# Mandatory options:
#   -a AGE, --age=AGE     the current age of the homepage's owner
#   -n NAME, --name=NAME  the name of the homepage's owner
#   -r ROLE, --role=ROLE  the role of the homepage's owner (u: user, m:
#                         moderator, b: bot)
#
# Optional options:
#   -e, --exit            exit directly after parsing, for runtime assessment
#   -v, --verbose         output verbose information
#
# Help options:
#   -h, -?, --help        display this help and exit
#   -u, --usage           display the usage and exit
#   -V, --version         display the version and exit

function usage() {
    # Define the usage message.
    local usage
    usage="Usage: $0 [-h,-? | -u | -V] [-e] [-v] -a=AGE -n=NAME -r={u,m,b} "
    usage+="source destination"
    printf '%s\n' "${usage}"
}

# Parse the arguments.
source docopts.sh --auto "$@"

# Check for the usage and version options.  The help option is handled
# by docopts.sh.
if [[ "${ARGS[--usage]}" == true ]]; then
    usage
    exit
elif [[ "${ARGS[--version]}" == true ]]; then
    printf '%s v1.0.0\n' "$0"
    exit
fi

# Check the arguments' values.
name="${ARGS[--name]}"

age="${ARGS[--age]}"
if [[ "${age}" != ?([+-])+([[:digit:]]) ]]; then
    printf '%s: Error: The option -a,--age must be an integer.\n' "$0"
    usage >&2
    exit 1
fi

role="${ARGS[--role]}"
if [[ "${role}" != [[:print:]] ]]; then
    printf '%s: Error: The option -r,--role must be a single character.\n' "$0"
    usage >&2
    exit 1
fi

case "${role}" in
    "u") role="User" ;;
    "m") role="Moderator" ;;
    "b") role="Bot" ;;
    *)
        printf '%s: Error: The option -r,--role must be in {u, m, b}.\n' "$0"
        usage >&2
        exit 1
        ;;
esac

verbose="${ARGS[--verbose]}"

# Set the positional arguments to variables.
in_file="${ARGS[<source>]}"
out_file="${ARGS[<destination>]}"

# Possibly, exit prematurely.
[[ "${ARGS[--exit]}" == true ]] && exit

# Run the HTML processor.
if [[ "$0" == */* ]]; then
    cd "${0%/*.sh}" || exit 1
fi
source process_html_template.sh

Example calls:

# Long options.
bash test_docopts.sh --verbose --name="A. R. G. Parser" --age=2 --role=b template.html argparser.html

# Short options.
bash test_docopts.sh -v -a 2 -n "A. R. G. Parser" -r b template.html argparser.html

# Merged short options.
bash test_docopts.sh -va 2 -n "A. R. G. Parser" -r b template.html argparser.html

# Leading positional arguments.
bash test_docopts.sh template.html argparser.html --verbose --name="A. R. G. Parser" --age=2 --role=b

# Positional arguments delimiter "--".
bash test_docopts.sh --verbose --name="A. R. G. Parser" --age=2 --role=b -- template.html argparser.html

# Intermixed positional arguments.
bash test_docopts.sh --verbose --name="A. R. G. Parser" template.html --age=2 argparser.html --role=b

# Help, usage, and version messages.
bash test_docopts.sh --help
bash test_docopts.sh --usage
bash test_docopts.sh --version

Notes:

  • Instead of defining the arguments and letting the parser create the help message, in docopts, the help message must be manually provided and the arguments definition gets extracted from there.
  • Due to the rather complicated grammar, the usage string is likely incorrect, as the arguments to short options are interpreted as positional arguments. This requires some boilerplate code to get the actual values. Moreover, when using short options, they must be given in the order defined in the usage string as their values are normal positional arguments and as such parsed from left to right, irrespective of the preceding short option "flag" (as the parser interprets the definition). Thus, in the example calls, the long options are used, when necessary.
  • The question mark ? for the help message is not supported, but emulated as --help by a separate call.

🡄 6.2.3. shFlags           6.2.5. Argparser 🡆