format-table: add new string cell type that accepts ANSI sequences
For various usecases it's useful that we can embed ANSI sequences in cells of tables. For example, I hope we can eventually switch "systemctl status" output to use the table formatter, and multiple of its fields contain ANSI sequences (since they pack multiple different pieces information into the same field, and highlight parts of it to communicate relevance of distinct parts). Add a distinct cell type for this, which gets special processing when we output to a terminal that doesn't support ANSI sequences, and to JSON: we strip the sequences.
This commit is contained in:
@@ -4,6 +4,8 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "ansi-color.h"
|
||||
#include "env-util.h"
|
||||
#include "format-table.h"
|
||||
#include "json-util.h"
|
||||
#include "terminal-util.h"
|
||||
@@ -835,9 +837,80 @@ TEST(table_bps) {
|
||||
"2500000000 2.3G 2.5Gbps\n");
|
||||
}
|
||||
|
||||
TEST(table_ansi) {
|
||||
_cleanup_(table_unrefp) Table *table = NULL;
|
||||
|
||||
ASSERT_NOT_NULL((table = table_new("foo", "bar", "baz", "kkk")));
|
||||
|
||||
ASSERT_OK(table_add_many(table,
|
||||
TABLE_STRING, "hallo",
|
||||
TABLE_STRING_WITH_ANSI, "knuerz" ANSI_HIGHLIGHT_RED "red" ANSI_HIGHLIGHT_GREEN "green",
|
||||
TABLE_STRING_WITH_ANSI, "noansi",
|
||||
TABLE_STRING_WITH_ANSI, ANSI_GREY "thisisgrey"));
|
||||
|
||||
unsigned saved_columns = columns();
|
||||
bool saved_color = colors_enabled();
|
||||
_cleanup_free_ char *saved_term = NULL;
|
||||
const char *e = getenv("TERM");
|
||||
if (e)
|
||||
ASSERT_NOT_NULL((saved_term = strdup(e)));
|
||||
|
||||
ASSERT_OK_ERRNO(setenv("COLUMNS", "200", /* overwrite= */ true));
|
||||
ASSERT_OK_ERRNO(setenv("SYSTEMD_COLORS", "1", /* overwrite= */ true));
|
||||
ASSERT_OK_ERRNO(setenv("TERM", FALLBACK_TERM, /* overwrite= */ true));
|
||||
reset_terminal_feature_caches();
|
||||
|
||||
_cleanup_free_ char *formatted = NULL;
|
||||
ASSERT_OK(table_format(table, &formatted));
|
||||
|
||||
ASSERT_STREQ(formatted,
|
||||
ANSI_ADD_UNDERLINE "FOO " ANSI_NORMAL
|
||||
ANSI_ADD_UNDERLINE " " ANSI_NORMAL
|
||||
ANSI_ADD_UNDERLINE "BAR " ANSI_NORMAL
|
||||
ANSI_ADD_UNDERLINE " " ANSI_NORMAL
|
||||
ANSI_ADD_UNDERLINE "BAZ " ANSI_NORMAL
|
||||
ANSI_ADD_UNDERLINE " " ANSI_NORMAL
|
||||
ANSI_ADD_UNDERLINE "KKK " ANSI_NORMAL "\n"
|
||||
"hallo knuerz" ANSI_HIGHLIGHT_RED "red" ANSI_HIGHLIGHT_GREEN "green" ANSI_NORMAL
|
||||
" noansi" ANSI_NORMAL
|
||||
" " ANSI_GREY "thisisgrey" ANSI_NORMAL "\n");
|
||||
|
||||
/* Validate that color is correctly stripped */
|
||||
ASSERT_OK_ERRNO(setenv("SYSTEMD_COLORS", "0", /* overwrite= */ true));
|
||||
reset_terminal_feature_caches();
|
||||
|
||||
formatted = mfree(formatted);
|
||||
ASSERT_OK(table_format(table, &formatted));
|
||||
|
||||
ASSERT_STREQ(formatted,
|
||||
"FOO BAR BAZ KKK\n"
|
||||
"hallo knuerzredgreen noansi thisisgrey\n");
|
||||
|
||||
ASSERT_OK(table_print(table, /* f= */ NULL));
|
||||
|
||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *j = NULL, *jj = NULL;
|
||||
|
||||
ASSERT_OK(table_to_json(table, &j));
|
||||
|
||||
ASSERT_OK(sd_json_build(&jj,
|
||||
SD_JSON_BUILD_ARRAY(
|
||||
SD_JSON_BUILD_OBJECT(
|
||||
SD_JSON_BUILD_PAIR_STRING("foo", "hallo"),
|
||||
SD_JSON_BUILD_PAIR_STRING("bar", "knuerzredgreen"),
|
||||
SD_JSON_BUILD_PAIR_STRING("baz", "noansi"),
|
||||
SD_JSON_BUILD_PAIR_STRING("kkk", "thisisgrey")))));
|
||||
ASSERT_TRUE(sd_json_variant_equal(j, jj));
|
||||
|
||||
ASSERT_OK(sd_json_variant_dump(j, SD_JSON_FORMAT_COLOR_AUTO|SD_JSON_FORMAT_PRETTY_AUTO, /* f= */ NULL, /* prefix= */ NULL));
|
||||
|
||||
ASSERT_OK(setenvf("COLUMNS", /* overwrite= */ true, "%u", saved_columns));
|
||||
ASSERT_OK(setenvf("SYSTEMD_COLORS", /* overwrite= */ true, "%i", saved_color));
|
||||
ASSERT_OK(set_unset_env("TERM", saved_term, /* overwrite= */ true));
|
||||
}
|
||||
|
||||
static int intro(void) {
|
||||
ASSERT_OK(setenv("SYSTEMD_COLORS", "0", 1));
|
||||
ASSERT_OK(setenv("COLUMNS", "40", 1));
|
||||
ASSERT_OK_ERRNO(setenv("SYSTEMD_COLORS", "0", /* overwrite= */ true));
|
||||
ASSERT_OK_ERRNO(setenv("COLUMNS", "40", /* overwrite= */ true));
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user