From 36e07cebf1323098b2854b3571563abda01f0323 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Tue, 13 Jun 2017 11:11:17 +0200 Subject: libsmartcols: add header-repeat feature Signed-off-by: Karel Zak --- libsmartcols/src/libsmartcols.h.in | 2 ++ libsmartcols/src/libsmartcols.sym | 2 ++ libsmartcols/src/smartcolsP.h | 4 ++++ libsmartcols/src/table.c | 35 +++++++++++++++++++++++++++++++++++ libsmartcols/src/table_print.c | 27 ++++++++++++++++++++++++--- 5 files changed, 67 insertions(+), 3 deletions(-) (limited to 'libsmartcols') diff --git a/libsmartcols/src/libsmartcols.h.in b/libsmartcols/src/libsmartcols.h.in index cfe2439ef..bce2cc725 100644 --- a/libsmartcols/src/libsmartcols.h.in +++ b/libsmartcols/src/libsmartcols.h.in @@ -219,6 +219,7 @@ extern int scols_table_is_raw(const struct libscols_table *tb); extern int scols_table_is_ascii(const struct libscols_table *tb); extern int scols_table_is_json(const struct libscols_table *tb); extern int scols_table_is_noheadings(const struct libscols_table *tb); +extern int scols_table_is_header_repeat(const struct libscols_table *tb); extern int scols_table_is_empty(const struct libscols_table *tb); extern int scols_table_is_export(const struct libscols_table *tb); extern int scols_table_is_maxout(const struct libscols_table *tb); @@ -231,6 +232,7 @@ extern int scols_table_enable_raw(struct libscols_table *tb, int enable); extern int scols_table_enable_ascii(struct libscols_table *tb, int enable); extern int scols_table_enable_json(struct libscols_table *tb, int enable); extern int scols_table_enable_noheadings(struct libscols_table *tb, int enable); +extern int scols_table_enable_header_repeat(struct libscols_table *tb, int enable); extern int scols_table_enable_export(struct libscols_table *tb, int enable); extern int scols_table_enable_maxout(struct libscols_table *tb, int enable); extern int scols_table_enable_nowrap(struct libscols_table *tb, int enable); diff --git a/libsmartcols/src/libsmartcols.sym b/libsmartcols/src/libsmartcols.sym index 7b9a3d97b..fec33cbfd 100644 --- a/libsmartcols/src/libsmartcols.sym +++ b/libsmartcols/src/libsmartcols.sym @@ -171,4 +171,6 @@ global: SMARTCOLS_2.31 { scols_table_set_termheight; scols_table_get_termheight; + scols_table_is_header_repeat; + scols_table_enable_header_repeat; } SMARTCOLS_2.30; diff --git a/libsmartcols/src/smartcolsP.h b/libsmartcols/src/smartcolsP.h index 1a749b247..65009779a 100644 --- a/libsmartcols/src/smartcolsP.h +++ b/libsmartcols/src/smartcolsP.h @@ -164,12 +164,16 @@ struct libscols_table { int indent_last_sep;/* last printed has been line separator */ int format; /* SCOLS_FMT_* */ + size_t termlines_used; /* printed line counter */ + size_t header_next; /* where repeat header */ + /* flags */ unsigned int ascii :1, /* don't use unicode */ colors_wanted :1, /* enable colors */ is_term :1, /* isatty() */ padding_debug :1, /* output visible padding chars */ maxout :1, /* maximize output */ + header_repeat :1, /* print header after libscols_table->termheight */ header_printed :1, /* header already printed */ priv_symbols :1, /* default private symbols */ no_headings :1, /* don't print header */ diff --git a/libsmartcols/src/table.c b/libsmartcols/src/table.c index dd412b220..3306ff57c 100644 --- a/libsmartcols/src/table.c +++ b/libsmartcols/src/table.c @@ -1032,6 +1032,28 @@ int scols_table_enable_noheadings(struct libscols_table *tb, int enable) return 0; } +/** + * scols_table_enable_header_repeat: + * @tb: table + * @enable: 1 or 0 + * + * Enable/disable header line repeat. The header line is printed only once by + * default. Note that the flag will be silently ignored and disabled if the + * output is not on terminal or output format is JSON, raw, etc. + * + * Returns: 0 on success, negative number in case of an error. + * + * Since: 2.31 + */ +int scols_table_enable_header_repeat(struct libscols_table *tb, int enable) +{ + if (!tb) + return -EINVAL; + DBG(TAB, ul_debugobj(tb, "header-repeat: %s", enable ? "ENABLE" : "DISABLE")); + tb->header_repeat = enable ? 1 : 0; + return 0; +} + /** * scols_table_enable_maxout: * @tb: table @@ -1128,6 +1150,19 @@ int scols_table_is_noheadings(const struct libscols_table *tb) return tb->no_headings; } +/** + * scols_table_is_header_repeat + * @tb: table + * + * Returns: 1 if header repeat is enabled. + * + * Since: 2.31 + */ +int scols_table_is_header_repeat(const struct libscols_table *tb) +{ + return tb->header_repeat; +} + /** * scols_table_is_export: * @tb: table diff --git a/libsmartcols/src/table_print.c b/libsmartcols/src/table_print.c index 8cd737c8b..8e37c80cb 100644 --- a/libsmartcols/src/table_print.c +++ b/libsmartcols/src/table_print.c @@ -43,6 +43,9 @@ #define cellpadding_symbol(tb) ((tb)->padding_debug ? "." : \ ((tb)->symbols->cell_padding ? (tb)->symbols->cell_padding: " ")) +#define want_repeat_header(tb) (!(tb)->header_repeat || (tb)->header_next <= (tb)->termlines_used) + + /* This is private struct to work with output data */ struct libscols_buffer { char *begin; /* begin of the buffer */ @@ -307,6 +310,7 @@ static void print_newline_padding(struct libscols_table *tb, assert(cl); fputs(linesep(tb), tb->out); /* line break */ + tb->termlines_used++; /* fill cells after line break */ for (i = 0; i <= (size_t) cl->seqnum; i++) @@ -650,6 +654,7 @@ static void fput_children_open(struct libscols_table *tb) fputs(linesep(tb), tb->out); tb->indent_last_sep = 1; tb->indent++; + tb->termlines_used++; } static void fput_children_close(struct libscols_table *tb) @@ -684,8 +689,10 @@ static void fput_line_close(struct libscols_table *tb, int last, int last_in_tab if (!tb->no_linesep) fputs(linesep(tb), tb->out); - } else if (tb->no_linesep == 0 && last_in_table == 0) + } else if (tb->no_linesep == 0 && last_in_table == 0) { fputs(linesep(tb), tb->out); + tb->termlines_used++; + } tb->indent_last_sep = 1; } @@ -724,6 +731,7 @@ static int print_line(struct libscols_table *tb, while (rc == 0 && pending) { pending = 0; fputs(linesep(tb), tb->out); + tb->termlines_used++; scols_reset_iter(&itr, SCOLS_ITER_FORWARD); while (rc == 0 && scols_table_next_column(tb, &itr, &cl) == 0) { if (scols_column_is_hidden(cl)) @@ -833,7 +841,7 @@ static int print_header(struct libscols_table *tb, struct libscols_buffer *buf) assert(tb); - if (tb->header_printed == 1 || + if ((tb->header_printed == 1 && tb->header_repeat == 0) || scols_table_is_noheadings(tb) || scols_table_is_export(tb) || scols_table_is_json(tb) || @@ -852,13 +860,20 @@ static int print_header(struct libscols_table *tb, struct libscols_buffer *buf) rc = print_data(tb, cl, NULL, &cl->header, buf); } - if (rc == 0) + if (rc == 0) { fputs(linesep(tb), tb->out); + tb->termlines_used++; + } tb->header_printed = 1; + tb->header_next = tb->termlines_used + tb->termheight; + if (tb->header_repeat) + DBG(TAB, ul_debugobj(tb, "\tnext header: %zu [current=%zu]", + tb->header_next, tb->termlines_used)); return rc; } + static int print_range( struct libscols_table *tb, struct libscols_buffer *buf, struct libscols_iter *itr, @@ -879,6 +894,9 @@ static int print_range( struct libscols_table *tb, if (end && ln == end) break; + + if (!last && want_repeat_header(tb)) + print_header(tb, buf); } return rc; @@ -1398,6 +1416,9 @@ static int initialize_printing(struct libscols_table *tb, struct libscols_buffer } else bufsz = BUFSIZ; + if (!tb->is_term || tb->format != SCOLS_FMT_HUMAN || scols_table_is_tree(tb)) + tb->header_repeat = 0; + /* * Estimate extra space necessary for tree, JSON or another output * decoration. -- cgit v1.2.3-55-g7522