table

Помоћни програм из командне линије за форматирање и приказ CSV-а
Дневник | Датотеке | Референце | ПРОЧИТАЈМЕ | ЛИЦЕНЦА

чување 29d5023c38e8629769473c5c6a93c535dd50efea
родитељ 00bb345f88d99c427151eb3176b0a98addcf8d6a
Аутор: Страхиња Радић <contact@strahinja.org>
Датум:   Tue, 16 May 2023 22:44:49 +0200

Add -a

Signed-off-by: Страхиња Радић <contact@strahinja.org>

Diffstat:
M.gitignore | 2+-
MTODO | 2+-
Mdefs.h | 3+++
Mtable.1.in | 15+++++++++++++++
Mtable.c | 173+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------
измењених датотека: 5, додавања: 164(+), брисања: 31(-)

diff --git a/.gitignore b/.gitignore @@ -18,7 +18,7 @@ nohup.out *.xz *.png *.1 -config.redo +config.redo* table table.1 date diff --git a/TODO b/TODO @@ -1,7 +1,7 @@ TODO ==== -[ ] Add column alignment +[x] Add column alignment <x> Add switch to turn off processing of quotes; have tsvtable use it automatically diff --git a/defs.h b/defs.h @@ -17,6 +17,7 @@ typedef unsigned long ULONG; typedef enum { CMD_NONE, + CMD_ALIGN, CMD_COLUMNS, CMD_DELIMITER, CMD_FORMAT, @@ -27,6 +28,8 @@ typedef enum { enum { Q_PROCESS, Q_IGNORE }; +typedef enum { ALIGN_LEFT, ALIGN_CENTER, ALIGN_RIGHT } Alignment; + enum { TABLE_SYMBOLS_ASCII, TABLE_SYMBOLS_SINGLE, diff --git a/table.1.in b/table.1.in @@ -47,6 +47,7 @@ is a synonym for .YS . .SY table +.OP "\-a \fR|\fP \-\-align=" alignment .OP "\-b \fR|\fP \-\-border\-mode" .OP "\-c \fR|\fP \-\-columns=" cols .OP "\-d \fR|\fP \-\-delim=" delim @@ -78,6 +79,20 @@ drawing. .SH OPTIONS . .TP +.BI \-a " alignment" +.TQ +.BI \-\-align= alignment +.br +Set column alignments. +.I alignment +is a string consisting of characters +.BR l ", " c " or " r , +which respectively set the alignment of the corresponding column to left, center +or right. +For example, \fC\-arccc\fR sets the alignment for the first column to right, and +the next three columns to center. +. +.TP .B \-b .TQ .B \-\-border-mode diff --git a/table.c b/table.c @@ -76,6 +76,8 @@ u32 delimiter = L','; ULONG* format = NULL; size_t format_size = 0; ULONG format_value = 0; +Alignment* align = NULL; +size_t align_size = 0; int border_mode = 0; int handle_ansi = 1; int msdos = 0; @@ -93,7 +95,8 @@ version() int usage() { - printf("Usage: %s [-b|--border-mode] [-c <cols>|--columns=<cols>] [-d" + printf("Usage: %s [-a <alignment>|--align=<alignment>]" + " [-b|--border-mode] [-c <cols>|--columns=<cols>] [-d" " <delim>|--delimiter=<delim>] [-f <format>|--format=<format>]" " [-h|--help] [-m|--msdos] [-n|--no-ansi]" " [-p|--pause] [-q <behavior>|--quotes=<behavior>]" @@ -219,6 +222,41 @@ set_symbol_set(char* arg, int* current_symbol_set, int* current_inner_symbol_set } int +set_align(const char* arg, Alignment** align, size_t* align_size) +{ + const char* parg = arg; + Alignment* palign = NULL; + + *align_size = strlen(arg); + CALLOC(*align, Alignment, *align_size); + palign = *align; + + while (*parg) + { + switch (*parg) + { + case 'l': + *palign++ = ALIGN_LEFT; + break; + case 'c': + *palign++ = ALIGN_CENTER; + break; + case 'r': + *palign++ = ALIGN_RIGHT; + break; + default: + free(*align); + *align = NULL; + *align_size = 0; + return 1; + } + parg++; + } + + return 0; +} + +int set_columns(const char* arg, size_t* cols) { size_t c = strtol(arg, NULL, 10); @@ -325,6 +363,35 @@ set_quotes_behavior(const char* arg, int* quotes) return 0; } +int +print_aligned(const u8* s, size_t rune_length, size_t to_size, Alignment align, + size_t* current_rune_column) +{ + size_t i; + + if (align == ALIGN_CENTER) + for (i = 0; i < (to_size - rune_length) / 2; i++) + { + printf(" "); + (*current_rune_column)++; + } + else if (align == ALIGN_RIGHT) + for (i = 0; i < (to_size - rune_length); i++) + { + printf(" "); + (*current_rune_column)++; + } + printf("%s", s); + (*current_rune_column) += rune_length; + if (align == ALIGN_CENTER) + for (i = 0; i < (to_size - rune_length) / 2; i++) + { + printf(" "); + (*current_rune_column)++; + } + return 0; +} + /* Return number of columns based on the input line */ size_t number_of_columns(const u8* input, u32 delimiter) @@ -400,6 +467,11 @@ do_arg: { if (!strcmp(arg, "version")) cmd = CMD_VERSION; + else if (startswith(arg, "align=")) + { + arg += strlen("align="); + set_align(arg, &align, &align_size); + } else if (!strcmp(arg, "border-mode")) { arg += strlen("border-mode"); @@ -479,6 +551,9 @@ do_arg: { switch (c) { + case 'a': + cmd = CMD_ALIGN; + break; case 'b': border_mode = 1; break; @@ -527,7 +602,13 @@ do_arg: else { continue_current_arg: - if (cmd == CMD_COLUMNS) + if (cmd == CMD_ALIGN) + { + if (set_align(arg, &align, &align_size)) + return error(EINVAL, "Invalid argument: '%s'", + arg); + } + else if (cmd == CMD_COLUMNS) { if (set_columns(arg, &rune_columns)) return error(EINVAL, "Invalid argument: '%s'", @@ -578,9 +659,12 @@ done_arg: else input = stdin; - u8* line = NULL; - u8* pline = NULL; - int in_quote = 0; + u8* line = NULL; + u8* pline = NULL; + u8* outbuf = NULL; + u8* poutbuf = NULL; + size_t outbufrunelen = 0; + int in_quote = 0; u32 uch; u8 u8ch[7]; size_t u8len = 0; @@ -590,6 +674,7 @@ done_arg: u8* pch_end; CALLOC(line, u8, BUFSIZE); + CALLOC(outbuf, u8, BUFSIZE); do_input: if (feof(input)) @@ -612,6 +697,8 @@ do_input: in_quote = 0; pline = line; + poutbuf = outbuf; + outbufrunelen = 0; colno = 0; current_rune_column = 0; @@ -670,7 +757,6 @@ do_column: *table_symbols[current_symbol_set][2]); u8ch[u8len] = 0; printf("%s", u8ch); - current_table_column++; } else { @@ -685,8 +771,8 @@ do_column: += *(format + current_table_column); else column_start += format_value; - current_table_column++; } + current_table_column++; } else { @@ -783,14 +869,29 @@ continue_line: if (uch == delimiter && !in_quote && current_table_column < table_columns - 1) { + size_t colwidth = format ? *(format + current_table_column) + : format_value; + if (handle_ansi && lineno == 0) - printf("%s", ANSI_SGR_BOLD_OFF); + poutbuf += sprintf((char*)poutbuf, "%s", + ANSI_SGR_BOLD_OFF); + + print_aligned(outbuf, outbufrunelen, colwidth, + current_table_column < align_size + ? align[current_table_column] + : ALIGN_LEFT, + &current_rune_column); while (within_column(column_start)) { printf(" "); current_rune_column++; } + + *outbuf = 0; + poutbuf = outbuf; + outbufrunelen = 0; + column_start++; if (format) column_start += *(format + current_table_column); @@ -808,17 +909,19 @@ continue_line: } if (handle_ansi && lineno == 0) - printf("%s", ANSI_SGR_BOLD_ON); + poutbuf += sprintf((char*)poutbuf, "%s", + ANSI_SGR_BOLD_ON); pline += ch_len; colno += ch_len; } - else if (ch_len <= 0) + else if (!ch_len) /* UTF-8 error */ { if (within_column(column_start)) { - printf("%c", *pline++); - current_rune_column++; + sprintf((char*)poutbuf, "%c", *pline++); + poutbuf++; + outbufrunelen++; } colno++; } @@ -826,34 +929,25 @@ continue_line: { while (within_column(column_start)) { - printf(" "); - current_rune_column++; - if (current_rune_column % tab_length == 0) + sprintf((char*)poutbuf, " "); + poutbuf++; + outbufrunelen++; + if ((current_rune_column + outbufrunelen) % tab_length + == 0) break; } pline++; colno++; } - else if (border_mode) - { - pch_end = pline + ch_len; - if (within_column(column_start)) - { - while (pline != pch_end) - printf("%c", *pline++); - current_rune_column++; - } - pline = pch_end; - colno += ch_len; - } else { pch_end = pline + ch_len; if (within_column(column_start)) { while (pline != pch_end) - printf("%c", *pline++); - current_rune_column++; + poutbuf += sprintf((char*)poutbuf, "%c", + *pline++); + outbufrunelen++; } pline = pch_end; colno += ch_len; @@ -865,6 +959,25 @@ done_line:; if (handle_ansi && lineno == 0) printf("%s", ANSI_SGR_BOLD_OFF); + if (*outbuf) + { + size_t colwidth = format ? *(format + current_table_column) + : format_value; + + if (handle_ansi && lineno == 0) + poutbuf += sprintf((char*)poutbuf, "%s", + ANSI_SGR_BOLD_OFF); + + print_aligned(outbuf, outbufrunelen, colwidth, + current_table_column < align_size + ? align[current_table_column] + : ALIGN_LEFT, + &current_rune_column); + + *outbuf = 0; + poutbuf = outbuf; + outbufrunelen = 0; + } while (current_table_column < table_columns - 1) { while (within_column(column_start)) @@ -901,6 +1014,7 @@ done_line:; done_input: free(line); + free(outbuf); /* Bottom border */ if (!output_lines) @@ -957,6 +1071,7 @@ done_bottom_border: skip_bottom_border: free(format); + free(align); if (pause) {