ff6046
From 1d3c6e3c0937ac56a51594a3b6908a801fa9ac5c Mon Sep 17 00:00:00 2001
ff6046
From: Lennart Poettering <lennart@poettering.net>
ff6046
Date: Mon, 3 Dec 2018 21:36:26 +0100
ff6046
Subject: [PATCH] format-table: add option to uppercase cells on display
ff6046
ff6046
This adds a per-cell option for uppercasing displayed strings.
ff6046
Implicitly turn this on for the header row. The fact that we format the
ff6046
table header in uppercase is a formatting thing after all, hence should
ff6046
be applied by the formatter, i.e. the table display code.
ff6046
ff6046
Moreover, this provides us with the benefit that we can more nicely
ff6046
reuse the specified table headers as JSON field names, like we already
ff6046
do: json field names are usually not uppercase.
ff6046
ff6046
(cherry picked from commit 359abf6dd05aa6bca3438e9c969ed904bd3d447d)
ff6046
ff6046
Related: #1689832
ff6046
---
ff6046
 src/basic/format-table.c | 62 ++++++++++++++++++++++++++++++++--------
ff6046
 src/basic/format-table.h |  1 +
ff6046
 2 files changed, 51 insertions(+), 12 deletions(-)
ff6046
ff6046
diff --git a/src/basic/format-table.c b/src/basic/format-table.c
ff6046
index cfb8aadbda..fe2201ee5f 100644
ff6046
--- a/src/basic/format-table.c
ff6046
+++ b/src/basic/format-table.c
ff6046
@@ -1,5 +1,6 @@
ff6046
 /* SPDX-License-Identifier: LGPL-2.1+ */
ff6046
 
ff6046
+#include <ctype.h>
ff6046
 #include <stdio_ext.h>
ff6046
 
ff6046
 #include "alloc-util.h"
