From 83c4552371d4bfc15c923719cb3d481110e13fd6 Mon Sep 17 00:00:00 2001 From: Andrew Kesterson Date: Mon, 19 May 2014 17:15:54 -0700 Subject: [PATCH] Made validators less silly (require strict functions) and updated docs --- README.md | 86 ++++++++++++++++++++++++++++++++++++++++--------------- cmdarg.sh | 12 ++++++-- 2 files changed, 72 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index b5bd5d8..a13592b 100644 --- a/README.md +++ b/README.md @@ -32,16 +32,40 @@ cmdarg is a helper library I wrote for bash scripts because, at current, option cmdarg_parse cmdarg_usage +TL;DR +===== + +Cmdarg lets you specify arguments (things you require), options (things you don't require), and lets you easily parse them. The arguments can be set on the command line either via '-X' or '--Y', where X is the short option and Y is the long option. + + cmdarg 'r:' 'required-thing' 'Some thing I require' + cmdarg 'o?' 'optional-thing' 'Some optional thing' + cmdarg 'b' 'boolean-thing' 'Some boolean thing' + cmdarg_parse "$@" + + echo ${cmdarg_cfg['required-thing']} + echo ${cmdarg_cfg['optional-thing']} + echo ${cmdarg_cfg['boolean-thing']} + + # your_script.sh -r some_thingy -b -o optional_thing + # your_script.sh --required-thing some_thingy --boolean-thing + +Because cmdarg does key off of the short options, you are limited to as many options as you have unique single characters in your character set (likely 61 - 26 lower & upper alpha, +9 numerics). + cmdarg ====== -This function is used to tell the library what command line arguments you accept. Check cmdarg.sh for the latest syntax. +This function is used to tell the library what command line arguments you accept. - cmdarg 'l:' 'source_ldap' 'Source (old) LDAP URI' - cmdarg 'u:' 'source_ldap_username' 'Source (old) LDAP Username' - cmdarg 'c:' 'groupmap' 'A CSV file mapping usernames to groups that they should belong to post-conversion' '' 'test -e $OPTARG' + cmdarg FLAGS LONGOPT DESCRIPTION DEFAULT VALIDATOR -The first argument to cmdarg must be an argument specification. Argument specifications take the form 'NOT', where: +Examples: + + cmdarg 'f' 'boolean-flag' 'Some boolean flag' + cmdarg 'a:' 'required-arg' 'Some required arg' + cmdarg 'a?' 'optional-arg' 'Some optional arg with a default' 'default_value' + cmdarg 'a:' 'required-validated-arg' 'Some required argument with a validator' '' validator_function + +*FLAGS* : The first argument to cmdarg must be an argument specification. Argument specifications take the form 'NOT', where: - N : The single letter Name of the argument - O : Whether the option is optional or not. Use ':' here for a required argument, '?' for an optional argument. If you provide a default value for a required argument (:), then it becomes optional. @@ -49,16 +73,32 @@ The first argument to cmdarg must be an argument specification. Argument specifi If O and T are both unset, and only the single letter N is provided, then the argument is a boolean argument which will default to false. -The arguments can be set on the command line either via '-X' or '--Y', where X is the short option and Y is the long option. Example: +*LONGOPT* is a long option name (such as long-option-name) that can be used to set your argument via --LONGOPT instead of via -N (from your FLAGS). - cmdarg 'r:' 'required-thing' 'Some thing I require' - cmdarg 'o?' 'optional-thing' 'Some optional thing' - cmdarg 'b' 'boolean-thing' 'Some boolean thing' +*DESCRIPTION* is a string that describes what this argument is for. - # your_script.sh -r some_thingy -b -o optional_thing - # your_script.sh --required-thing some_thingy --boolean-thing +*DEFAULT* is any default value that you want to be set for this option if the user does not specify one -Because cmdarg does key off of the short options, you are limited to as many unique single characters are in your character set (likely 61 - 26 lower & upper alpha, +9 numerics). +*VALIDATOR* The name of a bash function which will validate this argument (see VALIDATORS below). + + +Validators +========== + +Validators must be bash function names - not bash statements - and they must accept one argument, being the value to validate. Validators are not told the name of the option, only the value. Validator functions must return 0 if they value they are given is valid, and 1 if it is invalid. Validators should refrain from producing output on stdout or stderr. + +For example, this is a valid validator: + + function validate_int + { + echo "$1" | grep -E '^[0-9]+$' + } + + cmdarg 'x' 'x-option' 'some opt' '' validate_int + +... While this is not: + + cmdarg 'x' 'x-option' 'some opt' '' "grep -E '^[0-9]+$'" cmdarg_info =========== @@ -80,7 +120,7 @@ This command does what you expect, parsing your command line arguments. However Any argument parsed that has a validator assigned, and whose validator returns nonzero, is considered a failure. Any REQUIRED argument that is not specified is considered a failure. However, it is worth noting that if a required argument has a default value, and you provide an empty value to it, we won't know any better and that will be accepted (how do we know you didn't actually *mean* to do that?). -For every argument integer, boolean or string argument, a global associative array "cmdarg_cfg" is populated with the long version of the option. E.g., in the example above, '-c' would become ${cmdarg_cfg['groupmap']}, for friendlier access during scripting. +For every argument integer, boolean or string argument, a global associative array "cmdarg_cfg" is populated with the long version of the option. E.g., in the example above, '-c' would become ${cmdarg_cfg['groupmap']}, for friendlier access during scripting. cmdarg 'x:' 'some required thing' cmdarg_parse "$@" @@ -101,7 +141,7 @@ cmdarg takes the pain out of creating your --help messages. For example, conside #!/bin/bash source /usr/lib/cmdarg.sh declare -a myarray - + cmdarg_info "header" "Some script that needed argument parsing" cmdarg_info "author" "Some Poor Bastard " cmdarg_info "copyright" "(C) 2013" @@ -111,21 +151,21 @@ cmdarg takes the pain out of creating your --help messages. For example, conside cmdarg 'b' 'boolean-thing' 'Some boolean thing' cmdarg 'a?[]' 'myarray' 'Some array of stuff' cmdarg_parse "$@" - -... And you ran it with '--help', you would get a nice preformatted help message: + +... And you ran it with '--help', you would get a nice preformatted help message: test.sh (C) 2013 : Some Poor Bastard - + Some script that needed argument parsing - + Required Arguments: - -R,--required-thing v : String. Some thing I REALLY require - + -R,--required-thing v : String. Some thing I REALLY require + Optional Arguments: -r,--required-thing-with-default v : String. Some thing I require (Default "Some default") - -o,--optional-thing v : String. Some optional thing - -b,--boolean-thing : Boolean. Some boolean thing - -a,--myarray v[, ...] : Array. Some array of stuff. Pass this argument multiple times for multiple values. + -o,--optional-thing v : String. Some optional thing + -b,--boolean-thing : Boolean. Some boolean thing + -a,--myarray v[, ...] : Array. Some array of stuff. Pass this argument multiple times for multiple values. Setting arrays and hashes ========================= diff --git a/cmdarg.sh b/cmdarg.sh index 5e5347c..7b0a03c 100644 --- a/cmdarg.sh +++ b/cmdarg.sh @@ -42,7 +42,7 @@ function cmdarg exit 1 fi - declare -xA argtypemap + declare -A argtypemap argtypemap[':']=$CMDARG_FLAG_REQARG argtypemap['?']=$CMDARG_FLAG_OPTARG argtype=${1:1:1} @@ -81,7 +81,13 @@ function cmdarg CMDARG_OPTIONAL+=($shortopt) fi cmdarg_cfg["$2"]="${4:-}" - CMDARG_VALIDATORS["$shortopt"]="${5:-}" + local validatorfunc + validatorfunc=${5:-} + if [[ "$validatorfunc" != "" ]] && [[ "$(declare -F $validatorfunc)" == "" ]]; then + echo "Validators must be bash functions accepting 1 argument (not '$validatorfunc')" >&2 + exit 1 + fi + CMDARG_VALIDATORS["$shortopt"]="$validatorfunc" CMDARG_GETOPTLIST="${CMDARG_GETOPTLIST}$1" } @@ -304,7 +310,7 @@ function cmdarg_parse shortopt=${CMDARG_REV[$opt]} if [ "${CMDARG_VALIDATORS[$shortopt]}" != "" ]; then OPTARG=${cmdarg_cfg[$opt]} - ( eval "${CMDARG_VALIDATORS[${shortopt}]}" && [ "$OPTARG" != "" ]) + ( ( ${CMDARG_VALIDATORS[${shortopt}]} "$OPTARG" ) && [ "$OPTARG" != "" ]) if [ $? -ne 0 ]; then echo "Invalid value for -$shortopt : ${cmdarg_cfg[$opt]}" failed=1