чување 29d5023c38e8629769473c5c6a93c535dd50efea
родитељ 00bb345f88d99c427151eb3176b0a98addcf8d6a
Аутор: Страхиња Радић <contact@strahinja.org>
Датум: Tue, 16 May 2023 22:44:49 +0200
Add -a
Signed-off-by: Страхиња Радић <contact@strahinja.org>
Diffstat:
измењених датотека: 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,
+ ¤t_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,
+ ¤t_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)
{