Skip to content

Instantly share code, notes, and snippets.

@nicola-lunghi
Last active October 3, 2022 08:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nicola-lunghi/6d70c0e74ba66e7b3ca20612dd502a47 to your computer and use it in GitHub Desktop.
Save nicola-lunghi/6d70c0e74ba66e7b3ca20612dd502a47 to your computer and use it in GitHub Desktop.
Example of adding a "preamble" to argbash to put code before argbash code.
#!/bin/bash
# m4_ignore(
echo "This is just a script template, not the script (yet) - pass it to 'argbash' to fix this." >&2
exit 11 #)[ <-- needed because of Argbash
###############################################################################
# PREAMBLE
###############################################################################
# Treat expansion of unset variables as an error and exit immediately
# if a command pipeline exits with a non-zero status
set -o nounset -o errexit
## useful variables
script_name="$(basename "${BASH_SOURCE[0]}")"
script_version="1.0"
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
_arg_command=""
_arg_config=""
_arg_help=""
_positionals=()
###############################################################################
# END PREAMBLE
###############################################################################
# ] <-- needed because of Argbash
# ARG_OPTIONAL_SINGLE([config],[c],[specify a config file],[curdir/.lab_config.conf])
# ARG_POSITIONAL_SINGLE([command],[specify a command to execute],[help])
# ARGBASH_SET_DELIM([ =])
# ARG_OPTION_STACKING([getopt])
# ARG_RESTRICT_VALUES([no-local-options])
# ARG_DEFAULTS_POS([])
# ARG_HELP([Print help function])
# ARG_VERSION([echo "$script_name $script_version"][][])
# ARGBASH_SET_INDENT([ ])
# ARG_POSITIONAL_DOUBLEDASH([])
# ARGBASH_PREPARE()
# [ <-- needed because of Argbash
###############################################################################
# MAIN
###############################################################################
# argparse stuff
parse_commandline "$@"
handle_passed_args_count
assign_positional_args 1 "${_positionals[@]}"
# printf 'Value of --%s: %s\n' 'help' "$_arg_help"
printf "Value of '%s': %s\\n" 'command' "${_arg_command}"
printf "Value of '%s': %s\\n" 'config' "${_arg_config}"
printf "Value of '%s': %s\\n" 'positionals' "${_positionals[*]}"
#### MAIN END
# ] <-- needed because of Argbash
#!/bin/bash
###############################################################################
# PREAMBLE
###############################################################################
# Treat expansion of unset variables as an error and exit immediately
# if a command pipeline exits with a non-zero status
set -o nounset -o errexit
## useful variables
script_name="$(basename "${BASH_SOURCE[0]}")"
script_version="1.0"
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
_arg_command=""
_arg_config=""
_arg_help=""
_positionals=()
###############################################################################
# END PREAMBLE
###############################################################################
# ARG_OPTIONAL_SINGLE([config],[c],[specify a config file],[curdir/.lab_config.conf])
# ARG_POSITIONAL_SINGLE([command],[specify a command to execute],[help])
# ARGBASH_SET_DELIM([ =])
# ARG_OPTION_STACKING([getopt])
# ARG_RESTRICT_VALUES([no-local-options])
# ARG_DEFAULTS_POS([])
# ARG_HELP([Print help function])
# ARG_VERSION([echo "$script_name $script_version"])
# ARGBASH_SET_INDENT([ ])
# ARG_POSITIONAL_DOUBLEDASH([])
# ARGBASH_PREPARE()
# needed because of Argbash --> m4_ignore([
### START OF CODE GENERATED BY Argbash v2.10.0 one line above ###
# Argbash is a bash code generator used to get arguments parsing right.
# Argbash is FREE SOFTWARE, see https://argbash.io for more info
# # When called, the process ends.
# Args:
# $1: The exit message (print to stderr)
# $2: The exit code (default is 1)
# if env var _PRINT_HELP is set to 'yes', the usage is print to stderr (prior to $1)
# Example:
# test -f "$_arg_infile" || _PRINT_HELP=yes die "Can't continue, have to supply file as an argument, got '$_arg_infile'" 4
die()
{
local _ret="${2:-1}"
test "${_PRINT_HELP:-no}" = yes && print_help >&2
echo "$1" >&2
exit "${_ret}"
}
# Function that evaluates whether a value passed to an argument
# does not violate the global rule imposed by the ARG_RESTRICT_VALUES macro:
# The value must not match any long or short option this script uses
# Args:
# $1: The name of the option
# $2: The passed value
evaluate_strictness()
{
[[ "$2" =~ ^-(-(config|command|help|version)$|[chv]) ]] && die "You have passed '$2' as a value of argument '$1', which makes it look like that you have omitted the actual value, since '$2' is an option accepted by this script. This is considered a fatal error."
}
# Function that evaluates whether a value passed to it begins by a character
# that is a short option of an argument the script knows about.
# This is required in order to support getopts-like short options grouping.
begins_with_short_option()
{
local first_option all_short_options='chv'
first_option="${1:0:1}"
test "$all_short_options" = "${all_short_options/$first_option/}" && return 1 || return 0
}
# THE DEFAULTS INITIALIZATION - POSITIONALS
# The positional args array has to be reset before the parsing, because it may already be defined
# - for example if this script is sourced by an argbash-powered script.
_positionals=()
_arg_command="help"
# THE DEFAULTS INITIALIZATION - OPTIONALS
_arg_config="curdir/.lab_config.conf"
# Function that prints general usage of the script.
# This is useful if users asks for it, or if there is an argument parsing error (unexpected / spurious arguments)
# and it makes sense to remind the user how the script is supposed to be called.
print_help()
{
printf '%s\n' "Print help function"
printf 'Usage: %s [-c|--config <arg>] [-h|--help] [-v|--version] [--] [<command>]\n' "$0"
printf '\t%s\n' "<command>: specify a command to execute (default: 'help')"
printf '\t%s\n' "-c, --config: specify a config file (default: 'curdir/.lab_config.conf')"
printf '\t%s\n' "-h, --help: Prints help"
printf '\t%s\n' "-v, --version: Prints version"
}
# The parsing of the command-line
parse_commandline()
{
_positionals_count=0
while test $# -gt 0
do
_key="$1"
# If two dashes (i.e. '--') were passed on the command-line,
# assign the rest of arguments as positional arguments and bail out.
if test "$_key" = '--'
then
shift
# Handle the case when the double dash is the last argument.
test $# -gt 0 || break
_positionals+=("$@")
_positionals_count=$((_positionals_count + $#))
shift $(($# - 1))
_last_positional="$1"
break
fi
case "$_key" in
# We support whitespace as a delimiter between option argument and its value.
# Therefore, we expect the --config or -c value.
# so we watch for --config and -c.
# Since we know that we got the long or short option,
# we just reach out for the next argument to get the value.
-c|--config)
test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
_arg_config="$2"
shift
evaluate_strictness "$_key" "$_arg_config"
;;
# We support the = as a delimiter between option argument and its value.
# Therefore, we expect --config=value, so we watch for --config=*
# For whatever we get, we strip '--config=' using the ${var##--config=} notation
# to get the argument value
--config=*)
_arg_config="${_key##--config=}"
evaluate_strictness "$_key" "$_arg_config"
;;
# We support getopts-style short arguments grouping,
# so as -c accepts value, we allow it to be appended to it, so we watch for -c*
# and we strip the leading -c from the argument string using the ${var##-c} notation.
-c*)
_arg_config="${_key##-c}"
evaluate_strictness "$_key" "$_arg_config"
;;
# The help argurment doesn't accept a value,
# we expect the --help or -h, so we watch for them.
-h|--help)
print_help
exit 0
;;
# We support getopts-style short arguments clustering,
# so as -h doesn't accept value, other short options may be appended to it, so we watch for -h*.
# After stripping the leading -h from the argument, we have to make sure
# that the first character that follows coresponds to a short option.
-h*)
print_help
exit 0
;;
# See the comment of option '--help' to see what's going on here - principle is the same.
-v|--version)
echo "$script_name $script_version"
exit 0
;;
# See the comment of option '-h' to see what's going on here - principle is the same.
-v*)
echo "$script_name $script_version"
exit 0
;;
*)
_last_positional="$1"
_positionals+=("$_last_positional")
_positionals_count=$((_positionals_count + 1))
;;
esac
shift
done
}
# Check that we receive expected amount positional arguments.
# Return 0 if everything is OK, 1 if we have too little arguments
# and 2 if we have too much arguments
handle_passed_args_count()
{
test "${_positionals_count}" -le 1 || _PRINT_HELP=yes die "FATAL ERROR: There were spurious positional arguments --- we expect between 0 and 1, but got ${_positionals_count} (the last one was: '${_last_positional}')." 1
}
# Take arguments that we have received, and save them in variables of given names.
# The 'eval' command is needed as the name of target variable is saved into another variable.
assign_positional_args()
{
local _positional_name _shift_for=$1
# We have an array of variables to which we want to save positional args values.
# This array is able to hold array elements as targets.
# As variables don't contain spaces, they may be held in space-separated string.
_positional_names="_arg_command "
shift "$_shift_for"
for _positional_name in ${_positional_names}
do
test $# -gt 0 || break
eval "$_positional_name=\${1}" || die "Error during argument parsing, possibly an Argbash bug." 1
shift
done
}
# Call the function that assigns passed optional arguments to variables:
# parse_commandline "$@"
# Then, call the function that checks that the amount of passed arguments is correct
# followed by the function that assigns passed positional arguments to variables:
# handle_passed_args_count
# assign_positional_args 1 "${_positionals[@]}"
# OTHER STUFF GENERATED BY Argbash
### END OF CODE GENERATED BY Argbash (sortof) ### ])
# [ <-- needed because of Argbash
###############################################################################
# MAIN
###############################################################################
# argparse stuff
parse_commandline "$@"
handle_passed_args_count
assign_positional_args 1 "${_positionals[@]}"
# printf 'Value of --%s: %s\n' 'help' "$_arg_help"
printf "Value of '%s': %s\\n" 'command' "${_arg_command}"
printf "Value of '%s': %s\\n" 'config' "${_arg_config}"
printf "Value of '%s': %s\\n" 'positionals' "${_positionals[*]}"
#### MAIN END
# ] <-- needed because of Argbash
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment