From: Peter Krempa <pkrempa@redhat.com> In certain cases the code might want to skip the forced spacing. Introduce a concept of flags for each column and new function 'vshTableRowAppendFlags' which will do similar job as 'vshTableRowAppend' but add tuples of flags and the string itself. This patch implements the following flags: VSH_TABLE_CELL_SKIP_LEADING - skips the single leading whitespace VSH_TABLE_CELL_SKIP_TRAILING - skips the trailing 2 whitespaces VSH_TABLE_CELL_ALIGN_RIGHT - moves the alignment to the right of the column Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- tools/vsh-table.c | 75 ++++++++++++++++++++++++++++++++++++++++++++--- tools/vsh-table.h | 14 +++++++++ 2 files changed, 85 insertions(+), 4 deletions(-) diff --git a/tools/vsh-table.c b/tools/vsh-table.c index 0e537dd106..0502546bab 100644 --- a/tools/vsh-table.c +++ b/tools/vsh-table.c @@ -33,6 +33,7 @@ typedef struct _vshTableRow vshTableRow; struct _vshTableRow { char **cells; + unsigned int *flags; size_t ncells; }; @@ -55,6 +56,7 @@ vshTableRowFree(vshTableRow *row) g_free(row->cells[i]); g_free(row->cells); + g_free(row->flags); g_free(row); } G_DEFINE_AUTOPTR_CLEANUP_FUNC(vshTableRow, vshTableRowFree); @@ -89,6 +91,7 @@ static vshTableRow * vshTableRowNew(const char *arg, va_list ap) { vshTableRow *row = NULL; + size_t nflags = 0; if (!arg) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", @@ -100,10 +103,12 @@ vshTableRowNew(const char *arg, va_list ap) while (arg) { g_autofree char *tmp = NULL; + unsigned int fn = VSH_TABLE_CELL_DEFAULT; tmp = g_strdup(arg); VIR_APPEND_ELEMENT(row->cells, row->ncells, tmp); + VIR_APPEND_ELEMENT(row->flags, nflags, fn); arg = va_arg(ap, const char *); } @@ -178,6 +183,52 @@ vshTableRowAppend(vshTable *table, const char *arg, ...) } +/** + * vshTableRowAppendFlags: + * @table: table to append to + * @flags: start of the cell tuples of the row row (NULL terminated) + * + * Append new row into the @table. The number of cells in the row has + * to be equal to the number of cells in the table header. Each column consists + * of a tuple of an 'unsigned int' corresponding to bitwise-or of + * vshTableCellFlags and an const char * representing the value to add. + * + * Returns: 0 if succeeded, -1 if failed. + */ +int +vshTableRowAppendFlags(vshTable *table, + unsigned int f1, + const char *c1, + ...) +{ + g_autoptr(vshTableRow) row = g_new0(vshTableRow, 1); + size_t ncolumns = table->rows[0]->ncells; + va_list ap; + unsigned int fn = f1; + g_autofree char *cn = g_strdup(c1); + size_t nflags = 0; + + va_start(ap, c1); + while (cn) { + VIR_APPEND_ELEMENT(row->flags, nflags, fn); + VIR_APPEND_ELEMENT(row->cells, row->ncells, cn); + + fn = va_arg(ap, unsigned int); + cn = g_strdup(va_arg(ap, const char *)); + } + va_end(ap); + + if (ncolumns != row->ncells) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Incorrect number of cells in a table row")); + return -1; + } + + VIR_APPEND_ELEMENT(table->rows, table->nrows, row); + + return 0; +} + /** * Function pulled from util-linux * @@ -286,7 +337,11 @@ vshTableGetColumnsWidths(vshTable *table, return -1; /* include the built-in whitespace in the calculated length */ - size += 3; + if (!(row->flags[j] & VSH_TABLE_CELL_SKIP_LEADING)) + size += 1; + + if (!(row->flags[j] & VSH_TABLE_CELL_SKIP_TRAILING)) + size += 2; VIR_FREE(row->cells[j]); row->cells[j] = tmp; @@ -318,13 +373,25 @@ vshTableRowPrint(vshTableRow *row, size_t j; for (i = 0; i < row->ncells; i++) { - virBufferAsprintf(buf, " %s", row->cells[i]); + if (!(row->flags[i] & VSH_TABLE_CELL_SKIP_LEADING)) + virBufferAddLit(buf, " "); - if (i < (row->ncells - 1)) { + if (row->flags[i] & VSH_TABLE_CELL_ALIGN_RIGHT) { for (j = 0; j < maxwidths[i] - widths[i]; j++) virBufferAddChar(buf, ' '); - virBufferAddLit(buf, " "); + virBufferAsprintf(buf, "%s", row->cells[i]); + } else { + virBufferAsprintf(buf, "%s", row->cells[i]); + + if (i < (row->ncells - 1)) { + for (j = 0; j < maxwidths[i] - widths[i]; j++) + virBufferAddChar(buf, ' '); + } } + + if (!(row->flags[i] & VSH_TABLE_CELL_SKIP_TRAILING) && + i < (row->ncells - 1)) + virBufferAddLit(buf, " "); } virBufferAddChar(buf, '\n'); } diff --git a/tools/vsh-table.h b/tools/vsh-table.h index 18d5139aa6..cffc9c3dbc 100644 --- a/tools/vsh-table.h +++ b/tools/vsh-table.h @@ -24,6 +24,13 @@ typedef struct _vshTable vshTable; +typedef enum { + VSH_TABLE_CELL_DEFAULT = 0, + VSH_TABLE_CELL_SKIP_LEADING = 1 << 0, + VSH_TABLE_CELL_SKIP_TRAILING = 1 << 1, + VSH_TABLE_CELL_ALIGN_RIGHT = 1 << 2, +} vshTableCellFlags; + void vshTableFree(vshTable *table); G_DEFINE_AUTOPTR_CLEANUP_FUNC(vshTable, vshTableFree); @@ -36,6 +43,13 @@ int vshTableRowAppend(vshTable *table, const char *arg, ...) G_GNUC_NULL_TERMINATED; +int +vshTableRowAppendFlags(vshTable *table, + unsigned int f1, + const char *c1, + ...) + G_GNUC_NULL_TERMINATED; + void vshTablePrintToStdout(vshTable *table, vshControl *ctl); -- 2.53.0