summaryrefslogtreecommitdiffstats
path: root/src/utils/libsmartcols/src/print.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/utils/libsmartcols/src/print.c')
-rw-r--r--src/utils/libsmartcols/src/print.c261
1 files changed, 179 insertions, 82 deletions
diff --git a/src/utils/libsmartcols/src/print.c b/src/utils/libsmartcols/src/print.c
index 9d78c90..9f60148 100644
--- a/src/utils/libsmartcols/src/print.c
+++ b/src/utils/libsmartcols/src/print.c
@@ -1,5 +1,4 @@
-/*
- * table.c - functions handling the data at the table level
+ /* print.c - functions to print table
*
* Copyright (C) 2010-2014 Karel Zak <kzak@redhat.com>
* Copyright (C) 2016 Igor Gnatenko <i.gnatenko.brain@gmail.com>
@@ -217,16 +216,94 @@ static int has_pending_data(struct libscols_table *tb)
return 0;
}
+static void fputs_color_reset(struct libscols_table *tb)
+{
+ if (tb->cur_color) {
+ fputs(UL_COLOR_RESET, tb->out);
+ tb->cur_color = NULL;
+ }
+}
+
+static void fputs_color(struct libscols_table *tb, const char *color)
+{
+ if (tb->cur_color)
+ fputs_color_reset(tb);
+
+ tb->cur_color = color;
+ if (color)
+ fputs(color, tb->out);
+}
+
+static const char *get_cell_color(struct libscols_table *tb,
+ struct libscols_column *cl,
+ struct libscols_line *ln,
+ struct libscols_cell *ce)
+{
+ const char *color = NULL;
+
+ if (!tb || !tb->colors_wanted || tb->format != SCOLS_FMT_HUMAN)
+ return NULL;
+ if (ce)
+ color = ce->color;
+ if (!color && (!ln || !ln->color) && cl)
+ color = cl->color;
+ return color;
+}
+
+/* switch from line color to cell/column color */
+static void fputs_color_cell_open(struct libscols_table *tb,
+ struct libscols_column *cl,
+ struct libscols_line *ln,
+ struct libscols_cell *ce)
+{
+ const char *color = get_cell_color(tb, cl, ln, ce);
+
+ if (color)
+ fputs_color(tb, color);
+}
+
+/* switch from cell/column color to line color or reset */
+static void fputs_color_cell_close(struct libscols_table *tb,
+ struct libscols_column *cl,
+ struct libscols_line *ln,
+ struct libscols_cell *ce)
+{
+ const char *color = get_cell_color(tb, cl, ln, ce);
+
+ if (color)
+ fputs_color(tb, ln ? ln->color : NULL);
+}
+
+/* switch to line color */
+static void fputs_color_line_open(struct libscols_table *tb,
+ struct libscols_line *ln)
+{
+ if (!tb || !tb->colors_wanted || tb->format != SCOLS_FMT_HUMAN)
+ return;
+ fputs_color(tb, ln ? ln->color : NULL);
+}
+
+/* switch off all colors */
+static void fputs_color_line_close(struct libscols_table *tb)
+{
+ if (!tb || !tb->colors_wanted || tb->format != SCOLS_FMT_HUMAN)
+ return;
+ fputs_color_reset(tb);
+}
+
/* print padding or ASCII-art instead of data of @cl */
static void print_empty_cell(struct libscols_table *tb,
struct libscols_column *cl,
struct libscols_line *ln, /* optional */
+ struct libscols_cell *ce,
size_t bufsz)
{
size_t len_pad = 0; /* in screen cells as opposed to bytes */
DBG(COL, ul_debugobj(cl, " printing empty cell"));
+ fputs_color_cell_open(tb, cl, ln, ce);
+
/* generate tree ASCII-art rather than padding */
if (ln && scols_column_is_tree(cl)) {
if (!ln->parent) {
@@ -256,39 +333,28 @@ static void print_empty_cell(struct libscols_table *tb,
}
/* minout -- don't fill */
- if (scols_table_is_minout(tb) && is_next_columns_empty(tb, cl, ln))
+ if (scols_table_is_minout(tb) && is_next_columns_empty(tb, cl, ln)) {
+ fputs_color_cell_close(tb, cl, ln, ce);
return;
+ }
/* default -- fill except last column */
- if (!scols_table_is_maxout(tb) && is_last_column(cl))
+ if (!scols_table_is_maxout(tb) && is_last_column(cl)) {
+ fputs_color_cell_close(tb, cl, ln, ce);
return;
+ }
/* fill rest of cell with space */
for(; len_pad < cl->width; ++len_pad)
fputs(cellpadding_symbol(tb), tb->out);
+ fputs_color_cell_close(tb, cl, ln, ce);
+
if (!is_last_column(cl))
fputs(colsep(tb), tb->out);
}
-static const char *get_cell_color(struct libscols_table *tb,
- struct libscols_column *cl,
- struct libscols_line *ln, /* optional */
- struct libscols_cell *ce) /* optional */
-{
- const char *color = NULL;
-
- if (tb && tb->colors_wanted) {
- if (ce)
- color = ce->color;
- if (ln && !color)
- color = ln->color;
- if (!color)
- color = cl->color;
- }
- return color;
-}
/* Fill the start of a line with padding (or with tree ascii-art).
*
@@ -304,6 +370,7 @@ static const char *get_cell_color(struct libscols_table *tb,
static void print_newline_padding(struct libscols_table *tb,
struct libscols_column *cl,
struct libscols_line *ln, /* optional */
+ struct libscols_cell *ce,
size_t bufsz)
{
size_t i;
@@ -316,9 +383,13 @@ static void print_newline_padding(struct libscols_table *tb,
fputs(linesep(tb), tb->out); /* line break */
tb->termlines_used++;
+ fputs_color_line_open(tb, ln);
+
/* fill cells after line break */
for (i = 0; i <= (size_t) cl->seqnum; i++)
- print_empty_cell(tb, scols_table_get_column(tb, i), ln, bufsz);
+ print_empty_cell(tb, scols_table_get_column(tb, i), ln, ce, bufsz);
+
+ fputs_color_line_close(tb);
}
/*
@@ -374,7 +445,6 @@ static int print_pending_data(
struct libscols_line *ln, /* optional */
struct libscols_cell *ce)
{
- const char *color = get_cell_color(tb, cl, ln, ce);
size_t width = cl->width, bytes;
size_t len = width, i;
char *data;
@@ -407,25 +477,29 @@ static int print_pending_data(
if (bytes)
step_pending_data(cl, bytes);
- if (color)
- fputs(color, tb->out);
+ fputs_color_cell_open(tb, cl, ln, ce);
+
fputs(data, tb->out);
- if (color)
- fputs(UL_COLOR_RESET, tb->out);
free(data);
/* minout -- don't fill */
- if (scols_table_is_minout(tb) && is_next_columns_empty(tb, cl, ln))
+ if (scols_table_is_minout(tb) && is_next_columns_empty(tb, cl, ln)) {
+ fputs_color_cell_close(tb, cl, ln, ce);
return 0;
+ }
/* default -- fill except last column */
- if (!scols_table_is_maxout(tb) && is_last_column(cl))
+ if (!scols_table_is_maxout(tb) && is_last_column(cl)) {
+ fputs_color_cell_close(tb, cl, ln, ce);
return 0;
+ }
/* fill rest of cell with space */
for(i = len; i < width; i++)
fputs(cellpadding_symbol(tb), tb->out);
+ fputs_color_cell_close(tb, cl, ln, ce);
+
if (!is_last_column(cl))
fputs(colsep(tb), tb->out);
@@ -435,6 +509,49 @@ err:
return -errno;
}
+static void print_json_data(struct libscols_table *tb,
+ struct libscols_column *cl,
+ const char *name,
+ char *data)
+{
+ switch (cl->json_type) {
+ case SCOLS_JSON_STRING:
+ /* name: "aaa" */
+ ul_jsonwrt_value_s(&tb->json, name, data);
+ break;
+ case SCOLS_JSON_NUMBER:
+ /* name: 123 */
+ ul_jsonwrt_value_raw(&tb->json, name, data);
+ break;
+ case SCOLS_JSON_BOOLEAN:
+ /* name: true|false */
+ ul_jsonwrt_value_boolean(&tb->json, name,
+ !*data ? 0 :
+ *data == '0' ? 0 :
+ *data == 'N' || *data == 'n' ? 0 : 1);
+ break;
+ case SCOLS_JSON_ARRAY_STRING:
+ case SCOLS_JSON_ARRAY_NUMBER:
+ /* name: [ "aaa", "bbb", "ccc" ] */
+ ul_jsonwrt_array_open(&tb->json, name);
+
+ if (!scols_column_is_customwrap(cl))
+ ul_jsonwrt_value_s(&tb->json, NULL, data);
+ else do {
+ char *next = cl->wrap_nextchunk(cl, data, cl->wrapfunc_data);
+
+ if (cl->json_type == SCOLS_JSON_ARRAY_STRING)
+ ul_jsonwrt_value_s(&tb->json, NULL, data);
+ else
+ ul_jsonwrt_value_raw(&tb->json, NULL, data);
+ data = next;
+ } while (data);
+
+ ul_jsonwrt_array_close(&tb->json);
+ break;
+ }
+}
+
static int print_data(struct libscols_table *tb,
struct libscols_column *cl,
struct libscols_line *ln, /* optional */
@@ -442,7 +559,6 @@ static int print_data(struct libscols_table *tb,
struct libscols_buffer *buf)
{
size_t len = 0, i, width, bytes;
- const char *color = NULL;
char *data, *nextchunk;
const char *name = NULL;
int is_last;
@@ -472,36 +588,23 @@ static int print_data(struct libscols_table *tb,
return 0;
case SCOLS_FMT_EXPORT:
- fprintf(tb->out, "%s=", name);
+ fputs_shell_ident(name, tb->out);
+ if (endswith(name, "%"))
+ fputs("PCT", tb->out);
+ fputc('=', tb->out);
fputs_quoted(data, tb->out);
if (!is_last)
fputs(colsep(tb), tb->out);
return 0;
case SCOLS_FMT_JSON:
- switch (cl->json_type) {
- case SCOLS_JSON_STRING:
- ul_jsonwrt_value_s(&tb->json, name, data, is_last);
- break;
- case SCOLS_JSON_NUMBER:
- ul_jsonwrt_value_raw(&tb->json, name, data, is_last);
- break;
- case SCOLS_JSON_BOOLEAN:
- ul_jsonwrt_value_boolean(&tb->json, name,
- !*data ? 0 :
- *data == '0' ? 0 :
- *data == 'N' || *data == 'n' ? 0 : 1,
- is_last);
- break;
- }
+ print_json_data(tb, cl, name, data);
return 0;
case SCOLS_FMT_HUMAN:
break; /* continue below */
}
- color = get_cell_color(tb, cl, ln, ce);
-
/* Encode. Note that 'len' and 'width' are number of cells, not bytes.
*/
data = buffer_get_safe_data(tb, buf, &len, scols_column_get_safechars(cl));
@@ -549,49 +652,39 @@ static int print_data(struct libscols_table *tb,
data = NULL;
}
+ fputs_color_cell_open(tb, cl, ln, ce);
+
if (data && *data) {
if (scols_column_is_right(cl)) {
- if (color)
- fputs(color, tb->out);
for (i = len; i < width; i++)
fputs(cellpadding_symbol(tb), tb->out);
- fputs(data, tb->out);
- if (color)
- fputs(UL_COLOR_RESET, tb->out);
len = width;
+ }
+ fputs(data, tb->out);
- } else if (color) {
- char *p = data;
- size_t art = buffer_get_safe_art_size(buf);
-
- /* we don't want to colorize tree ascii art */
- if (scols_column_is_tree(cl) && art && art < bytes) {
- fwrite(p, 1, art, tb->out);
- p += art;
- }
-
- fputs(color, tb->out);
- fputs(p, tb->out);
- fputs(UL_COLOR_RESET, tb->out);
- } else
- fputs(data, tb->out);
}
/* minout -- don't fill */
- if (scols_table_is_minout(tb) && is_next_columns_empty(tb, cl, ln))
+ if (scols_table_is_minout(tb) && is_next_columns_empty(tb, cl, ln)) {
+ fputs_color_cell_close(tb, cl, ln, ce);
return 0;
+ }
/* default -- fill except last column */
- if (!scols_table_is_maxout(tb) && is_last)
+ if (!scols_table_is_maxout(tb) && is_last) {
+ fputs_color_cell_close(tb, cl, ln, ce);
return 0;
+ }
/* fill rest of cell with space */
for(i = len; i < width; i++)
fputs(cellpadding_symbol(tb), tb->out);
+ fputs_color_cell_close(tb, cl, ln, ce);
+
if (len > width && !scols_column_is_trunc(cl)) {
DBG(COL, ul_debugobj(cl, "*** data len=%zu > column width=%zu", len, width));
- print_newline_padding(tb, cl, ln, buffer_get_size(buf)); /* next column starts on next line */
+ print_newline_padding(tb, cl, ln, ce, buffer_get_size(buf)); /* next column starts on next line */
} else if (!is_last)
fputs(colsep(tb), tb->out); /* columns separator */
@@ -664,6 +757,8 @@ static int print_line(struct libscols_table *tb,
DBG(LINE, ul_debugobj(ln, "printing line"));
+ fputs_color_line_open(tb, ln);
+
/* regular line */
scols_reset_iter(&itr, SCOLS_ITER_FORWARD);
while (rc == 0 && scols_table_next_column(tb, &itr, &cl) == 0) {
@@ -677,12 +772,14 @@ static int print_line(struct libscols_table *tb,
if (rc == 0 && cl->pending_data)
pending = 1;
}
+ fputs_color_line_close(tb);
/* extra lines of the multi-line cells */
while (rc == 0 && pending) {
DBG(LINE, ul_debugobj(ln, "printing pending data"));
pending = 0;
fputs(linesep(tb), tb->out);
+ fputs_color_line_open(tb, ln);
tb->termlines_used++;
scols_reset_iter(&itr, SCOLS_ITER_FORWARD);
while (rc == 0 && scols_table_next_column(tb, &itr, &cl) == 0) {
@@ -693,8 +790,9 @@ static int print_line(struct libscols_table *tb,
if (rc == 0 && cl->pending_data)
pending = 1;
} else
- print_empty_cell(tb, cl, ln, buffer_get_size(buf));
+ print_empty_cell(tb, cl, ln, NULL, buffer_get_size(buf));
}
+ fputs_color_line_close(tb);
}
return 0;
@@ -702,7 +800,7 @@ static int print_line(struct libscols_table *tb,
int __scols_print_title(struct libscols_table *tb)
{
- int rc, color = 0;
+ int rc;
mbs_align_t align;
size_t width, len = 0, bufsz, titlesz;
char *title = NULL, *buf = NULL;
@@ -783,15 +881,14 @@ int __scols_print_title(struct libscols_table *tb)
goto done;
}
- if (tb->colors_wanted && tb->title.color)
- color = 1;
- if (color)
- fputs(tb->title.color, tb->out);
+
+ if (tb->colors_wanted)
+ fputs_color(tb, tb->title.color);
fputs(title, tb->out);
- if (color)
- fputs(UL_COLOR_RESET, tb->out);
+ if (tb->colors_wanted)
+ fputs_color_reset(tb);
fputc('\n', tb->out);
rc = 0;
@@ -877,7 +974,7 @@ int __scols_print_range(struct libscols_table *tb,
rc = print_line(tb, ln, buf);
if (scols_table_is_json(tb))
- ul_jsonwrt_object_close(&tb->json, last);
+ ul_jsonwrt_object_close(&tb->json);
else if (last == 0 && tb->no_linesep == 0) {
fputs(linesep(tb), tb->out);
tb->termlines_used++;
@@ -937,9 +1034,9 @@ static int print_tree_line(struct libscols_table *tb,
last = (is_child(ln) && is_last_child(ln)) ||
(is_tree_root(ln) && is_last_tree_root(tb, ln));
- ul_jsonwrt_object_close(&tb->json, last);
+ ul_jsonwrt_object_close(&tb->json);
if (last && is_child(ln))
- ul_jsonwrt_array_close(&tb->json, last);
+ ul_jsonwrt_array_close(&tb->json);
ln = ln->parent;
} while(ln && last);