From: Zbigniew Jędrzejewski-Szmek Date: Fri, 10 Apr 2026 17:06:00 +0000 (+0200) Subject: shared/options: add option to generate a help line for custom option format X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=10e78e0b0ee94c553fdf6cb88c115af702408c19;p=thirdparty%2Fsystemd.git shared/options: add option to generate a help line for custom option format Sometimes we want to document what -RR or -vv does or some other special thing. Let's allow this by (ab-)using long_code pointer to store a preformatted string. --- diff --git a/src/shared/options.c b/src/shared/options.c index e5206e641d8..dc2fb34cf62 100644 --- a/src/shared/options.c +++ b/src/shared/options.c @@ -21,8 +21,9 @@ static bool option_arg_required(const Option *opt) { static bool option_is_metadata(const Option *opt) { /* A metadata entry that is not a real option, like the group marker */ - return FLAGS_SET(ASSERT_PTR(opt)->flags, OPTION_GROUP_MARKER) || - FLAGS_SET(ASSERT_PTR(opt)->flags, OPTION_HELP_ENTRY); + return ASSERT_PTR(opt)->flags & (OPTION_GROUP_MARKER | + OPTION_HELP_ENTRY | + OPTION_HELP_ENTRY_VERBATIM); } static void shift_arg(char* argv[], int target, int source) { @@ -313,30 +314,38 @@ int _option_parser_get_help_table( /* No help string — we do not show the option */ continue; - char sc[3] = " "; - if (opt->short_code != 0) - xsprintf(sc, "-%c", opt->short_code); - - /* We indent the option string by two spaces. We could set the minimum cell width and - * right-align for a similar result, but that'd be more work. This is only used for - * display. - * - * "=" is shown only when a long option is defined: -l --long=ARG, --long=ARG, -s ARG. - */ - bool need_eq = option_takes_arg(opt) && opt->long_code; - bool need_quote = opt->metavar && strchr(opt->metavar, ' '); - _cleanup_free_ char *s = strjoin( - " ", - sc, - " ", - opt->long_code ? "--" : "", - strempty(opt->long_code), - option_arg_optional(opt) ? "[" : "", - need_eq ? "=" : "", - need_quote ? "'" : "", - strempty(opt->metavar), - need_quote ? "'" : "", - option_arg_optional(opt) ? "]" : ""); + _cleanup_free_ char *s = NULL; + + if (FLAGS_SET(opt->flags, OPTION_HELP_ENTRY_VERBATIM)) { + assert(opt->long_code); + + s = strjoin(" ", + opt->long_code); + } else { + char sc[3] = " "; + if (opt->short_code != 0) + xsprintf(sc, "-%c", opt->short_code); + + /* We indent the option string by two spaces. We could set the minimum cell width and + * right-align for a similar result, but that'd be more work. This is only used for + * display. + * + * "=" is shown only when a long option is defined: -l --long=ARG, --long=ARG, -s ARG. + */ + bool need_eq = option_takes_arg(opt) && opt->long_code; + bool need_quote = opt->metavar && strchr(opt->metavar, ' '); + s = strjoin(" ", + sc, + " ", + opt->long_code ? "--" : "", + strempty(opt->long_code), + option_arg_optional(opt) ? "[" : "", + need_eq ? "=" : "", + need_quote ? "'" : "", + strempty(opt->metavar), + need_quote ? "'" : "", + option_arg_optional(opt) ? "]" : ""); + } if (!s) return log_oom(); diff --git a/src/shared/options.h b/src/shared/options.h index e834cbededa..e8256059d15 100644 --- a/src/shared/options.h +++ b/src/shared/options.h @@ -5,10 +5,11 @@ #include "shared-forward.h" typedef enum OptionFlags { - OPTION_OPTIONAL_ARG = 1U << 0, /* Same as optional_argument in getopt */ - OPTION_STOPS_PARSING = 1U << 1, /* This option acts like "--" */ - OPTION_GROUP_MARKER = 1U << 2, /* Fake option entry to separate groups */ - OPTION_HELP_ENTRY = 1U << 3, /* Fake option entry to insert an additional help line */ + OPTION_OPTIONAL_ARG = 1U << 0, /* Same as optional_argument in getopt */ + OPTION_STOPS_PARSING = 1U << 1, /* This option acts like "--" */ + OPTION_GROUP_MARKER = 1U << 2, /* Fake option entry to separate groups */ + OPTION_HELP_ENTRY = 1U << 3, /* Fake option entry to insert an additional help line */ + OPTION_HELP_ENTRY_VERBATIM = 1U << 4, /* Same, but use the long_code in the first column as written */ } OptionFlags; typedef struct Option { @@ -49,6 +50,7 @@ typedef struct Option { #define OPTION_LONG_FLAGS(fl, lc, mv, h) OPTION_FULL(fl, /* sc= */ 0, lc, mv, h) #define OPTION_SHORT(sc, mv, h) OPTION(sc, /* lc= */ NULL, mv, h) #define OPTION_SHORT_FLAGS(fl, sc, mv, h) OPTION_FULL(fl, sc, /* lc= */ NULL, mv, h) +#define OPTION_HELP_VERBATIM(lc, h) OPTION_FULL(OPTION_HELP_ENTRY_VERBATIM, /* sc= */ 0, lc, /* mv= */ NULL, h) #define OPTION_COMMON_HELP \ OPTION('h', "help", NULL, "Show this help")