parse-options: no --[no-]no-...
Avoid showing an optional "no-" for options that already start with a "no-" in the short help, as that double negation is confusing. Document the opposite variant on its own line with a generated help text instead, unless it's defined and documented explicitly already. Signed-off-by: René Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
René Scharfe committed
Aug 5, 2023 at 16:44 UTC
2a409a1d1250c8a9fcac7beaa58ae80881dda2dc
3 files changed
+28
-3
parse-options.c
+24
-1
@@ -1042,11 +1042,22 @@ static void usage_padding(FILE *outfile, size_t pos)
1042
fprintf(outfile, "%*s", pad + USAGE_GAP, "");
1043
}
1044
1045
+static const struct option *find_option_by_long_name(const struct option *opts,
1046
+ const char *long_name)
1047
+{
1048
+ for (; opts->type != OPTION_END; opts++) {
1049
+ if (opts->long_name && !strcmp(opts->long_name, long_name))
1050
+ return opts;
1051
+ }
1052
+ return NULL;
1053
+}
1054
+
1055
static enum parse_opt_result usage_with_options_internal(struct parse_opt_ctx_t *ctx,
1056
const char * const *usagestr,
1057
const struct option *opts,
1058
int full, int err)
1059
{
1060
+ const struct option *all_opts = opts;
1061
FILE *outfile = err ? stderr : stdout;
1062
int need_newline;
1063
@@ -1128,6 +1139,7 @@ static enum parse_opt_result usage_with_options_internal(struct parse_opt_ctx_t
1139
for (; opts->type != OPTION_END; opts++) {
1140
size_t pos;
1141
const char *cp, *np;
1142
+ const char *positive_name = NULL;
1143
1144
if (opts->type == OPTION_SUBCOMMAND)
1145
continue;
@@ -1157,7 +1169,8 @@ static enum parse_opt_result usage_with_options_internal(struct parse_opt_ctx_t
1169
pos += fprintf(outfile, ", ");
1170
if (opts->long_name) {
1171
const char *long_name = opts->long_name;
1160
- if (opts->flags & PARSE_OPT_NONEG)
1172
+ if ((opts->flags & PARSE_OPT_NONEG) ||
1173
+ skip_prefix(long_name, "no-", &positive_name))
1174
pos += fprintf(outfile, "--%s", long_name);
1175
else
1176
pos += fprintf(outfile, "--[no-]%s", long_name);
@@ -1185,6 +1198,16 @@ static enum parse_opt_result usage_with_options_internal(struct parse_opt_ctx_t
1198
np++;
1199
pos = 0;
1200
}
1201
+
1202
+ if (positive_name) {
1203
+ if (find_option_by_long_name(all_opts, positive_name))
1204
+ continue;
1205
+ pos = usage_indent(outfile);
1206
+ pos += fprintf(outfile, "--%s", positive_name);
1207
+ usage_padding(outfile, pos);
1208
+ fprintf_ln(outfile, _("opposite of --no-%s"),
1209
+ positive_name);
1210
+ }
1211
}
1212
fputc('\n', outfile);
1213
t/t0040-parse-options.sh
+2
-1
@@ -14,7 +14,8 @@ usage: test-tool parse-options <options>
14
A helper function for the parse-options API.
15
16
--[no-]yes get a boolean
17
- -D, --[no-]no-doubt begins with 'no-'
17
+ -D, --no-doubt begins with 'no-'
18
+ --doubt opposite of --no-doubt
19
-B, --no-fear be brave
20
-b, --[no-]boolean increment by one
21
-4, --[no-]or4 bitwise-or boolean with ...0100
t/t1502/optionspec-neg.help
+2
-1
@@ -4,7 +4,8 @@ usage: some-command [options] <args>...
4
some-command does foo and bar!
5
6
--[no-]foo can be negated
7
- --[no-]no-bar can be positivated
7
+ --no-bar can be positivated
8
+ --bar opposite of --no-bar
9
--positive-only cannot be negated
10
--no-negative cannot be positivated
11