diff options
Diffstat (limited to 'libsmartcols/src/print.c')
-rw-r--r-- | libsmartcols/src/print.c | 195 |
1 files changed, 169 insertions, 26 deletions
diff --git a/libsmartcols/src/print.c b/libsmartcols/src/print.c index dc6637cea..4a45b41fb 100644 --- a/libsmartcols/src/print.c +++ b/libsmartcols/src/print.c @@ -33,9 +33,17 @@ * fallback to be more robust and backwardly compatible. */ #define titlepadding_symbol(tb) ((tb)->symbols->title_padding ? (tb)->symbols->title_padding : " ") -#define branch_symbol(tb) ((tb)->symbols->branch ? (tb)->symbols->branch : "|-") -#define vertical_symbol(tb) ((tb)->symbols->vert ? (tb)->symbols->vert : "| ") -#define right_symbol(tb) ((tb)->symbols->right ? (tb)->symbols->right : "`-") +#define branch_symbol(tb) ((tb)->symbols->tree_branch ? (tb)->symbols->tree_branch : "|-") +#define vertical_symbol(tb) ((tb)->symbols->tree_vert ? (tb)->symbols->tree_vert : "| ") +#define right_symbol(tb) ((tb)->symbols->tree_right ? (tb)->symbols->tree_right : "`-") + +#define grp_vertical_symbol(tb) ((tb)->symbols->group_vert ? (tb)->symbols->group_vert : "|") +#define grp_horizontal_symbol(tb) ((tb)->symbols->group_horz ? (tb)->symbols->group_horz : "-") +#define grp_m_first_symbol(tb) ((tb)->symbols->group_first_member ? (tb)->symbols->group_first_member : ",->") +#define grp_m_last_symbol(tb) ((tb)->symbols->group_last_member ? (tb)->symbols->group_last_member : "\\->") +#define grp_m_middle_symbol(tb) ((tb)->symbols->group_middle_member ? (tb)->symbols->group_middle_member : "|->") +#define grp_c_middle_symbol(tb) ((tb)->symbols->group_middle_child ? (tb)->symbols->group_middle_child : "|-") +#define grp_c_last_symbol(tb) ((tb)->symbols->group_last_child ? (tb)->symbols->group_last_child : "`-") #define cellpadding_symbol(tb) ((tb)->padding_debug ? "." : \ ((tb)->symbols->cell_padding ? (tb)->symbols->cell_padding: " ")) @@ -44,7 +52,7 @@ /* returns pointer to the end of used data */ -static int line_ascii_art_to_buffer(struct libscols_table *tb, +static int tree_ascii_art_to_buffer(struct libscols_table *tb, struct libscols_line *ln, struct libscols_buffer *buf) { @@ -57,7 +65,7 @@ static int line_ascii_art_to_buffer(struct libscols_table *tb, if (!ln->parent) return 0; - rc = line_ascii_art_to_buffer(tb, ln->parent, buf); + rc = tree_ascii_art_to_buffer(tb, ln->parent, buf); if (rc) return rc; @@ -69,6 +77,95 @@ static int line_ascii_art_to_buffer(struct libscols_table *tb, return buffer_append_data(buf, art); } +static int grpset_is_empty( struct libscols_table *tb, + size_t idx, + size_t *rest) +{ + size_t i; + + for (i = idx; i < tb->grpset_size; i++) { + if (tb->grpset[i] == NULL) { + if (rest) + (*rest)++; + } else + return 0; + } + return 1; +} + +static int groups_ascii_art_to_buffer( struct libscols_table *tb, + struct libscols_line *ln, + struct libscols_buffer *buf) +{ + int rc, filled = 0; + size_t i, rest = 0; + const char *filler = cellpadding_symbol(tb); + + if (!has_groups(tb) || !tb->grpset) + return 0; + + DBG(LINE, ul_debugobj(ln, "printing groups chart")); + + rc = scols_groups_update_grpset(tb, ln); + if (rc) + return rc; + + for (i = 0; i < tb->grpset_size; i+=3) { + struct libscols_group *gr = tb->grpset[i]; + + if (!gr) { + buffer_append_ntimes(buf, 3, cellpadding_symbol(tb)); + continue; + } + + switch (gr->state) { + case SCOLS_GSTATE_FIRST_MEMBER: + buffer_append_data(buf, grp_m_first_symbol(tb)); + break; + case SCOLS_GSTATE_MIDDLE_MEMBER: + buffer_append_data(buf, grp_m_middle_symbol(tb)); + break; + case SCOLS_GSTATE_LAST_MEMBER: + buffer_append_data(buf, grp_m_last_symbol(tb)); + break; + case SCOLS_GSTATE_CONT_MEMBERS: + buffer_append_data(buf, grp_vertical_symbol(tb)); + buffer_append_ntimes(buf, 2, filler); + break; + case SCOLS_GSTATE_MIDDLE_CHILD: + buffer_append_data(buf, filler); + buffer_append_data(buf, grp_c_middle_symbol(tb)); + if (grpset_is_empty(tb, i + 3, &rest)) { + buffer_append_ntimes(buf, rest+1, grp_horizontal_symbol(tb)); + filled = 1; + } + filler = grp_horizontal_symbol(tb); + break; + case SCOLS_GSTATE_LAST_CHILD: + buffer_append_data(buf, cellpadding_symbol(tb)); + buffer_append_data(buf, grp_c_last_symbol(tb)); + if (grpset_is_empty(tb, i + 3, &rest)) { + buffer_append_ntimes(buf, rest+1, grp_horizontal_symbol(tb)); + filled = 1; + } + filler = grp_horizontal_symbol(tb); + break; + case SCOLS_GSTATE_CONT_CHILDREN: + buffer_append_data(buf, filler); + buffer_append_data(buf, grp_vertical_symbol(tb)); + buffer_append_data(buf, filler); + break; + } + + if (filled) + break; + } + + if (!filled) + buffer_append_data(buf, filler); + return 0; +} + static int has_pending_data(struct libscols_table *tb) { struct libscols_column *cl; @@ -107,7 +204,7 @@ static void print_empty_cell(struct libscols_table *tb, if (art) { /* whatever the rc, len_pad will be sensible */ - line_ascii_art_to_buffer(tb, ln, art); + tree_ascii_art_to_buffer(tb, ln, art); if (!list_empty(&ln->ln_branch) && has_pending_data(tb)) buffer_append_data(art, vertical_symbol(tb)); data = buffer_get_safe_data(tb, art, &len_pad, NULL); @@ -458,19 +555,26 @@ int __cell_to_buffer(struct libscols_table *tb, return buffer_set_data(buf, data); /* + * Group stuff + */ + if (!scols_table_is_json(tb) && cl->is_groups) + rc = groups_ascii_art_to_buffer(tb, ln, buf); + + /* * Tree stuff */ - if (ln->parent && !scols_table_is_json(tb)) { - rc = line_ascii_art_to_buffer(tb, ln->parent, buf); + if (!rc && ln->parent && !scols_table_is_json(tb)) { + rc = tree_ascii_art_to_buffer(tb, ln->parent, buf); if (!rc && is_last_child(ln)) rc = buffer_append_data(buf, right_symbol(tb)); else if (!rc) rc = buffer_append_data(buf, branch_symbol(tb)); - if (!rc) - buffer_set_art_index(buf); } + if (!rc && (ln->parent || cl->is_groups) && !scols_table_is_json(tb)) + buffer_set_art_index(buf); + if (!rc) rc = buffer_append_data(buf, data); return rc; @@ -490,8 +594,6 @@ static int print_line(struct libscols_table *tb, assert(ln); - DBG(TAB, ul_debugobj(tb, "printing line")); - /* regular line */ scols_reset_iter(&itr, SCOLS_ITER_FORWARD); while (rc == 0 && scols_table_next_column(tb, &itr, &cl) == 0) { @@ -651,7 +753,20 @@ int __scols_print_header(struct libscols_table *tb, struct libscols_buffer *buf) while (rc == 0 && scols_table_next_column(tb, &itr, &cl) == 0) { if (scols_column_is_hidden(cl)) continue; - rc = buffer_set_data(buf, scols_cell_get_data(&cl->header)); + + buffer_reset_data(buf); + + if (cl->is_groups + && scols_table_is_tree(tb) && scols_column_is_tree(cl)) { + size_t i; + for (i = 0; i < tb->grpset_size + 1; i++) { + rc = buffer_append_data(buf, " "); + if (rc) + break; + } + } + if (!rc) + rc = buffer_append_data(buf, scols_cell_get_data(&cl->header)); if (!rc) rc = print_data(tb, cl, NULL, &cl->header, buf); } @@ -664,8 +779,8 @@ int __scols_print_header(struct libscols_table *tb, struct libscols_buffer *buf) 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)); + DBG(TAB, ul_debugobj(tb, "\tnext header: %zu [current=%zu, rc=%d]", + tb->header_next, tb->termlines_used, rc)); return rc; } @@ -715,7 +830,9 @@ static int print_tree_line(struct libscols_table *tb, int last, int last_in_table) { - int rc; + int rc, children = 0, gr_children = 0; + + DBG(LINE, ul_debugobj(ln, "printing line")); /* print the line */ fput_line_open(tb); @@ -723,27 +840,46 @@ static int print_tree_line(struct libscols_table *tb, if (rc) goto done; - /* print children */ - if (!list_empty(&ln->ln_branch)) { - struct list_head *p; + children = has_children(ln); + gr_children = is_last_group_member(ln) && has_group_children(ln); + if (children || gr_children) fput_children_open(tb); - /* print all children */ + /* print children */ + if (children) { + struct list_head *p; + list_for_each(p, &ln->ln_branch) { struct libscols_line *chld = list_entry(p, struct libscols_line, ln_children); - int last_child = p->next == &ln->ln_branch; + int last_child = !gr_children && p->next == &ln->ln_branch; rc = print_tree_line(tb, chld, buf, last_child, last_in_table && last_child); if (rc) goto done; } + } - fput_children_close(tb); + /* print group's children */ + if (gr_children) { + struct list_head *p; + + list_for_each(p, &ln->group->gr_children) { + struct libscols_line *chld = + list_entry(p, struct libscols_line, ln_children); + int last_child = p->next == &ln->group->gr_children; + + rc = print_tree_line(tb, chld, buf, last_child, last_in_table && last_child); + if (rc) + goto done; + } } - if (list_empty(&ln->ln_branch) || scols_table_is_json(tb)) + if (children || gr_children) + fput_children_close(tb); + + if ((!children && !gr_children) || scols_table_is_json(tb)) fput_line_close(tb, last, last_in_table); done: return rc; @@ -757,17 +893,18 @@ int __scols_print_tree(struct libscols_table *tb, struct libscols_buffer *buf) assert(tb); - DBG(TAB, ul_debugobj(tb, "printing tree")); + DBG(TAB, ul_debugobj(tb, "----printing-tree-----")); scols_reset_iter(&itr, SCOLS_ITER_FORWARD); - while (scols_table_next_line(tb, &itr, &ln) == 0) + while (scols_table_next_line(tb, &itr, &ln) == 0) { if (!last || !ln->parent) last = ln; + } scols_reset_iter(&itr, SCOLS_ITER_FORWARD); while (rc == 0 && scols_table_next_line(tb, &itr, &ln) == 0) { - if (ln->parent) + if (ln->parent || ln->parent_group) continue; rc = print_tree_line(tb, ln, buf, ln == last, ln == last); } @@ -893,6 +1030,12 @@ int __scols_initialize_printing(struct libscols_table *tb, struct libscols_buffe goto err; } + /* + * Make sure groups members are in the same orders as the tree + */ + if (has_groups(tb) && scols_table_is_tree(tb)) + scols_groups_fix_members_order(tb); + if (tb->format == SCOLS_FMT_HUMAN) { rc = __scols_calculate(tb, *buf); if (rc != 0) |