--- /dev/null
+/*
+ * Copyright (C) 2010-2014 Karel Zak <kzak@redhat.com>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <getopt.h>
+
+#include "c.h"
+#include "nls.h"
+#include "strutils.h"
+#include "xalloc.h"
+
+#include "libsmartcols.h"
+
+
+enum { COL_NAME, COL_FOO, COL_BAR };
+
+/* add columns to the @tb */
+static void setup_columns(struct libscols_table *tb)
+{
+ if (!scols_table_new_column(tb, "NAME", 0, 0))
+ goto fail;
+ if (!scols_table_new_column(tb, "BAR", 0, 0))
+ goto fail;
+ if (!scols_table_new_column(tb, "FOO", 0, 0))
+ goto fail;
+ return;
+fail:
+ scols_unref_table(tb);
+ err(EXIT_FAILURE, "failed to create output columns");
+}
+
+static struct libscols_line *add_line(struct libscols_table *tb, const char *name, const char *data)
+{
+ struct libscols_line *ln = scols_table_new_line(tb, NULL);
+ if (!ln)
+ err(EXIT_FAILURE, "failed to create output line");
+
+ if (scols_line_set_data(ln, COL_NAME, name))
+ goto fail;
+ if (scols_line_set_data(ln, COL_FOO, data))
+ goto fail;
+ if (scols_line_set_data(ln, COL_BAR, data))
+ goto fail;
+ return ln;
+fail:
+ scols_unref_table(tb);
+ err(EXIT_FAILURE, "failed to create output line");
+}
+
+int main(int argc, char *argv[])
+{
+ struct libscols_table *tb;
+ struct libscols_column *cl;
+ struct libscols_line *ln;
+ struct libscols_cell *ce;
+ int c;
+
+ static const struct option longopts[] = {
+ { "maxout", 0, NULL, 'm' },
+ { "width", 1, NULL, 'w' },
+ { "help", 1, NULL, 'h' },
+
+ { NULL, 0, NULL, 0 },
+ };
+
+ setlocale(LC_ALL, ""); /* just to have enable UTF8 chars */
+
+ scols_init_debug(0);
+
+ tb = scols_new_table();
+ if (!tb)
+ err(EXIT_FAILURE, "failed to create output table");
+
+ while((c = getopt_long(argc, argv, "hmw:", longopts, NULL)) != -1) {
+ switch(c) {
+ case 'h':
+ printf("%s [--help | --maxout | --width <num>]\n", program_invocation_short_name);
+ break;
+ case 'm':
+ scols_table_enable_maxout(tb, TRUE);
+ break;
+ case 'w':
+ scols_table_set_termforce(tb, SCOLS_TERMFORCE_ALWAYS);
+ scols_table_set_termwidth(tb, strtou32_or_err(optarg, "failed to parse terminal width"));
+ break;
+ }
+ }
+
+ scols_table_enable_colors(tb, isatty(STDOUT_FILENO));
+ setup_columns(tb);
+ add_line(tb, "AAA", "bla bla bla");
+ add_line(tb, "BB", "b");
+ add_line(tb, "CCCC", "fooo");
+ add_line(tb, "D", "baaar");
+ add_line(tb, "EE", "eee");
+
+ cl = scols_table_get_column(tb, 1);
+ scols_column_set_color(cl, "red"); /* red column */
+
+ cl = scols_table_get_column(tb, 2);
+ scols_column_set_color(cl, "reverse"); /* reverse column */
+
+ ln = scols_table_get_line(tb, 0);
+ scols_line_set_color(ln, "\033[37;41m"); /* line with red bg */
+ ce = scols_line_get_cell(ln, 0);
+ scols_cell_set_color(ce, "\033[37;45m"); /* cell with purple bg */
+
+ ln = scols_table_get_line(tb, 3);
+ scols_line_set_color(ln, "\033[37;41m"); /* line with red bg */
+ ce = scols_line_get_cell(ln, 2);
+ scols_cell_set_color(ce, "\033[37;44m"); /* cell with blue bg */
+
+ scols_print_table(tb);
+ scols_unref_table(tb);
+ return EXIT_SUCCESS;
+}
-/*
- * 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>
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) {
}
/* 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).
*
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;
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);
}
/*
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;
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);
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;
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));
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 */
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) {
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) {
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;
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;
goto done;
}
- if (tb->colors_wanted && tb->title.color)
- color = 1;
- if (color)
- fputs(tb->title.color, tb->out);
+ fputs_color(tb, tb->title.color);
fputs(title, tb->out);
- if (color)
- fputs(UL_COLOR_RESET, tb->out);
+ fputs_color_reset(tb);
fputc('\n', tb->out);
rc = 0;