shared/verbs: add a footer for verbs
This will be needed for 'udevadm hwdb' which carries a footer.
This commit is contained in:
@@ -629,6 +629,10 @@ int _command_print_verb_help(
|
||||
return r;
|
||||
}
|
||||
|
||||
r = print_wrapped(verb->footer, /* footer_ansi_seq= */ NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = print_man_links(cmd->man_pages);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to print man page links: %m");
|
||||
@@ -672,6 +676,9 @@ static int verb_build_json(
|
||||
!!verb->help,
|
||||
"abstract", SD_JSON_BUILD_STRV(STRV_MAKE(verb->help))),
|
||||
SD_JSON_BUILD_PAIR_CONDITION(!!opts, "options", SD_JSON_BUILD_VARIANT(opts)),
|
||||
SD_JSON_BUILD_PAIR_CONDITION(
|
||||
!!verb->footer,
|
||||
"postscript", SD_JSON_BUILD_STRV(STRV_MAKE(verb->footer))),
|
||||
SD_JSON_BUILD_PAIR_CONDITION(
|
||||
verb->min_args != VERB_ANY,
|
||||
"minArguments", SD_JSON_BUILD_UNSIGNED(verb->min_args)),
|
||||
|
||||
+19
-15
@@ -44,11 +44,12 @@ typedef struct _alignptr_ Verb {
|
||||
uintptr_t data;
|
||||
const char *argspec; /* optional nulstr with specifications of positional args */
|
||||
const char *help;
|
||||
const char *footer; /* optional footer to print in --help */
|
||||
const char *option_namespace; /* optional namespace with the verb's own options */
|
||||
} Verb;
|
||||
assert_cc(sizeof(Verb) % sizeof(void*) == 0);
|
||||
|
||||
#define _VERB_DATA(d, v, ns, a, amin, amax, f, dat, h) \
|
||||
#define _VERB_DATA(d, v, ns, a, amin, amax, f, dat, h, ft) \
|
||||
_section_("SYSTEMD_VERBS") \
|
||||
_alignptr_ \
|
||||
_used_ \
|
||||
@@ -64,31 +65,32 @@ assert_cc(sizeof(Verb) % sizeof(void*) == 0);
|
||||
.data = dat, \
|
||||
.argspec = a, \
|
||||
.help = h, \
|
||||
.footer = ft, \
|
||||
.option_namespace = ns, \
|
||||
}
|
||||
|
||||
/* Forward-define function d. scope specifies the scope, e.g. static. ns declares the option
|
||||
* namespace with the verb's own options, which are then shown in the verb's help (see
|
||||
* command_print_verb_help()) and reported in the CLI introspection. */
|
||||
#define VERB_SCOPE_NS_FULL(scope, d, v, ns, a, amin, amax, f, dat, h) \
|
||||
#define VERB_SCOPE_NS_FULL(scope, d, v, ns, a, amin, amax, f, dat, h, ft) \
|
||||
DISABLE_WARNING_REDUNDANT_DECLS \
|
||||
scope int d(int, char**, uintptr_t, void*); \
|
||||
REENABLE_WARNING \
|
||||
_VERB_DATA(d, v, ns, a, amin, amax, f, dat, h)
|
||||
_VERB_DATA(d, v, ns, a, amin, amax, f, dat, h, ft)
|
||||
/* The same as VERB_SCOPE_NS_FULL, but for verbs without options of their own. */
|
||||
#define VERB_SCOPE_FULL(scope, d, v, a, amin, amax, f, dat, h) \
|
||||
VERB_SCOPE_NS_FULL(scope, d, v, /* ns= */ NULL, a, amin, amax, f, dat, h)
|
||||
#define VERB_SCOPE_FULL(scope, d, v, a, amin, amax, f, dat, h, ft) \
|
||||
VERB_SCOPE_NS_FULL(scope, d, v, /* ns= */ NULL, a, amin, amax, f, dat, h, ft)
|
||||
/* The same as VERB_SCOPE_NS_FULL/VERB_SCOPE_FULL with scope hardwired to 'static'. */
|
||||
#define VERB_NS_FULL(d, v, ns, a, amin, amax, f, dat, h) \
|
||||
VERB_SCOPE_NS_FULL(static, d, v, ns, a, amin, amax, f, dat, h)
|
||||
#define VERB_NS_FULL(d, v, ns, a, amin, amax, f, dat, h, ft) \
|
||||
VERB_SCOPE_NS_FULL(static, d, v, ns, a, amin, amax, f, dat, h, ft)
|
||||
#define VERB_FULL(d, v, a, amin, amax, f, dat, h) \
|
||||
VERB_SCOPE_FULL(static, d, v, a, amin, amax, f, dat, h)
|
||||
VERB_SCOPE_FULL(static, d, v, a, amin, amax, f, dat, h, /* ft= */ NULL)
|
||||
|
||||
/* The same as the macros above, but without the data argument. */
|
||||
#define VERB_SCOPE_NS(scope, d, v, ns, a, amin, amax, f, h) \
|
||||
VERB_SCOPE_NS_FULL(scope, d, v, ns, a, amin, amax, f, /* dat= */ 0, h)
|
||||
VERB_SCOPE_NS_FULL(scope, d, v, ns, a, amin, amax, f, /* dat= */ 0, h, /* ft= */ NULL)
|
||||
#define VERB_SCOPE(scope, d, v, a, amin, amax, f, h) \
|
||||
VERB_SCOPE_FULL(scope, d, v, a, amin, amax, f, /* dat= */ 0, h)
|
||||
VERB_SCOPE_FULL(scope, d, v, a, amin, amax, f, /* dat= */ 0, h, /* ft= */ NULL)
|
||||
#define VERB_NS(d, v, ns, a, amin, amax, f, h) \
|
||||
VERB_SCOPE_NS(static, d, v, ns, a, amin, amax, f, h)
|
||||
#define VERB(d, v, a, amin, amax, f, h) \
|
||||
@@ -106,13 +108,15 @@ assert_cc(sizeof(Verb) % sizeof(void*) == 0);
|
||||
* The macro works as a separator between groups and must be between other VERB* stanzas. */
|
||||
#define VERB_GROUP(gr) \
|
||||
_VERB_DATA(/* d= */ NULL, /* v= */ gr, /* ns= */ NULL, /* a= */ NULL, \
|
||||
/* amin= */ 0, /* amax= */ 0, /* f= */ VERB_GROUP_MARKER, /* dat= */ 0, /* h= */ NULL)
|
||||
/* amin= */ 0, /* amax= */ 0, /* f= */ VERB_GROUP_MARKER, /* dat= */ 0, \
|
||||
/* h= */ NULL, /* ft= */ NULL)
|
||||
|
||||
#define _COMMAND(u, ...) \
|
||||
#define _COMMAND(u, ...) \
|
||||
static const CommandDescription UNIQ_T(description, u) = { __VA_ARGS__ }; \
|
||||
_VERB_DATA(/* d= */ NULL, /* v= */ NULL, /* ns= */ NULL, /* a= */ NULL, \
|
||||
/* amin= */ 0, /* amax= */ 0, /* f= */ VERB_COMMAND_MARKER, \
|
||||
/* dat= */ (uintptr_t) &UNIQ_T(description, u), /* h= */ NULL)
|
||||
_VERB_DATA(/* d= */ NULL, /* v= */ NULL, /* ns= */ NULL, /* a= */ NULL, \
|
||||
/* amin= */ 0, /* amax= */ 0, /* f= */ VERB_COMMAND_MARKER, \
|
||||
/* dat= */ (uintptr_t) &UNIQ_T(description, u), \
|
||||
/* h= */ NULL, /* ft= */ NULL)
|
||||
#define COMMAND(...) _COMMAND(UNIQ, __VA_ARGS__)
|
||||
|
||||
/* This is magically mapped to the beginning and end of the section */
|
||||
|
||||
@@ -101,7 +101,7 @@ static const Verb introspect_verbs[] = {
|
||||
.help = "Beta verb" },
|
||||
{ .verb = "gamma", .flags = VERB_OPTION_REQUIRED,
|
||||
.min_args = VERB_ANY, .max_args = VERB_ANY, .dispatch = noop_dispatcher,
|
||||
.help = "Gamma verb" },
|
||||
.help = "Gamma verb", .footer = "Gamma footer" },
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user