mirror of
https://github.com/systemd/systemd.git
synced 2025-03-19 22:50:17 +03:00
Merge pull request #18338 from poettering/print-table-with-bells-and-whistles
json/table printing unification work
This commit is contained in:
commit
87970ee5bc
@ -52,4 +52,13 @@
|
||||
Before each file, the filename is printed as a comment.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry id='json'>
|
||||
<term><option>--json=</option><replaceable>MODE</replaceable></term>
|
||||
|
||||
<listitem><para>Shows output formatted as JSON. Expects one of <literal>short</literal> (for the
|
||||
shortest possible output without any redundant whitespace or line breaks), <literal>pretty</literal>
|
||||
(for a pretty version of the same, with indentation and line breaks) or <literal>off</literal> (to turn
|
||||
off JSON output, the default).</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
@ -162,15 +162,6 @@
|
||||
operation begins.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--json=</option><replaceable>MODE</replaceable></term>
|
||||
|
||||
<listitem><para>Shows output formatted as JSON. Expects one of <literal>short</literal> (for the
|
||||
shortest possible output without any redundant whitespace or line breaks), <literal>pretty</literal>
|
||||
(for a pretty version of the same, with indentation and line breaks) or <literal>off</literal> (to turn
|
||||
off json output).</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<xi:include href="standard-options.xml" xpointer="help" />
|
||||
<xi:include href="standard-options.xml" xpointer="version" />
|
||||
</variablelist>
|
||||
@ -237,6 +228,9 @@
|
||||
url="https://systemd.io/DISCOVERABLE_PARTITIONS">Discoverable Partitions Specification</ulink>.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<xi:include href="standard-options.xml" xpointer="no-pager" />
|
||||
<xi:include href="standard-options.xml" xpointer="no-legend" />
|
||||
<xi:include href="standard-options.xml" xpointer="json" />
|
||||
</variablelist>
|
||||
|
||||
</refsect1>
|
||||
|
@ -278,15 +278,6 @@
|
||||
and graphic illustrating the changes applied.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--json=</option><replaceable>MODE</replaceable></term>
|
||||
|
||||
<listitem><para>Shows output formatted as JSON. Expects one of <literal>short</literal> (for the
|
||||
shortest possible output without any redundant whitespace or line breaks), <literal>pretty</literal>
|
||||
(for a pretty version of the same, with indentation and line breaks) or <literal>off</literal> (to turn
|
||||
off json output).</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--definitions=</option></term>
|
||||
|
||||
@ -321,6 +312,9 @@
|
||||
|
||||
<xi:include href="standard-options.xml" xpointer="help" />
|
||||
<xi:include href="standard-options.xml" xpointer="version" />
|
||||
<xi:include href="standard-options.xml" xpointer="no-pager" />
|
||||
<xi:include href="standard-options.xml" xpointer="no-legend" />
|
||||
<xi:include href="standard-options.xml" xpointer="json" />
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
|
@ -211,14 +211,6 @@
|
||||
<filename>/opt/</filename> hierarchies, but below some specified root directory.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--json=</option></term>
|
||||
|
||||
<listitem><para>Generate JSON output, instead of human readable tabular output. Takes one of
|
||||
<literal>short</literal>, <literal>pretty</literal> or <literal>off</literal> in order to control the
|
||||
output style, or explicitly disabling JSON output.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--force</option></term>
|
||||
|
||||
@ -229,6 +221,8 @@
|
||||
</varlistentry>
|
||||
|
||||
<xi:include href="standard-options.xml" xpointer="no-pager" />
|
||||
<xi:include href="standard-options.xml" xpointer="no-legend" />
|
||||
<xi:include href="standard-options.xml" xpointer="json" />
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
|
@ -239,8 +239,6 @@ static int list_bus_names(int argc, char **argv, void *userdata) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to set columns to display: %m");
|
||||
|
||||
table_set_header(table, arg_legend);
|
||||
|
||||
HASHMAP_FOREACH_KEY(v, k, names) {
|
||||
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
|
||||
|
||||
@ -357,14 +355,7 @@ static int list_bus_names(int argc, char **argv, void *userdata) {
|
||||
return log_error_errno(r, "Failed to fill line: %m");
|
||||
}
|
||||
|
||||
if (arg_json_format_flags & (JSON_FORMAT_OFF|JSON_FORMAT_PRETTY|JSON_FORMAT_PRETTY_AUTO))
|
||||
(void) pager_open(arg_pager_flags);
|
||||
|
||||
r = table_print_json(table, NULL, arg_json_format_flags);
|
||||
if (r < 0)
|
||||
return table_log_print_error(r);
|
||||
|
||||
return 0;
|
||||
return table_print_with_pager(table, arg_json_format_flags, arg_pager_flags, arg_legend);
|
||||
}
|
||||
|
||||
static void print_subtree(const char *prefix, const char *path, char **l) {
|
||||
@ -2255,6 +2246,8 @@ static int help(void) {
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
(void) pager_open(arg_pager_flags);
|
||||
|
||||
printf("%s [OPTIONS...] COMMAND ...\n\n"
|
||||
"%sIntrospect the D-Bus IPC bus.%s\n"
|
||||
"\nCommands:\n"
|
||||
|
@ -46,6 +46,8 @@ static const char *arg_target = NULL;
|
||||
static DissectImageFlags arg_flags = DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_DISCARD_ON_LOOP|DISSECT_IMAGE_RELAX_VAR_CHECK|DISSECT_IMAGE_FSCK;
|
||||
static VeritySettings arg_verity_settings = VERITY_SETTINGS_DEFAULT;
|
||||
static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF;
|
||||
static PagerFlags arg_pager_flags = 0;
|
||||
static bool arg_legend = true;
|
||||
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_verity_settings, verity_settings_done);
|
||||
|
||||
@ -63,6 +65,8 @@ static int help(void) {
|
||||
"%1$s [OPTIONS...] --copy-to IMAGE [SOURCE] PATH\n\n"
|
||||
"%5$sDissect a file system OS image.%6$s\n\n"
|
||||
"%3$sOptions:%4$s\n"
|
||||
" --no-pager Do not pipe output into a pager\n"
|
||||
" --no-legend Do not show the headers and footers\n"
|
||||
" -r --read-only Mount read-only\n"
|
||||
" --fsck=BOOL Run fsck before mounting\n"
|
||||
" --mkdir Make mount directory before mounting, if missing\n"
|
||||
@ -96,6 +100,8 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
|
||||
enum {
|
||||
ARG_VERSION = 0x100,
|
||||
ARG_NO_PAGER,
|
||||
ARG_NO_LEGEND,
|
||||
ARG_DISCARD,
|
||||
ARG_FSCK,
|
||||
ARG_ROOT_HASH,
|
||||
@ -108,6 +114,8 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
static const struct option options[] = {
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "version", no_argument, NULL, ARG_VERSION },
|
||||
{ "no-pager", no_argument, NULL, ARG_NO_PAGER },
|
||||
{ "no-legend", no_argument, NULL, ARG_NO_LEGEND },
|
||||
{ "mount", no_argument, NULL, 'm' },
|
||||
{ "read-only", no_argument, NULL, 'r' },
|
||||
{ "discard", required_argument, NULL, ARG_DISCARD },
|
||||
@ -137,6 +145,14 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
case ARG_VERSION:
|
||||
return version();
|
||||
|
||||
case ARG_NO_PAGER:
|
||||
arg_pager_flags |= PAGER_DISABLE;
|
||||
break;
|
||||
|
||||
case ARG_NO_LEGEND:
|
||||
arg_legend = false;
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
arg_action = ACTION_MOUNT;
|
||||
break;
|
||||
@ -339,6 +355,9 @@ static int action_dissect(DissectedImage *m, LoopDevice *d) {
|
||||
assert(m);
|
||||
assert(d);
|
||||
|
||||
if (arg_json_format_flags & (JSON_FORMAT_OFF|JSON_FORMAT_PRETTY|JSON_FORMAT_PRETTY_AUTO))
|
||||
(void) pager_open(arg_pager_flags);
|
||||
|
||||
if (arg_json_format_flags & JSON_FORMAT_OFF)
|
||||
printf(" Name: %s\n", basename(arg_image));
|
||||
|
||||
@ -482,7 +501,9 @@ static int action_dissect(DissectedImage *m, LoopDevice *d) {
|
||||
}
|
||||
|
||||
if (arg_json_format_flags & JSON_FORMAT_OFF) {
|
||||
r = table_print(t, stdout);
|
||||
(void) table_set_header(t, arg_legend);
|
||||
|
||||
r = table_print(t, NULL);
|
||||
if (r < 0)
|
||||
return table_log_print_error(r);
|
||||
} else {
|
||||
|
@ -113,8 +113,6 @@ static int list_homes(int argc, char *argv[], void *userdata) {
|
||||
_cleanup_(table_unrefp) Table *table = NULL;
|
||||
int r;
|
||||
|
||||
(void) pager_open(arg_pager_flags);
|
||||
|
||||
r = acquire_bus(&bus);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -175,11 +173,9 @@ static int list_homes(int argc, char *argv[], void *userdata) {
|
||||
if (r < 0)
|
||||
return table_log_sort_error(r);
|
||||
|
||||
table_set_header(table, arg_legend);
|
||||
|
||||
r = table_print_json(table, stdout, arg_json_format_flags);
|
||||
r = table_print_with_pager(table, arg_json_format_flags, arg_pager_flags, arg_legend);
|
||||
if (r < 0)
|
||||
return table_log_print_error(r);
|
||||
return r;
|
||||
}
|
||||
|
||||
if (arg_legend && (arg_json_format_flags & JSON_FORMAT_OFF)) {
|
||||
|
@ -107,6 +107,8 @@ static int arg_pretty = -1;
|
||||
static uint64_t arg_size = UINT64_MAX;
|
||||
static bool arg_size_auto = false;
|
||||
static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF;
|
||||
static PagerFlags arg_pager_flags = 0;
|
||||
static bool arg_legend = true;
|
||||
static void *arg_key = NULL;
|
||||
static size_t arg_key_size = 0;
|
||||
static char *arg_tpm2_device = NULL;
|
||||
@ -1918,11 +1920,7 @@ static int context_dump_partitions(Context *context, const char *node) {
|
||||
return table_log_add_error(r);
|
||||
}
|
||||
|
||||
r = table_print_json(t, stdout, arg_json_format_flags);
|
||||
if (r < 0)
|
||||
return table_log_print_error(r);
|
||||
|
||||
return 0;
|
||||
return table_print_with_pager(t, arg_json_format_flags, arg_pager_flags, arg_legend);
|
||||
}
|
||||
|
||||
static void context_bar_char_process_partition(
|
||||
@ -3479,6 +3477,8 @@ static int help(void) {
|
||||
"\n%sGrow and add partitions to partition table.%s\n\n"
|
||||
" -h --help Show this help\n"
|
||||
" --version Show package version\n"
|
||||
" --no-pager Do not pipe output into a pager\n"
|
||||
" --no-legend Do not show the headers and footers\n"
|
||||
" --dry-run=BOOL Whether to run dry-run operation\n"
|
||||
" --empty=MODE One of refuse, allow, require, force, create; controls\n"
|
||||
" how to handle empty disks lacking partition tables\n"
|
||||
@ -3510,6 +3510,8 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
|
||||
enum {
|
||||
ARG_VERSION = 0x100,
|
||||
ARG_NO_PAGER,
|
||||
ARG_NO_LEGEND,
|
||||
ARG_DRY_RUN,
|
||||
ARG_EMPTY,
|
||||
ARG_DISCARD,
|
||||
@ -3529,6 +3531,8 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
static const struct option options[] = {
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "version", no_argument, NULL, ARG_VERSION },
|
||||
{ "no-pager", no_argument, NULL, ARG_NO_PAGER },
|
||||
{ "no-legend", no_argument, NULL, ARG_NO_LEGEND },
|
||||
{ "dry-run", required_argument, NULL, ARG_DRY_RUN },
|
||||
{ "empty", required_argument, NULL, ARG_EMPTY },
|
||||
{ "discard", required_argument, NULL, ARG_DISCARD },
|
||||
@ -3561,6 +3565,14 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
case ARG_VERSION:
|
||||
return version();
|
||||
|
||||
case ARG_NO_PAGER:
|
||||
arg_pager_flags |= PAGER_DISABLE;
|
||||
break;
|
||||
|
||||
case ARG_NO_LEGEND:
|
||||
arg_legend = false;
|
||||
break;
|
||||
|
||||
case ARG_DRY_RUN:
|
||||
r = parse_boolean(optarg);
|
||||
if (r < 0)
|
||||
|
@ -2550,3 +2550,30 @@ int table_print_json(Table *t, FILE *f, JsonFormatFlags flags) {
|
||||
|
||||
return fflush_and_check(f);
|
||||
}
|
||||
|
||||
int table_print_with_pager(
|
||||
Table *t,
|
||||
JsonFormatFlags json_format_flags,
|
||||
PagerFlags pager_flags,
|
||||
bool show_header) {
|
||||
|
||||
bool saved_header;
|
||||
int r;
|
||||
|
||||
assert(t);
|
||||
|
||||
/* A all-in-one solution for showing tables, and turning on a pager first. Also optionally suppresses
|
||||
* the table header and logs about any error. */
|
||||
|
||||
if (json_format_flags & (JSON_FORMAT_OFF|JSON_FORMAT_PRETTY|JSON_FORMAT_PRETTY_AUTO))
|
||||
(void) pager_open(pager_flags);
|
||||
|
||||
saved_header = t->header;
|
||||
t->header = show_header;
|
||||
r = table_print_json(t, stdout, json_format_flags);
|
||||
t->header = saved_header;
|
||||
if (r < 0)
|
||||
return table_log_print_error(r);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include "json.h"
|
||||
#include "macro.h"
|
||||
#include "pager.h"
|
||||
|
||||
typedef enum TableDataType {
|
||||
TABLE_EMPTY,
|
||||
@ -129,6 +130,8 @@ const void *table_get_at(Table *t, size_t row, size_t column);
|
||||
int table_to_json(Table *t, JsonVariant **ret);
|
||||
int table_print_json(Table *t, FILE *f, JsonFormatFlags json_flags);
|
||||
|
||||
int table_print_with_pager(Table *t, JsonFormatFlags json_format_flags, PagerFlags pager_flags, bool show_header);
|
||||
|
||||
#define table_log_add_error(r) \
|
||||
log_error_errno(r, "Failed to add cell(s) to table: %m")
|
||||
|
||||
|
@ -35,6 +35,7 @@ static char **arg_hierarchies = NULL; /* "/usr" + "/opt" by default */
|
||||
static char *arg_root = NULL;
|
||||
static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF;
|
||||
static PagerFlags arg_pager_flags = 0;
|
||||
static bool arg_legend = true;
|
||||
static bool arg_force = false;
|
||||
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_hierarchies, strv_freep);
|
||||
@ -226,12 +227,9 @@ static int verb_status(int argc, char **argv, void *userdata) {
|
||||
|
||||
(void) table_set_sort(t, (size_t) 0, (size_t) -1);
|
||||
|
||||
if (arg_json_format_flags & (JSON_FORMAT_OFF|JSON_FORMAT_PRETTY|JSON_FORMAT_PRETTY_AUTO))
|
||||
(void) pager_open(arg_pager_flags);
|
||||
|
||||
r = table_print_json(t, stdout, arg_json_format_flags);
|
||||
r = table_print_with_pager(t, arg_json_format_flags, arg_pager_flags, arg_legend);
|
||||
if (r < 0)
|
||||
return table_log_add_error(r);
|
||||
return r;
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -860,14 +858,7 @@ static int verb_list(int argc, char **argv, void *userdata) {
|
||||
|
||||
(void) table_set_sort(t, (size_t) 0, (size_t) -1);
|
||||
|
||||
if (arg_json_format_flags & (JSON_FORMAT_OFF|JSON_FORMAT_PRETTY|JSON_FORMAT_PRETTY_AUTO))
|
||||
(void) pager_open(arg_pager_flags);
|
||||
|
||||
r = table_print_json(t, stdout, arg_json_format_flags);
|
||||
if (r < 0)
|
||||
return table_log_print_error(r);
|
||||
|
||||
return 0;
|
||||
return table_print_with_pager(t, arg_json_format_flags, arg_pager_flags, arg_legend);
|
||||
}
|
||||
|
||||
static int verb_help(int argc, char **argv, void *userdata) {
|
||||
@ -890,6 +881,7 @@ static int verb_help(int argc, char **argv, void *userdata) {
|
||||
" --version Show package version\n"
|
||||
"\n%3$sOptions:%4$s\n"
|
||||
" --no-pager Do not pipe output into a pager\n"
|
||||
" --no-legend Do not show the headers and footers\n"
|
||||
" --root=PATH Operate relative to root path\n"
|
||||
" --json=pretty|short|off\n"
|
||||
" Generate JSON output\n"
|
||||
@ -909,18 +901,20 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
enum {
|
||||
ARG_VERSION = 0x100,
|
||||
ARG_NO_PAGER,
|
||||
ARG_NO_LEGEND,
|
||||
ARG_ROOT,
|
||||
ARG_JSON,
|
||||
ARG_FORCE,
|
||||
};
|
||||
|
||||
static const struct option options[] = {
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "version", no_argument, NULL, ARG_VERSION },
|
||||
{ "no-pager", no_argument, NULL, ARG_NO_PAGER },
|
||||
{ "root", required_argument, NULL, ARG_ROOT },
|
||||
{ "json", required_argument, NULL, ARG_JSON },
|
||||
{ "force", no_argument, NULL, ARG_FORCE },
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "version", no_argument, NULL, ARG_VERSION },
|
||||
{ "no-pager", no_argument, NULL, ARG_NO_PAGER },
|
||||
{ "no-legend", no_argument, NULL, ARG_NO_LEGEND },
|
||||
{ "root", required_argument, NULL, ARG_ROOT },
|
||||
{ "json", required_argument, NULL, ARG_JSON },
|
||||
{ "force", no_argument, NULL, ARG_FORCE },
|
||||
{}
|
||||
};
|
||||
|
||||
@ -943,6 +937,10 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
arg_pager_flags |= PAGER_DISABLE;
|
||||
break;
|
||||
|
||||
case ARG_NO_LEGEND:
|
||||
arg_legend = false;
|
||||
break;
|
||||
|
||||
case ARG_ROOT:
|
||||
r = parse_path_argument_and_warn(optarg, false, &arg_root);
|
||||
if (r < 0)
|
||||
|
Loading…
x
Reference in New Issue
Block a user