diff mbox series

[v8,07/37] parse-options: parse into strvec

Message ID 20210311021037.3001235-8-emilyshaffer@google.com (mailing list archive)
State New, archived
Headers show
Series config-based hooks | expand

Commit Message

Emily Shaffer March 11, 2021, 2:10 a.m. UTC
parse-options already knows how to read into a string_list, and it knows
how to read into an strvec as a passthrough (that is, including the
argument as well as its value). string_list and strvec serve similar
purposes but are somewhat painful to convert between; so, let's teach
parse-options to read values of string arguments directly into an
strvec without preserving the argument name.

This is useful if collecting generic arguments to pass through to
another command, for example, 'git hook run --arg "--quiet" --arg
"--format=pretty" some-hook'. The resulting strvec would contain
{ "--quiet", "--format=pretty" }.

The implementation is based on that of OPT_STRING_LIST.

Signed-off-by: Emily Shaffer <emilyshaffer@google.com>
---

Notes:
    Since v7, updated the reference doc to make the intended usage for OPT_STRVEC
    more clear.
    
    Since v4, fixed one or two more places where I missed the argv_array->strvec
    rename.

 Documentation/technical/api-parse-options.txt |  7 +++++++
 parse-options-cb.c                            | 16 ++++++++++++++++
 parse-options.h                               |  4 ++++
 3 files changed, 27 insertions(+)

Comments

Ævar Arnfjörð Bjarmason March 12, 2021, 8:50 a.m. UTC | #1
On Thu, Mar 11 2021, Emily Shaffer wrote:

