From 448abbba63471153df6ba520a5621595557ce3c8 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 18 Jul 2023 15:54:04 -0700 Subject: [PATCH 1/3] short help: allow multi-line opthelp When "-h" triggers the short-help in a command that implements its option parsing using the parse-options API, the option help text is shown with a single fprintf() as a long line. When the text is multi-line, the second and subsequent lines are not left padded, that breaks the alignment across options. Borrowing the idea from the advice API where its hint strings are shown with (localized) "hint:" prefix, let's internally split the (localized) help text into lines, and showing the first line, pad the remaining lines to align. Signed-off-by: Junio C Hamano --- parse-options.c | 12 +++++++++++- t/helper/test-parse-options.c | 2 ++ t/t0040-parse-options.sh | 2 ++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/parse-options.c b/parse-options.c index f8a155ee13b959..817416db99c584 100644 --- a/parse-options.c +++ b/parse-options.c @@ -1109,6 +1109,7 @@ static enum parse_opt_result usage_with_options_internal(struct parse_opt_ctx_t for (; opts->type != OPTION_END; opts++) { size_t pos; int pad; + const char *cp, *np; if (opts->type == OPTION_SUBCOMMAND) continue; @@ -1157,7 +1158,16 @@ static enum parse_opt_result usage_with_options_internal(struct parse_opt_ctx_t (const char *)opts->value); continue; } - fprintf(outfile, "%*s%s\n", pad + USAGE_GAP, "", _(opts->help)); + + for (cp = _(opts->help); *cp; cp = np) { + np = strchrnul(cp, '\n'); + fprintf(outfile, + "%*s%.*s\n", pad + USAGE_GAP, "", + (int)(np - cp), cp); + if (*np) + np++; + pad = USAGE_OPTS_WIDTH; + } } fputc('\n', outfile); diff --git a/t/helper/test-parse-options.c b/t/helper/test-parse-options.c index 00fa281a9c9342..a4f6e24b0c6e1b 100644 --- a/t/helper/test-parse-options.c +++ b/t/helper/test-parse-options.c @@ -133,6 +133,8 @@ int cmd__parse_options(int argc, const char **argv) OPT_STRING(0, "st", &string, "st", "get another string (pervert ordering)"), OPT_STRING('o', NULL, &string, "str", "get another string"), OPT_NOOP_NOARG(0, "obsolete"), + OPT_SET_INT_F(0, "longhelp", &integer, "help text of this entry\n" + "spans multiple lines", 0, PARSE_OPT_NONEG), OPT_STRING_LIST(0, "list", &list, "str", "add str to list"), OPT_GROUP("Magic arguments"), OPT_NUMBER_CALLBACK(&integer, "set integer to NUM", diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh index 7d7ecfd57162cf..83e5d4eeb68105 100755 --- a/t/t0040-parse-options.sh +++ b/t/t0040-parse-options.sh @@ -35,6 +35,8 @@ String options --string2 get another string --st get another string (pervert ordering) -o get another string + --longhelp help text of this entry + spans multiple lines --list add str to list Magic arguments From d86a8f386d89edaffec63a626f5226c9f39f5027 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 18 Jul 2023 15:31:03 -0700 Subject: [PATCH 2/3] remote: simplify "remote add --tags" help text The help text for the --tags option was split into two option[] entries, which was a hacky way to give two lines of help text (the second entry did not have either short or long help, and there was no way to invoke its entry---it was there only for the help text). As we now support multi-line text in the option help, let's make the second line of the help a proper second line and remove the hacky second entry. Signed-off-by: Junio C Hamano --- builtin/remote.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/builtin/remote.c b/builtin/remote.c index 1e0b137d977bb7..09fb9ae30d786a 100644 --- a/builtin/remote.c +++ b/builtin/remote.c @@ -167,10 +167,9 @@ static int add(int argc, const char **argv, const char *prefix) struct option options[] = { OPT_BOOL('f', "fetch", &fetch, N_("fetch the remote branches")), OPT_SET_INT(0, "tags", &fetch_tags, - N_("import all tags and associated objects when fetching"), + N_("import all tags and associated objects when fetching\n" + "or do not fetch any tag at all (--no-tags)"), TAGS_SET), - OPT_SET_INT(0, NULL, &fetch_tags, - N_("or do not fetch any tag at all (--no-tags)"), TAGS_UNSET), OPT_STRING_LIST('t', "track", &track, N_("branch"), N_("branch(es) to track")), OPT_STRING('m', "master", &master, N_("branch"), N_("master branch")), From c512643e67d33673933fa3d245be28b08b974755 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 18 Jul 2023 15:58:00 -0700 Subject: [PATCH 3/3] short help: allow a gap smaller than USAGE_GAP The parse-options API responds to "git cmd -h" by listing the option flag (padded to the USAGE_OPTS_WIDTH column), followed by USAGE_GAP (set to 2) whitespaces, followed by the help text. If the flags part does not fit within the USAGE_OPTS_WIDTH, the help text is given on its own line. Imagine that "@" below depicts the USAGE_OPTS_WIDTH'th column, and "#" are for the usage help text, the output may look like this: @@@@@@@@@@@@@ ######################################## -f description of the flag '-f' comes here --short= description of the flag '--short' --very-long-option= description of the flag '--very-long-option' This is all good and nice in principle, but it becomes awkward when the flags part is just one column over the limit and forces a line break. See the description of the "--almost" option below: @@@@@@@@@@@@@ ######################################## -f description of the flag '-f' comes here --short= description of the flag '--short' --almost= description of the flag '--almost' --very-long-option= description of the flag '--very-long-option' If we allow shrinking the gap to a single whitespace only in such a case, we would instead get: @@@@@@@@@@@@@ ######################################## -f description of the flag '-f' comes here --short= description of the flag '--short' --almost= description of the flag '--almost' --very-long-option= description of the flag '--very-long-option' and the boundary between the flags and their descriptions does not become any harder to see, while saving precious vertical screen real estate. Signed-off-by: Junio C Hamano --- parse-options.c | 4 +++- t/t0040-parse-options.sh | 3 +-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/parse-options.c b/parse-options.c index 817416db99c584..87c9fae6349650 100644 --- a/parse-options.c +++ b/parse-options.c @@ -1146,7 +1146,9 @@ static enum parse_opt_result usage_with_options_internal(struct parse_opt_ctx_t !(opts->flags & PARSE_OPT_NOARG)) pos += usage_argh(opts, outfile); - if (pos <= USAGE_OPTS_WIDTH) + if (pos == USAGE_OPTS_WIDTH + 1) + pad = -1; + else if (pos <= USAGE_OPTS_WIDTH) pad = USAGE_OPTS_WIDTH - pos; else { fputc('\n', outfile); diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh index 83e5d4eeb68105..e19a19963697a0 100755 --- a/t/t0040-parse-options.sh +++ b/t/t0040-parse-options.sh @@ -30,8 +30,7 @@ usage: test-tool parse-options -F, --file set file to String options - -s, --string - get a string + -s, --string get a string --string2 get another string --st get another string (pervert ordering) -o get another string