libsmartcols: use ASCII art for trees rather than padding

Based on patch from  Roman Odaisky.

References: https://launchpad.net/bugs/1406133
Signed-off-by: Karel Zak <kzak@redhat.com>
This commit is contained in:
Karel Zak 2015-01-07 15:20:22 +01:00
parent 2fa60c5ec2
commit 8501d9befe
1 changed files with 97 additions and 35 deletions

View File

@ -151,12 +151,103 @@ static size_t buffer_get_safe_art_size(struct libscols_buffer *buf)
return bytes;
}
/* returns pointer to the end of used data */
static int line_ascii_art_to_buffer(struct libscols_table *tb,
struct libscols_line *ln,
struct libscols_buffer *buf)
{
const char *art;
int rc;
assert(ln);
assert(buf);
if (!ln->parent)
return 0;
rc = line_ascii_art_to_buffer(tb, ln->parent, buf);
if (rc)
return rc;
if (list_entry_is_last(&ln->ln_children, &ln->parent->ln_branch))
art = " ";
else
art = tb->symbols->vert;
return buffer_append_data(buf, art);
}
#define is_last_column(_tb, _cl) \
list_entry_is_last(&(_cl)->cl_columns, &(_tb)->tb_columns)
#define colsep(tb) ((tb)->colsep ? (tb)->colsep : " ")
#define linesep(tb) ((tb)->linesep ? (tb)->linesep : "\n")
/* print padding or asci-art instead of data of @cl */
static void print_empty_cell(struct libscols_table *tb,
struct libscols_column *cl,
struct libscols_line *ln, /* optional */
size_t bufsz)
{
size_t len_pad = 0; /* in screen cells as opposed to bytes */
/* generate tree asci-art rather than padding */
if (ln && scols_column_is_tree(cl)) {
if (!ln->parent) {
/* only print symbols->vert if followed by something */
if (!list_empty(&ln->ln_branch)) {
fputs(tb->symbols->vert, tb->out);
len_pad = mbs_safe_width(tb->symbols->vert);
}
} else {
/* use the same draw function as though we were intending to draw an L-shape */
struct libscols_buffer *art = new_buffer(bufsz);
char *data;
if (art) {
/* whatever the rc, len_pad will be sensible */
line_ascii_art_to_buffer(tb, ln, art);
data = buffer_get_safe_data(art, &len_pad);
if (data && len_pad)
fputs(data, tb->out);
free_buffer(art);
}
}
}
/* fill rest of cell with space */
for(; len_pad <= cl->width; ++len_pad)
fputc(' ', tb->out);
}
/* fill-in all line with padding (or tree asci-art)
*
* This is necessary after long non-truncated colum where next column
* is printed in next line. For example (see 'DDD'):
*
* aaa bbb ccc ddd eee
* AAA BBB CCCCCCC
* DDD EEE
* ^^^^^^^^^^^^
* new line padding
*/
static void print_newline_padding(struct libscols_table *tb,
struct libscols_column *cl,
struct libscols_line *ln, /* optional */
size_t bufsz,
size_t len)
{
size_t i;
assert(tb);
assert(cl);
fputs(linesep(tb), tb->out); /* line break */
/* 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);
}
static int print_data(struct libscols_table *tb,
struct libscols_column *cl,
struct libscols_line *ln, /* optional */
@ -252,46 +343,17 @@ static int print_data(struct libscols_table *tb,
fputs(data, tb->out);
}
for (i = len; i < width; i++)
fputs(" ", tb->out); /* padding */
fputc(' ', tb->out); /* padding */
if (!is_last_column(tb, cl)) {
if (len > width && !scols_column_is_trunc(cl)) {
fputs(linesep(tb), tb->out);
for (i = 0; i <= (size_t) cl->seqnum; i++) {
struct libscols_column *x = scols_table_get_column(tb, i);
fprintf(tb->out, "%*s ", -((int)x->width), " ");
}
} else
fputs(colsep(tb), tb->out); /* columns separator */
}
return 0;
}
/* returns pointer to the end of used data */
static int line_ascii_art_to_buffer(struct libscols_table *tb,
struct libscols_line *ln,
struct libscols_buffer *buf)
{
const char *art;
int rc;
assert(ln);
assert(buf);
if (!ln->parent)
if (is_last_column(tb, cl))
return 0;
rc = line_ascii_art_to_buffer(tb, ln->parent, buf);
if (rc)
return rc;
if (list_entry_is_last(&ln->ln_children, &ln->parent->ln_branch))
art = " ";
if (len > width && !scols_column_is_trunc(cl))
print_newline_padding(tb, cl, ln, buf->bufsz, len); /* next column starts on next line */
else
art = tb->symbols->vert;
fputs(colsep(tb), tb->out); /* columns separator */
return buffer_append_data(buf, art);
return 0;
}
static int cell_to_buffer(struct libscols_table *tb,