> diff --git a/Documentation/technical/api-parse-options.txt b/Documentation/technical/api-parse-options.txt
> index 5a60bbfa7f..f79b17e7fc 100644
> --- a/Documentation/technical/api-parse-options.txt
> +++ b/Documentation/technical/api-parse-options.txt
> @@ -173,6 +173,13 @@ There are some macros to easily define options:
>  	The string argument is stored as an element in `string_list`.
>  	Use of `--no-option` will clear the list of preceding values.
>  
> +`OPT_STRVEC(short, long, &struct strvec, arg_str, description)`::
> +	Introduce an option with a string argument, meant to be specified
> +	multiple times.
> +	The string argument is stored as an element in `strvec`, and later
> +	arguments are added to the same `strvec`.
> +	Use of `--no-option` will clear the list of preceding values.
> +
>  `OPT_INTEGER(short, long, &int_var, description)`::
>  	Introduce an option with integer argument.
>  	The integer is put into `int_var`.
> diff --git a/parse-options-cb.c b/parse-options-cb.c
> index 4542d4d3f9..c2451dfb1b 100644
> --- a/parse-options-cb.c
> +++ b/parse-options-cb.c
> @@ -207,6 +207,22 @@ int parse_opt_string_list(const struct option *opt, const char *arg, int unset)
>  	return 0;
>  }
>  
> +int parse_opt_strvec(const struct option *opt, const char *arg, int unset)
> +{
> +	struct strvec *v = opt->value;
> +
> +	if (unset) {
> +		strvec_clear(v);
> +		return 0;
> +	}
> +
> +	if (!arg)
> +		return -1;
> +
> +	strvec_push(v, arg);
> +	return 0;
> +}
> +
>  int parse_opt_noop_cb(const struct option *opt, const char *arg, int unset)
>  {
>  	return 0;
> diff --git a/parse-options.h b/parse-options.h
> index ff6506a504..44c4ac08e9 100644
> --- a/parse-options.h
> +++ b/parse-options.h
> @@ -177,6 +177,9 @@ struct option {
>  #define OPT_STRING_LIST(s, l, v, a, h) \
>  				    { OPTION_CALLBACK, (s), (l), (v), (a), \
>  				      (h), 0, &parse_opt_string_list }
> +#define OPT_STRVEC(s, l, v, a, h) \
> +				    { OPTION_CALLBACK, (s), (l), (v), (a), \
> +				      (h), 0, &parse_opt_strvec }
>  #define OPT_UYN(s, l, v, h)         { OPTION_CALLBACK, (s), (l), (v), NULL, \
>  				      (h), PARSE_OPT_NOARG, &parse_opt_tertiary }
>  #define OPT_EXPIRY_DATE(s, l, v, h) \
> @@ -296,6 +299,7 @@ int parse_opt_commits(const struct option *, const char *, int);
>  int parse_opt_commit(const struct option *, const char *, int);
>  int parse_opt_tertiary(const struct option *, const char *, int);
>  int parse_opt_string_list(const struct option *, const char *, int);
> +int parse_opt_strvec(const struct option *, const char *, int);
>  int parse_opt_noop_cb(const struct option *, const char *, int);
>  enum parse_opt_result parse_opt_unknown_cb(struct parse_opt_ctx_t *ctx,
>  					   const struct option *,

Nice, seems very useful.

But let's add a test in test-parse-options.c like we have for
string_list?
Emily Shaffer March 24, 2021, 8:34 p.m. UTC | #2
On Fri, Mar 12, 2021 at 09:50:58AM +0100, Ævar Arnfjörð Bjarmason wrote:
[snip]
> Nice, seems very useful.
> 
> But let's add a test in test-parse-options.c like we have for
> string_list?

Sure, done. Thanks.
diff mbox series

Patch

diff --git a/Documentation/technical/api-parse-options.txt b/Documentation/technical/api-parse-options.txt
index 5a60bbfa7f..f79b17e7fc 100644
--- a/Documentation/technical/api-parse-options.txt
+++ b/Documentation/technical/api-parse-options.txt
@@ -173,6 +173,13 @@  There are some macros to easily define options:
 	The string argument is stored as an element in `string_list`.
 	Use of `--no-option` will clear the list of preceding values.
 
+`OPT_STRVEC(short, long, &struct strvec, arg_str, description)`::
+	Introduce an option with a string argument, meant to be specified
+	multiple times.
+	The string argument is stored as an element in `strvec`, and later
+	arguments are added to the same `strvec`.
+	Use of `--no-option` will clear the list of preceding values.
+
 `OPT_INTEGER(short, long, &int_var, description)`::
 	Introduce an option with integer argument.
 	The integer is put into `int_var`.
diff --git a/parse-options-cb.c b/parse-options-cb.c
index 4542d4d3f9..c2451dfb1b 100644
--- a/parse-options-cb.c
+++ b/parse-options-cb.c
@@ -207,6 +207,22 @@  int parse_opt_string_list(const struct option *opt, const char *arg, int unset)
 	return 0;
 }
 
+int parse_opt_strvec(const struct option *opt, const char *arg, int unset)
+{
+	struct strvec *v = opt->value;
+
+	if (unset) {
+		strvec_clear(v);
+		return 0;
+	}
+
+	if (!arg)
+		return -1;
+
+	strvec_push(v, arg);
+	return 0;
+}
+
 int parse_opt_noop_cb(const struct option *opt, const char *arg, int unset)
 {
 	return 0;
diff --git a/parse-options.h b/parse-options.h
index ff6506a504..44c4ac08e9 100644
--- a/parse-options.h
+++ b/parse-options.h
@@ -177,6 +177,9 @@  struct option {
 #define OPT_STRING_LIST(s, l, v, a, h) \
 				    { OPTION_CALLBACK, (s), (l), (v), (a), \
 				      (h), 0, &parse_opt_string_list }
+#define OPT_STRVEC(s, l, v, a, h) \
+				    { OPTION_CALLBACK, (s), (l), (v), (a), \
+				      (h), 0, &parse_opt_strvec }
 #define OPT_UYN(s, l, v, h)         { OPTION_CALLBACK, (s), (l), (v), NULL, \
 				      (h), PARSE_OPT_NOARG, &parse_opt_tertiary }
 #define OPT_EXPIRY_DATE(s, l, v, h) \
@@ -296,6 +299,7 @@  int parse_opt_commits(const struct option *, const char *, int);
 int parse_opt_commit(const struct option *, const char *, int);
 int parse_opt_tertiary(const struct option *, const char *, int);
 int parse_opt_string_list(const struct option *, const char *, int);
+int parse_opt_strvec(const struct option *, const char *, int);
 int parse_opt_noop_cb(const struct option *, const char *, int);
 enum parse_opt_result parse_opt_unknown_cb(struct parse_opt_ctx_t *ctx,
 					   const struct option *,