table

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

чување 5b64005e80e3fe98a81c442d35ef6ded7a42830a
родитељ d6e7d2eae13d29d30d7712841b09cb4d44523e04
Аутор: Страхиња Радић <contact@strahinja.org>
Датум:   Sat, 20 Feb 2021 17:56:05 +0100

Finished adding format support; updated manpage

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

Diffstat:
M.gitignore | 1+
Mdefs.h | 15++++-----------
Aexamples/quotes-english.csv | 6++++++
Mindex.html | 5+++++
Mtable.1.in | 36++++++++++++++++++++++++++++++++++++
Mtable.c | 202+++++++++++++++++++++++++++++++++++++++++++------------------------------------
измењених датотека: 6, додавања: 163(+), брисања: 102(-)

diff --git a/.gitignore b/.gitignore @@ -1,6 +1,7 @@ .cache .redo *.session +.gdbinit .do_built .do_built.dir *~ diff --git a/defs.h b/defs.h @@ -32,26 +32,19 @@ #include <uniwidth.h> #define PROGRAMNAME "table" -#define VERSION "0.1.2-beta" +#define VERSION "0.2.1" -#define BUFSIZE 4096 +#define BUFSIZE 4096 #define SMALL_BUFSIZE 256 -// Minimal table column width without the borders -// | A | B | C | -// ^^^--This -// [Max screen columns] - [Table columns] - 1 -// [Max table columns] = ------------------------------------------ -// MIN_TABLE_COL_WIDTH -#define MIN_TABLE_COL_WIDTH 3 //#define ANSI_SGR_RESET "\e[0m\e[?25h" -#define ANSI_SGR_BOLD_ON "\e[1m" +#define ANSI_SGR_BOLD_ON "\e[1m" #define ANSI_SGR_BOLD_OFF "\e[0m" typedef enum { FALSE = 0, - TRUE = 1 + TRUE = 1 } BOOL; typedef unsigned char UBYTE; diff --git a/examples/quotes-english.csv b/examples/quotes-english.csv @@ -0,0 +1,6 @@ +"ID","Name","Surname","Age" +"001","John","Smith","34" +"002","Steven","Watson","23" +"003","Richard","Smith","33" +"007","Bond, James","Bond","46" + diff --git a/index.html b/index.html @@ -155,6 +155,11 @@ fileviewer *.csv <h2>Changelog</h2> + <h2>v0.2.1</h3> + <ul> + <li>Added format support</li> + </ul> + <h3>v0.2</h3> <ul> <li>Switched to apenwarr/redo</li> diff --git a/table.1.in b/table.1.in @@ -31,6 +31,7 @@ table \- Command line utility to format and display CSV. .OP "\-b \fR|\fP \-\-border\-mode" .OP "\-c \fR|\fP \-\-columns=" cols .OP "\-d \fR|\fP \-\-delim=" delim +.OP "\-f \fR|\fP \-\-format=" format .OP "\-n \fR|\fP \-\-no\-ansi" .OP "\-s \fR|\fP \-\-symbols=" set .OP "\-t \fR|\fP \-\-expand-tabs" @@ -81,6 +82,41 @@ $ table -d ';' .CDE . .TP +.BI \-f " format" +.TQ +.BI \-\-format= format +.br +Set widths for individual columns as ratio. Parameter \fIformat\fP should be a +string of weights separated by colons. For example: +. +.CDS 12 +$ table -c 50 -s aa examples/quotes-english.csv ++-----------+-----------+-----------+-----------+ +|ID |Name |Surname |Age | +|001 |John |Smith |34 | +|002 |Steven |Watson |23 | +|003 |Richard |Smith |33 | +|007 |Bond, James|Bond |46 | ++-----------+-----------+-----------+-----------+ +$ table -f 1:2:3:4 -c 50 -s aa examples/quotes-english.csv ++----+---------+-------------+------------------+ +|ID |Name |Surname |Age | +|001 |John |Smith |34 | +|002 |Steven |Watson |23 | +|003 |Richard |Smith |33 | +|007 |Bond, Jam|Bond |46 | ++----+---------+-------------+------------------+ +$ table -f 1:5:5:1 -c 50 -s aa examples/quotes-english.csv ++----+------------------+------------------+----+ +|ID |Name |Surname |Age | +|001 |John |Smith |34 | +|002 |Steven |Watson |23 | +|003 |Richard |Smith |33 | +|007 |Bond, James |Bond |46 | ++----+------------------+------------------+----+ +.CDE +. +.TP .BR \-h .TQ .B \-\-help diff --git a/table.c b/table.c @@ -52,26 +52,18 @@ } \ *pformat++ = num; } -#define WITHIN_COLUMN (current_rune_column < \ - (current_table_column+1) * max_table_column_width \ - + current_table_column) - -#define WITHIN_SINGLE_COLUMN (current_rune_column < rune_columns-2) - size_t colno = 0; size_t lineno = 0; int current_symbol_set = TABLE_SYMBOLS_DOUBLE; int current_inner_symbol_set = TABLE_INNER_DOUBLE_SINGLE; size_t current_table_column = 0; size_t current_rune_column = 0; -size_t max_table_column_width = MIN_TABLE_COL_WIDTH; size_t table_columns = 0; size_t rune_columns = 80; size_t tab_length = 8; ucs4_t delimiter = ','; ULONG* format = NULL; size_t format_size = 0; - BOOL handle_ansi = TRUE; BOOL border_mode = FALSE; BOOL expand_tabs = FALSE; @@ -87,8 +79,9 @@ int usage() { printf("Usage: %s [-b|--border-mode] [-c <cols>|--columns=<cols>] [-d" - " <delim>|--delimiter=<delim>] [-h|--help] [-n|--no-ansi] [-s" - " <set>|--symbols=<set>] [-t|--expand-tabs] [-v|--version]\n", + " <delim>|--delimiter=<delim>] [-f <format>|--format=<format>]" + " [-h|--help] [-n|--no-ansi] [-s <set>|--symbols=<set>] " + "[-t|--expand-tabs] [-v|--version]\n", PROGRAMNAME); return 0; } @@ -241,6 +234,7 @@ set_format(const char* arg, ULONG** format, size_t* format_size) *format = NULL; return 2; } + *ptoken = 0; num = strtol(token, NULL, 10); if (errno) { @@ -260,6 +254,7 @@ set_format(const char* arg, ULONG** format, size_t* format_size) } if (*token) { + *ptoken = 0; num = strtol(token, NULL, 10); if (errno) { @@ -304,31 +299,16 @@ number_of_columns(const uint8_t* input, ucs4_t delimiter) return result; } -// | A | B | C | -// ^^^-^^^-^^^----This -size_t -get_max_table_column_width(size_t rune_columns, size_t table_columns) +UINT round_div(UINT a, UINT b) { - if (rune_columns < table_columns+1) - return MIN_TABLE_COL_WIDTH; - - size_t result = (rune_columns-table_columns-1)/table_columns; - - return result < MIN_TABLE_COL_WIDTH - ? MIN_TABLE_COL_WIDTH - : result; + return (a + (b/2)) / b; } BOOL -within_column() +within_column(size_t column_start) { - if (format) - { - } - else - { - } - return TRUE; + return (current_rune_column < + column_start + *(format+current_table_column)); } int @@ -483,28 +463,11 @@ main(int argc, char** argv) BOOL quote = FALSE; ucs4_t uch; size_t ch_len = 0; + size_t output_lines = 0; + size_t column_start = 0; CALLOC(line, uint8_t, BUFSIZE) - if (format) - { - ULONG* pformat = format; - ULONG format_sum = 0; - while (*pformat) - { - format_sum += *pformat; - pformat++; - } - pformat = format; - while (*pformat) - { - printf("format++ = %lu/%lu = %lu\n", *pformat, format_sum, - (rune_columns-1) * (*pformat) / format_sum); - pformat++; - } - } - else - printf("format not set\n"); while (!feof(input)) { char* eol = NULL; @@ -523,40 +486,79 @@ main(int argc, char** argv) colno = 0; current_rune_column = 0; + /* Top border */ if (lineno == 0) { if (!border_mode) table_columns = number_of_columns(line, delimiter); else table_columns = 1; - max_table_column_width = get_max_table_column_width(rune_columns, - table_columns); - if (rune_columns < table_columns * MIN_TABLE_COL_WIDTH - + table_columns + 1) - rune_columns = table_columns * MIN_TABLE_COL_WIDTH - + table_columns + 1; + + /* Sanity check */ + if (rune_columns < table_columns+1) + rune_columns = table_columns+1; + + if (format && !border_mode) + { + ULONG* pformat = format; + ULONG format_sum = 0; + while (*pformat) + format_sum += *pformat++; + pformat = format; + while (*pformat && format_sum) + { + *pformat = round_div((rune_columns-table_columns-2) + * (*pformat), format_sum); + pformat++; + } + } + else + { + ULONG* pformat = NULL; + format_size = SMALL_BUFSIZE; + CALLOC(format, ULONG, format_size) + pformat = format; + for (size_t col = 0; col < table_columns; col++) + *pformat++ = (rune_columns-table_columns-2) / table_columns; + } current_table_column = 0; - for (size_t col = 0; col < rune_columns; col++) + column_start = 0; + while (current_table_column < table_columns) { - if (col == 0) + if (current_rune_column == 0) + { printf("%s", table_symbols[current_symbol_set][0]); - else if (col == rune_columns-1) - printf("%s", table_symbols[current_symbol_set][2]); - else if (current_table_column < table_columns-1 - && col > 1 - && col % (max_table_column_width+1) == 0) + column_start++; + } + else if (!within_column(column_start)) { - current_table_column++; - printf("%s", table_inner_symbols[current_inner_symbol_set][0]); + if (current_table_column == table_columns-1) + { + printf("%s", table_symbols[current_symbol_set][2]); + current_table_column++; + } + else + { + printf("%s", table_inner_symbols[current_inner_symbol_set][0]); + column_start++; + if (format) + column_start += *(format+current_table_column); + current_table_column++; + } } else printf("%s", table_symbols[current_symbol_set][1]); + current_rune_column++; } printf("\n"); + output_lines++; } + /* Inner rows */ current_table_column = 0; + current_rune_column = 0; + column_start = 0; printf("%s", table_symbols[current_symbol_set][3]); @@ -579,7 +581,7 @@ main(int argc, char** argv) if (border_mode) { pch_end = pline + ch_len; - if (WITHIN_SINGLE_COLUMN) + if (within_column(column_start)) { while (pline != pch_end) printf("%c", *pline++); @@ -590,7 +592,7 @@ main(int argc, char** argv) } else if (ch_len <= 0) { - if (WITHIN_COLUMN) + if (within_column(column_start)) { printf("%c", *pline++); current_rune_column++; @@ -599,7 +601,7 @@ main(int argc, char** argv) } else if (uch == '\t' && expand_tabs) { - while (WITHIN_COLUMN) + while (within_column(column_start)) { printf(" "); current_rune_column++; @@ -614,12 +616,14 @@ main(int argc, char** argv) if (handle_ansi && lineno == 0) printf("%s", ANSI_SGR_BOLD_OFF); - while (WITHIN_COLUMN) + while (within_column(column_start)) { printf(" "); current_rune_column++; } - + column_start++; + if (format) + column_start += *(format+current_table_column); if (current_table_column != table_columns-1) { printf("%s", table_inner_symbols[current_inner_symbol_set][1]); @@ -636,10 +640,7 @@ main(int argc, char** argv) else { pch_end = pline + ch_len; - if ((current_table_column == table_columns-1 - && current_rune_column < rune_columns-2) - || (current_table_column < table_columns-1 - && WITHIN_COLUMN)) + if (within_column(column_start)) { while (pline != pch_end) printf("%c", *pline++); @@ -656,7 +657,7 @@ main(int argc, char** argv) while (current_table_column < table_columns-1) { - while (WITHIN_COLUMN) + while (within_column(column_start)) { printf(" "); current_rune_column++; @@ -665,7 +666,7 @@ main(int argc, char** argv) current_table_column++; current_rune_column++; } - while (current_rune_column < rune_columns-2) + while (within_column(column_start)) { printf(" "); current_rune_column++; @@ -673,32 +674,51 @@ main(int argc, char** argv) printf("%s\n", table_symbols[current_symbol_set][5]); + output_lines++; lineno++; } fclose(input); free(line); - if (format) - free(format); - current_table_column = 0; - for (size_t col = 0; col < rune_columns; col++) + /* Bottom border */ + if (output_lines) { - if (col == 0) - printf("%s", table_symbols[current_symbol_set][6]); - else if (col == rune_columns-1) - printf("%s", table_symbols[current_symbol_set][8]); - else if (current_table_column < table_columns-1 - && col > 1 - && col % (max_table_column_width+1) == 0) + current_table_column = 0; + current_rune_column = 0; + column_start = 0; + while (current_table_column < table_columns) { - current_table_column++; - printf("%s", table_inner_symbols[current_inner_symbol_set][2]); + if (current_rune_column == 0) + { + printf("%s", table_symbols[current_symbol_set][6]); + column_start++; + } + else if (!within_column(column_start)) + { + if (current_table_column == table_columns-1) + { + printf("%s", table_symbols[current_symbol_set][8]); + current_table_column++; + } + else + { + printf("%s", table_inner_symbols[current_inner_symbol_set][2]); + column_start++; + if (format) + column_start += *(format+current_table_column); + current_table_column++; + } + } + else + printf("%s", table_symbols[current_symbol_set][7]); + current_rune_column++; } - else - printf("%s", table_symbols[current_symbol_set][7]); + printf("\n"); + output_lines++; } - printf("\n"); + + free(format); return 0; }