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.
This commit is contained in:
+34
-25
@@ -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);
|
||||
_cleanup_free_ char *s = NULL;
|
||||
|
||||
/* 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) ? "]" : "");
|
||||
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();
|
||||
|
||||
|
||||
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user