diff --git a/bin/argbash b/bin/argbash index 7a71d4e..1088e62 100755 --- a/bin/argbash +++ b/bin/argbash @@ -495,7 +495,7 @@ then # match against suspicious, then inverse match against correct stuff: # #\(allowed\|another allowed\|...\) end of line> # Then, extract all matches (assumed to be alnum chars + '_') from grep and put them in the error msg. - grep_output="$(printf "%s" "$output" | grep '^#\s*\(ARG_\|ARGBASH\)' | grep -v '^#\s*\(ARGBASH_SET_INDENT\|ARG_OPTIONAL_SINGLE\|ARG_VERSION\|ARG_VERSION_AUTO\|ARG_HELP\|ARG_OPTIONAL_INCREMENTAL\|ARG_OPTIONAL_REPEATED\|ARG_VERBOSE\|ARG_OPTIONAL_BOOLEAN\|ARG_OPTIONAL_ACTION\|ARG_POSITIONAL_SINGLE\|ARG_POSITIONAL_INF\|ARG_POSITIONAL_MULTI\|ARG_POSITIONAL_DOUBLEDASH\|ARG_OPTION_STACKING\|ARG_RESTRICT_VALUES\|ARG_DEFAULTS_POS\|ARG_LEFTOVERS\|ARGBASH_WRAP\|INCLUDE_PARSING_CODE\|DEFINE_SCRIPT_DIR\|DEFINE_SCRIPT_DIR_GNU\|ARGBASH_SET_DELIM\|ARGBASH_GO\|ARGBASH_PREPARE\|ARG_TYPE_GROUP\|ARG_TYPE_GROUP_SET\|ARG_USE_ENV\|ARG_USE_PROG\)\s*\((\|$\)' | sed -e 's/#\s*\([[:alnum:]_]*\).*/\1 /' | tr -d '\n\r')" + grep_output="$(printf "%s" "$output" | grep '^#\s*\(ARG_\|ARGBASH\)' | grep -v '^#\s*\(ARGBASH_SET_INDENT\|ARG_OPTIONAL_SINGLE\|ARG_VERSION\|ARG_VERSION_AUTO\|ARG_HELP\|ARG_OPTIONAL_INCREMENTAL\|ARG_OPTIONAL_REPEATED\|ARG_VERBOSE\|ARG_OPTIONAL_BOOLEAN\|ARG_OPTIONAL_SWITCH_ON\|ARG_OPTIONAL_SWITCH_OFF\|ARG_OPTIONAL_ACTION\|ARG_POSITIONAL_SINGLE\|ARG_POSITIONAL_INF\|ARG_POSITIONAL_MULTI\|ARG_POSITIONAL_DOUBLEDASH\|ARG_OPTION_STACKING\|ARG_RESTRICT_VALUES\|ARG_DEFAULTS_POS\|ARG_LEFTOVERS\|ARGBASH_WRAP\|INCLUDE_PARSING_CODE\|DEFINE_SCRIPT_DIR\|DEFINE_SCRIPT_DIR_GNU\|ARGBASH_SET_DELIM\|ARGBASH_GO\|ARGBASH_PREPARE\|ARG_TYPE_GROUP\|ARG_TYPE_GROUP_SET\|ARG_USE_ENV\|ARG_USE_PROG\)\s*\((\|$\)' | sed -e 's/#\s*\([[:alnum:]_]*\).*/\1 /' | tr -d '\n\r')" test -n "$grep_output" && die "Your script contains possible misspelled Argbash macros: $grep_output" 1 fi if test "$outfname" != '-' diff --git a/src/collectors.m4 b/src/collectors.m4 index 798885f..74625ba 100644 --- a/src/collectors.m4 +++ b/src/collectors.m4 @@ -1,6 +1,30 @@ m4_define([_COLLECTOR_FEEDBACK], [m4_fatal($@)]) +dnl +dnl $1: The key +m4_define([_FORMAT_MISSING_PREFIX], [m4_do( + [[The prefix for option '$1' has not been found]], +)]) + +dnl +dnl $1: The argname(i.e. storage key) +dnl $2: The prefix +m4_define([STORE_NEGATION_PREFIX], [m4_do( + [m4_define([_NEG_PREFIX_FOR_$1], [[$2]])], +)]) + + +dnl +dnl $1: The argname(i.e. storage key) +dnl $2: Error-handling callback that is given the error message as the first argument. +m4_define([GET_NEGATION_PREFIX], [m4_do( + [m4_ifndef([_NEG_PREFIX_FOR_$1], + [m4_default([$2], [m4_fatal])([_FORMAT_MISSING_PREFIX([$1])])], + [m4_quote(m4_indir([_NEG_PREFIX_FOR_$1]))])], +)]) + + dnl dnl $1: The argument name dnl $2: The help message @@ -324,10 +348,48 @@ dnl $3: help dnl $4: default (=off) argbash_api([ARG_OPTIONAL_BOOLEAN], _CHECK_PASSED_ARGS_COUNT(1, 4)[m4_do( [[$0($@)]], - [m4_ifnblank([$4], [m4_case([$4], [on], , [off], , - [_COLLECTOR_FEEDBACK([Problem with argument '$1': Only 'on' or 'off' are allowed as boolean defaults, you have specified '$4'.])])])], - [_ADD_OPTIONAL_ARGUMENT_IF_POSSIBLE([$1], [$2], [$3], - m4_default_quoted([$4], [off]), [bool])], + [m4_ifnblank([$4], + [m4_case([$4], + [off], [_ARG_OPTIONAL_SWITCH_ON([$1], [$2], [$3])], + [on], [_ARG_OPTIONAL_SWITCH_OFF([$1], [$2], [$3])], + [_COLLECTOR_FEEDBACK([Problem with argument '$1': Only 'on' or 'off' are allowed as boolean defaults, you have specified '$4'.])])], + [_ADD_OPTIONAL_ARGUMENT_IF_POSSIBLE([$1], [$2], [$3], + m4_default_quoted([$4], [off]), [bool])], + )], +)]) + + +dnl $1: long name, var suffix (translit of [-] -> _) +dnl $2: short name (opt) +dnl $3: help +argbash_api([ARG_OPTIONAL_SWITCH_ON], _CHECK_PASSED_ARGS_COUNT(1, 3)[m4_do( + [[$0($@)]], + [_ARG_OPTIONAL_SWITCH_ON($@)], +)]) + + +m4_define([_ARG_OPTIONAL_SWITCH_ON], _CHECK_PASSED_ARGS_COUNT(1, 3)[m4_do( + [_ADD_OPTIONAL_ARGUMENT_IF_POSSIBLE([$1], [$2], [$3], [off], [bool])], +)]) + + +m4_define([_DEFAULT_NEGATION_PREFIX], [[no-]]) + +m4_define([ARG_SET_DEFAULT_NEGATION_PREFIX], [m4_define([_DEFAULT_NEGATION_PREFIX], [[$1]])]) + +dnl $1: long name, var suffix (translit of [-] -> _) +dnl $2: short name (opt) +dnl $3: help +dnl $4: the negation prefix (=no-, resulting in i.e. --no-video) +argbash_api([ARG_OPTIONAL_SWITCH_OFF], _CHECK_PASSED_ARGS_COUNT(1, 4)[m4_do( + [[$0($@)]], + [_ARG_OPTIONAL_SWITCH_OFF($@)], +)]) + + +m4_define([_ARG_OPTIONAL_SWITCH_OFF], _CHECK_PASSED_ARGS_COUNT(1, 4)[m4_do( + [STORE_NEGATION_PREFIX([$1], m4_default_quoted([$4], _DEFAULT_NEGATION_PREFIX))], + [_ADD_OPTIONAL_ARGUMENT_IF_POSSIBLE([$1], [$2], [$3], [on], [bool])], )]) diff --git a/src/function_generators.m4 b/src/function_generators.m4 index 6b2ced1..0727147 100644 --- a/src/function_generators.m4 +++ b/src/function_generators.m4 @@ -168,7 +168,7 @@ m4_define([_MAKE_ARGV_PARSING_FUNCTION], [MAKE_FUNCTION( [parse_commandline], [m4_do( [_JOIN_INDENTED(1, _IF_HAVE_POSITIONAL_ARGS([[_positionals_count=0],]), - [while test $[]# -gt 0], + [[while test $][# -gt 0]], [do], )], [_IF_HAVE_OPTIONAL_ARGS( @@ -193,8 +193,8 @@ m4_define([_MAKE_ARGV_PARSING_FUNCTION_POSIX], [MAKE_FUNCTION( [[The parsing of the command-line]], [parse_commandline], [m4_do( [_JOIN_INDENTED(1, - [while getopts '_GET_GETOPTS_STRING()' _key], - [do], + [[while getopts ']_GET_GETOPTS_STRING()[' _key]], + [[do]], )], [_EVAL_OPTIONALS_GETOPTS], [_INDENT_()done[]_ENDL_()], diff --git a/src/stuff.m4 b/src/stuff.m4 index 5b1231e..8a5e700 100644 --- a/src/stuff.m4 +++ b/src/stuff.m4 @@ -422,7 +422,7 @@ dnl $3: Name of the value-to-variable macro dnl $4: The name of the argument-holding variable dnl $5: Where to get the last value (optional) m4_define([_VAL_OPT_ADD_SPACE_WITHOUT_GETOPT_OR_SHORT_OPT], [_JOIN_INDENTED(_INDENT_LEVEL_IN_ARGV_CASE_BODY, - [test $[]# -lt 2 && die "Missing value for the optional argument '$_key'." 1], + [[test $][# -lt 2 && die "Missing value for the optional argument '$_key'." 1]], [$3([$1], ["@S|@2"], [$4])], [_APPEND_WRAPPED_ARGUMENT_TO_ARRAY_SPACE([$4], [m4_default_quoted([$5], [@S|@2])])], [shift], diff --git a/start_tmux.sh b/start_tmux.sh index 33ced19..7793d42 100644 --- a/start_tmux.sh +++ b/start_tmux.sh @@ -4,6 +4,6 @@ tmux send-keys 'vim stuff.m4' C-m tmux new-window -c resources tmux send-keys -l 'make unittests' tmux new-window -c tests/unittests -tmux send-keys -l 'vim ' +tmux send-keys -l 'vim -p test-support.m4 ' tmux select-window -t argbash:0 tmux -2 attach-session -t argbash diff --git a/tests/regressiontests/test-onlyopt.m4 b/tests/regressiontests/test-onlyopt.m4 index 19eefa3..0c2c0da 100644 --- a/tests/regressiontests/test-onlyopt.m4 +++ b/tests/regressiontests/test-onlyopt.m4 @@ -2,7 +2,7 @@ m4_define([if_not_posix], [m4_if(m4_quote(_OUTPUT_TYPE), [posix-script], [$2], [$1])]) -dnl m4_define([test], [m4_fatal([BOOM!!!])]) +dnl m4_define([test], [huuuuuuuuuu]) m4_define([incrx], [m4_fatal([BOOM!!!])]) # ARG_OPTIONAL_SINGLE([opt-arg], o, [@opt-arg@], x) # ARG_VERSION([echo "$0 FOO"]) diff --git a/tests/unittests/check-arguments.m4 b/tests/unittests/check-arguments.m4 index 96a3e17..60867df 100644 --- a/tests/unittests/check-arguments.m4 +++ b/tests/unittests/check-arguments.m4 @@ -44,6 +44,9 @@ assert_equals([not single], _CATH_IS_SINGLE_VALUED(m4_list_nth([_ARGS_CATH], 4), _DISCARD_VALUES_FOR_ALL_ARGUMENTS() +assert_equals(m4_list_len([_ARGS_LONG]), 0) + + ARG_OPTIONAL_SINGLE([foo], [f], [Help,BOMB], [Default]) ARG_POSITIONAL_SINGLE([defaultless], [xhelp]) ARG_POSITIONAL_MULTI([multi-BOMB], [help-BOMB], 3, [one], [two]) @@ -103,3 +106,23 @@ ARG_OPTIONAL_SINGLE([bar], [f]) assert_equals(m4_list_len([_ERRORS_]), 1) m4_bmatch(m4_list_nth([_ERRORS_], 1), ['f'.*already used], [], [m4_fatal([Expected error reflecting duplicate short option, got] 'm4_list_nth([_ERRORS_], 1)' instead.)]) m4_popdef([_COLLECTOR_FEEDBACK]) + +_DISCARD_VALUES_FOR_ALL_ARGUMENTS() + +ARG_OPTIONAL_SWITCH_ON([foo], [f]) +assert_equals_list_element([_ARGS_LONG], 1, [foo]) +assert_equals_list_element([_ARGS_DEFAULT], 1, [off]) + +ARG_OPTIONAL_SWITCH_OFF([bar], [b], , [BOMB]) +assert_equals_list_element([_ARGS_LONG], 2, [bar]) +assert_equals_list_element([_ARGS_DEFAULT], 2, [on]) +assert_equals(GET_NEGATION_PREFIX([bar]), [BOMB]) + +ARG_OPTIONAL_SWITCH_OFF([BOMB]) +assert_equals_list_element([_ARGS_LONG], 3, [BOMB]) +assert_equals_list_element([_ARGS_DEFAULT], 2, [on]) +assert_equals(GET_NEGATION_PREFIX([BOMB]), [no-]) + +ARG_SET_DEFAULT_NEGATION_PREFIX([BOMB]) +ARG_OPTIONAL_SWITCH_OFF([xx]) +assert_equals(GET_NEGATION_PREFIX([xx]), [BOMB]) diff --git a/tests/unittests/check-collectors.m4 b/tests/unittests/check-collectors.m4 new file mode 100644 index 0000000..6be3fb0 --- /dev/null +++ b/tests/unittests/check-collectors.m4 @@ -0,0 +1,12 @@ +m4_include([collectors.m4]) + +m4_include([test-support.m4]) + + +m4_define([SAVE], [m4_define([SAVED], [$1])]) + +GET_NEGATION_PREFIX([BOMB], [SAVE]) +assert_equals(SAVED, _FORMAT_MISSING_PREFIX([BOMB])) + +STORE_NEGATION_PREFIX([lol], [BOMB]) +assert_equals(GET_NEGATION_PREFIX([lol]), [BOMB])