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