]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
format-table: add a proper "underline" concept to cells
authorLennart Poettering <lennart@poettering.net>
Mon, 20 Nov 2023 11:06:11 +0000 (12:06 +0100)
committerLennart Poettering <lennart@poettering.net>
Mon, 20 Nov 2023 12:05:50 +0000 (13:05 +0100)
src/shared/format-table.c
src/shared/format-table.h

index 9a19177fde334aa730c1323a39a3ebda499b3994..41471dade038964162787da96a81af7f5d118c83 100644 (file)
@@ -77,7 +77,9 @@ typedef struct TableData {
         unsigned ellipsize_percent; /* 0 … 100, where to place the ellipsis when compression is needed */
         unsigned align_percent;     /* 0 … 100, where to pad with spaces when expanding is needed. 0: left-aligned, 100: right-aligned */
 
-        bool uppercase;             /* Uppercase string on display */
+        bool uppercase:1;           /* Uppercase string on display */
+        bool underline:1;
+        bool rgap_underline:1;
 
         const char *color;          /* ANSI color string to use for this cell. When written to terminal should not move cursor. Will automatically be reset after the cell */
         const char *rgap_color;     /* The ANSI color to use for the gap right of this cell. Usually used to underline entire rows in a gapless fashion */
@@ -401,7 +403,7 @@ static bool table_data_matches(
                 return false;
 
         /* If a color/url is set, refuse to merge */
-        if (d->color || d->rgap_color)
+        if (d->color || d->rgap_color || d->underline || d->rgap_underline)
                 return false;
         if (d->url)
                 return false;
@@ -617,6 +619,8 @@ static int table_dedup_cell(Table *t, TableCell *cell) {
 
         nd->color = od->color;
         nd->rgap_color = od->rgap_color;
+        nd->underline = od->underline;
+        nd->rgap_underline = od->rgap_underline;
         nd->url = TAKE_PTR(curl);
 
         table_data_unref(od);
@@ -759,6 +763,46 @@ int table_set_rgap_color(Table *t, TableCell *cell, const char *color) {
         return 0;
 }
 
+int table_set_underline(Table *t, TableCell *cell, bool b) {
+        TableData *d;
+        int r;
+
+        assert(t);
+        assert(cell);
+
+        r = table_dedup_cell(t, cell);
+        if (r < 0)
+                return r;
+
+        assert_se(d = table_get_data(t, cell));
+
+        if (d->underline == b)
+                return 0;
+
+        d->underline = b;
+        return 1;
+}
+
+int table_set_rgap_underline(Table *t, TableCell *cell, bool b) {
+        TableData *d;
+        int r;
+
+        assert(t);
+        assert(cell);
+
+        r = table_dedup_cell(t, cell);
+        if (r < 0)
+                return r;
+
+        assert_se(d = table_get_data(t, cell));
+
+        if (d->rgap_underline == b)
+                return 0;
+
+        d->rgap_underline = b;
+        return 1;
+}
+
 int table_set_url(Table *t, TableCell *cell, const char *url) {
         _cleanup_free_ char *copy = NULL;
         int r;
@@ -834,6 +878,8 @@ int table_update(Table *t, TableCell *cell, TableDataType type, const void *data
 
         nd->color = od->color;
         nd->rgap_color = od->rgap_color;
+        nd->underline = od->underline;
+        nd->rgap_underline = od->rgap_underline;
         nd->url = TAKE_PTR(curl);
 
         table_data_unref(od);
@@ -1101,6 +1147,31 @@ int table_add_many_internal(Table *t, TableDataType first_type, ...) {
                         goto check;
                 }
 
+                case TABLE_SET_UNDERLINE: {
+                        int u = va_arg(ap, int);
+                        r = table_set_underline(t, last_cell, u);
+                        goto check;
+                }
+
+                case TABLE_SET_RGAP_UNDERLINE: {
+                        int u = va_arg(ap, int);
+                        r = table_set_rgap_underline(t, last_cell, u);
+                        goto check;
+                }
+
+                case TABLE_SET_BOTH_UNDERLINES: {
+                        int u = va_arg(ap, int);
+
+                        r = table_set_underline(t, last_cell, u);
+                        if (r < 0) {
+                                va_end(ap);
+                                return r;
+                        }
+
+                        r = table_set_rgap_underline(t, last_cell, u);
+                        goto check;
+                }
+
                 case TABLE_SET_URL: {
                         const char *u = va_arg(ap, const char*);
                         r = table_set_url(t, last_cell, u);
@@ -2130,8 +2201,6 @@ static const char* table_data_color(TableData *d) {
 
         if (d->type == TABLE_FIELD)
                 return ansi_bright_blue();
-        if (d->type == TABLE_HEADER)
-                return ansi_underline();
 
         return NULL;
 }
@@ -2139,11 +2208,29 @@ static const char* table_data_color(TableData *d) {
 static const char* table_data_rgap_color(TableData *d) {
         assert(d);
 
-        if (d->rgap_color)
-                return d->rgap_color;
+        return d->rgap_color ?: d->rgap_color;
+}
+
+static const char* table_data_underline(TableData *d) {
+        assert(d);
+
+        if (d->underline)
+                return /* cescape( */ansi_add_underline_grey()/* ) */;
 
         if (d->type == TABLE_HEADER)
-                return ansi_underline();
+                return ansi_add_underline();
+
+        return NULL;
+}
+
+static const char* table_data_rgap_underline(TableData *d) {
+        assert(d);
+
+        if (d->rgap_underline)
+                return ansi_add_underline_grey();
+
+        if (d->type == TABLE_HEADER)
+                return ansi_add_underline();
 
         return NULL;
 }
@@ -2418,13 +2505,13 @@ int table_print(Table *t, FILE *f) {
                         row = t->data + i * t->n_columns;
 
                 do {
-                        const char *gap_color = NULL;
+                        const char *gap_color = NULL, *gap_underline = NULL;
                         more_sublines = false;
 
                         for (size_t j = 0; j < display_columns; j++) {
                                 _cleanup_free_ char *buffer = NULL, *extracted = NULL;
                                 bool lines_truncated = false;
-                                const char *field, *color = NULL;
+                                const char *field, *color = NULL, *underline = NULL;
                                 TableData *d;
                                 size_t l;
 
@@ -2490,6 +2577,7 @@ int table_print(Table *t, FILE *f) {
                                                 /* Drop trailing white spaces of last column when no cosmetics is set. */
                                                 if (j == display_columns - 1 &&
                                                     (!colors_enabled() || !table_data_color(d)) &&
+                                                    (!underline_enabled() || !table_data_underline(d)) &&
                                                     (!urlify_enabled() || !d->url))
                                                         delete_trailing_chars(aligned, NULL);
 
@@ -2511,27 +2599,36 @@ int table_print(Table *t, FILE *f) {
 
                                 if (colors_enabled() && gap_color)
                                         fputs(gap_color, f);
+                                if (underline_enabled() && gap_underline)
+                                        fputs(gap_underline, f);
 
                                 if (j > 0)
                                         fputc(' ', f); /* column separator left of cell */
 
+                                /* Undo gap color/underline */
+                                if ((colors_enabled() && gap_color) ||
+                                    (underline_enabled() && gap_underline))
+                                        fputs(ANSI_NORMAL, f);
+
                                 if (colors_enabled()) {
                                         color = table_data_color(d);
-
-                                        /* Undo gap color */
-                                        if (gap_color)
-                                                fputs(ANSI_NORMAL, f);
-
                                         if (color)
                                                 fputs(color, f);
                                 }
 
+                                if (underline_enabled()) {
+                                        underline = table_data_underline(d);
+                                        if (underline)
+                                                fputs(underline, f);
+                                }
+
                                 fputs(field, f);
 
-                                if (colors_enabled() && color)
+                                if (color || underline)
                                         fputs(ANSI_NORMAL, f);
 
                                 gap_color = table_data_rgap_color(d);
+                                gap_underline = table_data_rgap_underline(d);
                         }
 
                         fputc('\n', f);
index 37bfbca693b72f812355981f29fbd6f777da97d6..0368447638c2aaad3b653367cdd604d579abbfee 100644 (file)
@@ -68,6 +68,9 @@ typedef enum TableDataType {
         TABLE_SET_COLOR,
         TABLE_SET_RGAP_COLOR,
         TABLE_SET_BOTH_COLORS,
+        TABLE_SET_UNDERLINE,
+        TABLE_SET_RGAP_UNDERLINE,
+        TABLE_SET_BOTH_UNDERLINES,
         TABLE_SET_URL,
         TABLE_SET_UPPERCASE,
 
@@ -111,6 +114,8 @@ int table_set_align_percent(Table *t, TableCell *cell, unsigned percent);
 int table_set_ellipsize_percent(Table *t, TableCell *cell, unsigned percent);
 int table_set_color(Table *t, TableCell *cell, const char *color);
 int table_set_rgap_color(Table *t, TableCell *cell, const char *color);
+int table_set_underline(Table *t, TableCell *cell, bool b);
+int table_set_rgap_underline(Table *t, TableCell *cell, bool b);
 int table_set_url(Table *t, TableCell *cell, const char *url);
 int table_set_uppercase(Table *t, TableCell *cell, bool b);