ff6046
@@ -58,6 +59,8 @@ typedef struct TableData {
ff6046
         unsigned ellipsize_percent; /* 0 … 100, where to place the ellipsis when compression is needed */
ff6046
         unsigned align_percent;     /* 0 … 100, where to pad with spaces when expanding is needed. 0: left-aligned, 100: right-aligned */
ff6046
 
ff6046
+        bool uppercase;             /* Uppercase string on display */
ff6046
+
ff6046
         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 */
ff6046
         char *url;                  /* A URL to use for a clickable hyperlink */
ff6046
         char *formatted;            /* A cached textual representation of the cell data, before ellipsation/alignment */
ff6046
@@ -132,6 +135,7 @@ Table *table_new_raw(size_t n_columns) {
ff6046
 Table *table_new_internal(const char *first_header, ...) {
ff6046
         _cleanup_(table_unrefp) Table *t = NULL;
ff6046
         size_t n_columns = 1;
ff6046
+        const char *h;
ff6046
         va_list ap;
ff6046
         int r;
ff6046
 
ff6046
@@ -139,8 +143,6 @@ Table *table_new_internal(const char *first_header, ...) {
ff6046
 
ff6046
         va_start(ap, first_header);
ff6046
         for (;;) {
ff6046
-                const char *h;
ff6046
-
ff6046
                 h = va_arg(ap, const char*);
ff6046
                 if (!h)
ff6046
                         break;
ff6046
@@ -153,19 +155,18 @@ Table *table_new_internal(const char *first_header, ...) {
ff6046
         if (!t)
ff6046
                 return NULL;
ff6046
 
ff6046
-        r = table_add_cell(t, NULL, TABLE_STRING, first_header);
ff6046
-        if (r < 0)
ff6046
-                return NULL;
ff6046
-
ff6046
         va_start(ap, first_header);
ff6046
-        for (;;) {
ff6046
-                const char *h;
ff6046
+        for (h = first_header; h; h = va_arg(ap, const char*)) {
ff6046
+                TableCell *cell;
ff6046
 
ff6046
-                h = va_arg(ap, const char*);
ff6046
-                if (!h)
ff6046
-                        break;
ff6046
+                r = table_add_cell(t, &cell, TABLE_STRING, h);
ff6046
+                if (r < 0) {
ff6046
+                        va_end(ap);
ff6046
+                        return NULL;
ff6046
+                }
ff6046
 
ff6046
-                r = table_add_cell(t, NULL, TABLE_STRING, h);
ff6046
+                /* Make the table header uppercase */
ff6046
+                r = table_set_uppercase(t, cell, true);
ff6046
                 if (r < 0) {
ff6046
                         va_end(ap);
ff6046
                         return NULL;
ff6046
@@ -443,6 +444,7 @@ static int table_dedup_cell(Table *t, TableCell *cell) {
ff6046
 
ff6046
         nd->color = od->color;
ff6046
         nd->url = TAKE_PTR(curl);
ff6046
+        nd->uppercase = od->uppercase;
ff6046
 
ff6046
         table_data_unref(od);
ff6046
         t->data[i] = nd;
ff6046
@@ -590,6 +592,27 @@ int table_set_url(Table *t, TableCell *cell, const char *url) {
ff6046
         return free_and_replace(table_get_data(t, cell)->url, copy);
ff6046
 }
ff6046
 
ff6046
+int table_set_uppercase(Table *t, TableCell *cell, bool b) {
ff6046
+        TableData *d;
ff6046
+        int r;
ff6046
+
ff6046
+        assert(t);
ff6046
+        assert(cell);
ff6046
+
ff6046
+        r = table_dedup_cell(t, cell);
ff6046
+        if (r < 0)
ff6046
+                return r;
ff6046
+
ff6046
+        assert_se(d = table_get_data(t, cell));
ff6046
+
ff6046
+        if (d->uppercase == b)
ff6046
+                return 0;
ff6046
+
ff6046
+        d->formatted = mfree(d->formatted);
ff6046
+        d->uppercase = b;
ff6046
+        return 1;
ff6046
+}
ff6046
+
ff6046
 int table_update(Table *t, TableCell *cell, TableDataType type, const void *data) {
ff6046
         _cleanup_free_ char *curl = NULL;
ff6046
         TableData *nd, *od;
ff6046
@@ -623,6 +646,7 @@ int table_update(Table *t, TableCell *cell, TableDataType type, const void *data
ff6046
 
ff6046
         nd->color = od->color;
ff6046
         nd->url = TAKE_PTR(curl);
ff6046
+        nd->uppercase = od->uppercase;
ff6046
 
ff6046
         table_data_unref(od);
ff6046
         t->data[i] = nd;
ff6046
@@ -902,6 +926,20 @@ static const char *table_data_format(TableData *d) {
ff6046
                 return "";
ff6046
 
ff6046
         case TABLE_STRING:
ff6046
+                if (d->uppercase) {
ff6046
+                        char *p, *q;
ff6046
+
ff6046
+                        d->formatted = new(char, strlen(d->string) + 1);
ff6046
+                        if (!d->formatted)
ff6046
+                                return NULL;
ff6046
+
ff6046
+                        for (p = d->string, q = d->formatted; *p; p++, q++)
ff6046
+                                *q = (char) toupper((unsigned char) *p);
ff6046
+                        *q = 0;
ff6046
+
ff6046
+                        return d->formatted;
ff6046
+                }
ff6046
+
ff6046
                 return d->string;
ff6046
 
ff6046
         case TABLE_BOOLEAN:
ff6046
diff --git a/src/basic/format-table.h b/src/basic/format-table.h
ff6046
index a2bb2e0846..5a076b5383 100644
ff6046
--- a/src/basic/format-table.h
ff6046
+++ b/src/basic/format-table.h
ff6046
@@ -45,6 +45,7 @@ int table_set_align_percent(Table *t, TableCell *cell, unsigned percent);
ff6046
 int table_set_ellipsize_percent(Table *t, TableCell *cell, unsigned percent);
ff6046
 int table_set_color(Table *t, TableCell *cell, const char *color);
ff6046
 int table_set_url(Table *t, TableCell *cell, const char *color);
ff6046
+int table_set_uppercase(Table *t, TableCell *cell, bool b);
ff6046
 
ff6046
 int table_update(Table *t, TableCell *cell, TableDataType type, const void *data);
ff6046