diff options
Diffstat (limited to 'parse-options.c')
-rw-r--r-- | parse-options.c | 75 |
1 files changed, 61 insertions, 14 deletions
diff --git a/parse-options.c b/parse-options.c index f8a155ee13..e8e076c3a6 100644 --- a/parse-options.c +++ b/parse-options.c @@ -480,6 +480,9 @@ static void parse_options_check(const struct option *opts) opts->long_name)) optbug(opts, "uses feature " "not supported for dashless options"); + if (opts->type == OPTION_SET_INT && !opts->defval && + opts->long_name && !(opts->flags & PARSE_OPT_NONEG)) + optbug(opts, "OPTION_SET_INT 0 should not be negatable"); switch (opts->type) { case OPTION_COUNTUP: case OPTION_BIT: @@ -1020,14 +1023,37 @@ static int usage_argh(const struct option *opts, FILE *outfile) return utf8_fprintf(outfile, s, opts->argh ? _(opts->argh) : _("...")); } -#define USAGE_OPTS_WIDTH 24 -#define USAGE_GAP 2 +static int usage_indent(FILE *outfile) +{ + return fprintf(outfile, " "); +} + +#define USAGE_OPTS_WIDTH 26 + +static void usage_padding(FILE *outfile, size_t pos) +{ + if (pos < USAGE_OPTS_WIDTH) + fprintf(outfile, "%*s", USAGE_OPTS_WIDTH - (int)pos, ""); + else + fprintf(outfile, "\n%*s", USAGE_OPTS_WIDTH, ""); +} + +static const struct option *find_option_by_long_name(const struct option *opts, + const char *long_name) +{ + for (; opts->type != OPTION_END; opts++) { + if (opts->long_name && !strcmp(opts->long_name, long_name)) + return opts; + } + return NULL; +} static enum parse_opt_result usage_with_options_internal(struct parse_opt_ctx_t *ctx, const char * const *usagestr, const struct option *opts, int full, int err) { + const struct option *all_opts = opts; FILE *outfile = err ? stderr : stdout; int need_newline; @@ -1108,7 +1134,8 @@ 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; + const char *positive_name = NULL; if (opts->type == OPTION_SUBCOMMAND) continue; @@ -1127,7 +1154,7 @@ static enum parse_opt_result usage_with_options_internal(struct parse_opt_ctx_t need_newline = 0; } - pos = fprintf(outfile, " "); + pos = usage_indent(outfile); if (opts->short_name) { if (opts->flags & PARSE_OPT_NODASH) pos += fprintf(outfile, "%c", opts->short_name); @@ -1136,8 +1163,15 @@ static enum parse_opt_result usage_with_options_internal(struct parse_opt_ctx_t } if (opts->long_name && opts->short_name) pos += fprintf(outfile, ", "); - if (opts->long_name) - pos += fprintf(outfile, "--%s", opts->long_name); + if (opts->long_name) { + const char *long_name = opts->long_name; + if ((opts->flags & PARSE_OPT_NONEG) || + skip_prefix(long_name, "no-", &positive_name)) + pos += fprintf(outfile, "--%s", long_name); + else + pos += fprintf(outfile, "--[no-]%s", long_name); + } + if (opts->type == OPTION_NUMBER) pos += utf8_fprintf(outfile, _("-NUM")); @@ -1145,19 +1179,32 @@ 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) - pad = USAGE_OPTS_WIDTH - pos; - else { - fputc('\n', outfile); - pad = USAGE_OPTS_WIDTH; - } if (opts->type == OPTION_ALIAS) { - fprintf(outfile, "%*s", pad + USAGE_GAP, ""); + usage_padding(outfile, pos); fprintf_ln(outfile, _("alias of --%s"), (const char *)opts->value); continue; } - fprintf(outfile, "%*s%s\n", pad + USAGE_GAP, "", _(opts->help)); + + for (cp = opts->help ? _(opts->help) : ""; *cp; cp = np) { + np = strchrnul(cp, '\n'); + if (*np) + np++; + usage_padding(outfile, pos); + fwrite(cp, 1, np - cp, outfile); + pos = 0; + } + fputc('\n', outfile); + + if (positive_name) { + if (find_option_by_long_name(all_opts, positive_name)) + continue; + pos = usage_indent(outfile); + pos += fprintf(outfile, "--%s", positive_name); + usage_padding(outfile, pos); + fprintf_ln(outfile, _("opposite of --no-%s"), + positive_name); + } } fputc('\n', outfile); |