From 65dce6fd4107e065a9078a72a2b15f6bbf52ce4a Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Sun, 5 Dec 2021 13:00:17 -0500 Subject: [PATCH] usage: add `USAGE_STOP_PARSING` to stop parsing Some arguments like `--help` are successful and should stop the parsing, so that we do not enforce required arguments. --- adopt.c | 3 +++ adopt.h | 15 ++++++++++++--- tests/adopt.c | 28 ++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 3 deletions(-) diff --git a/adopt.c b/adopt.c index 56f483d..0ef811c 100644 --- a/adopt.c +++ b/adopt.c @@ -369,6 +369,9 @@ adopt_status_t adopt_parse( opt->status != ADOPT_STATUS_DONE) return opt->status; + if ((opt->spec->usage & ADOPT_USAGE_STOP_PARSING)) + return (opt->status = ADOPT_STATUS_DONE); + given_specs[given_idx++] = opt->spec; } diff --git a/adopt.h b/adopt.h index 02e7114..ecf5db8 100644 --- a/adopt.h +++ b/adopt.h @@ -52,6 +52,9 @@ typedef enum { * restrictions and usage information to be displayed to the end-user. */ typedef enum { + /** Defaults for the argument. */ + ADOPT_USAGE_DEFAULT = 0, + /** This argument is required. */ ADOPT_USAGE_REQUIRED = (1u << 0), @@ -63,14 +66,20 @@ typedef enum { */ ADOPT_USAGE_CHOICE = (1u << 1), + /** + * This argument short-circuits the remainder of parsing. + * Useful for arguments like `--help`. + */ + ADOPT_USAGE_STOP_PARSING = (1u << 2), + /** The argument's value is optional ("-n" or "-n foo") */ - ADOPT_USAGE_VALUE_OPTIONAL = (1u << 2), + ADOPT_USAGE_VALUE_OPTIONAL = (1u << 3), /** This argument should not be displayed in usage. */ - ADOPT_USAGE_HIDDEN = (1u << 3), + ADOPT_USAGE_HIDDEN = (1u << 4), /** In usage, show the long format instead of the abbreviated format. */ - ADOPT_USAGE_SHOW_LONG = (1u << 4), + ADOPT_USAGE_SHOW_LONG = (1u << 5), } adopt_usage_t; /** Specification for an available option. */ diff --git a/tests/adopt.c b/tests/adopt.c index 9e0beca..0fef25d 100644 --- a/tests/adopt.c +++ b/tests/adopt.c @@ -922,3 +922,31 @@ void test_adopt__choice_switch_or_arg_advances_arg(void) cl_assert_equal_p(NULL, baz); cl_assert_equal_s("actually_final", final); } + +void test_adopt__stop(void) +{ + int foo = 0, bar = 0, help = 0, baz = 0; + adopt_opt result; + + adopt_spec specs[] = { + { ADOPT_TYPE_SWITCH, "foo", 'f', &foo, 'f', ADOPT_USAGE_REQUIRED }, + { ADOPT_TYPE_SWITCH, "bar", 0, &bar, 'b', ADOPT_USAGE_REQUIRED }, + { ADOPT_TYPE_SWITCH, "help", 0, &help, 'h', ADOPT_USAGE_STOP_PARSING }, + { ADOPT_TYPE_SWITCH, "baz", 0, &baz, 'z', ADOPT_USAGE_REQUIRED }, + { 0 }, + }; + + char *args[] = { "-f", "--help", "-z" }; + + cl_assert_equal_i(ADOPT_STATUS_DONE, adopt_parse(&result, specs, args, 2)); + + cl_assert_equal_i(ADOPT_STATUS_DONE, result.status); + cl_assert_equal_s("--help", result.arg); + cl_assert_equal_p(NULL, result.value); + cl_assert_equal_i(0, result.args_len); + + cl_assert_equal_i('f', foo); + cl_assert_equal_p('h', help); + cl_assert_equal_p(0, bar); + cl_assert_equal_p(0, baz); +}