Skip to content

Latest commit

 

History

History
189 lines (156 loc) · 6.41 KB

shflags.md

File metadata and controls

189 lines (156 loc) · 6.41 KB

6.2.3. shFlags

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

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}"
}

# Define the help message.
FLAGS_HELP="$(cat << EOF
Usage: $0 [OPTIONS] ARGUMENTS source destination

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
EOF
)"
FLAGS_HELP+=$'\n'

# Parse the arguments.
source shflags

DEFINE_string "name" "?" "the name of the homepage's owner" "n"
DEFINE_integer "age" "-1" "the current age of the homepage's owner" "a"
DEFINE_string "role" "?" "the role of the homepage's owner (u: user, m: moderator, b: bot)" "r"
DEFINE_boolean "verbose" "${FLAGS_FALSE}" "output verbose information" "v"
DEFINE_boolean "exit" "${FLAGS_FALSE}" "exit directly after parsing, for runtime assessment" "e"
DEFINE_boolean "usage" "${FLAGS_FALSE}" "display the usage and exit" "u"
DEFINE_boolean "version" "${FLAGS_FALSE}" "display the version and exit" "V"

if ! FLAGS "$@"; then
    exit "$?"
fi
eval set -- "${FLAGS_ARGV}"

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

# Check the arguments' values.
if (( "$#" == 1 )); then
    printf '%s: Error: 2 positional arguments are required, but 1 is given.\n' \
        "$0"
    usage >&2
    exit 1
elif (( "$#" != 2 )); then
    printf '%s: Error: 2 positional arguments are required, but %s are given.\n' \
        "$0" "$#"
    usage >&2
    exit 1
fi

name="${FLAGS_name}"
if [[ "${name}" == "?" ]]; then
    printf '%s: Error: The option -n,--name is mandatory, but not given.\n' \
        "$0"
    usage >&2
    exit 1
fi

age="${FLAGS_age}"
if (( "${age}" == -1 )); then
    printf '%s: Error: The option -a,--age is mandatory, but not given.\n' "$0"
    usage >&2
    exit 1
fi

role="${FLAGS_role}"
if [[ "${role}" == "?" ]]; then
    printf '%s: Error: The option -r,--role is mandatory, but not given.\n' \
        "$0"
    usage >&2
    exit 1
elif [[ "${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

if [[ "${FLAGS_verbose}" == "${FLAGS_TRUE}" ]]; then
    verbose=true
else
    verbose=false
fi

# Set the positional arguments to variables.
in_file="$1"
out_file="$2"

# Possibly, exit prematurely.
[[ "${FLAGS_exit}" == "${FLAGS_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_shflags.sh --verbose --name="A. R. G. Parser" --age=2 --role=b template.html argparser.html

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

# Merged short options.
bash test_shflags.sh -vn "A. R. G. Parser" -a2 -rb template.html argparser.html

# Leading positional arguments.
bash test_shflags.sh template.html argparser.html -vn "A. R. G. Parser" -a2 -rb

# Positional arguments delimiter "--".
bash test_shflags.sh -vn "A. R. G. Parser" -a2 -rb -- template.html argparser.html

# Intermixed positional arguments.
bash test_shflags.sh -vn "A. R. G. Parser" template.html -a2 argparser.html -rb

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

Notes:

  • shFlags uses GNU getopt to parse long options, and fails parsing them on other getopt implementations.
  • Since shFlags is a gflags port, it uses a slightly strange and unintuitive syntax, like DEFINE_string long_option default help short_option.
  • Likewise, options are available in the environment as FLAGS_option_name, not by a different identifier.
  • Mandatory options aren't supported. In lieu of checking for their existence on the command line, "impossible" default values are set and then checked against.
  • The help message is partly auto-generated. In order to comply with the style decisions in shFlags, the manually set header is adapted to them.
  • The question mark ? for the help message is not supported.

🡄 6.2.2. getopt           6.2.4. docopts 🡆