чување 87a587014e2ac983134f36fde443c965723d74da
родитељ 66eea0abf2b8886d89ce550a87d083bd000a8188
Аутор: Страхиња Радић <contact@strahinja.org>
Датум: Wed, 10 May 2023 21:27:56 +0200
Add -q
Signed-off-by: Страхиња Радић <contact@strahinja.org>
Diffstat:
| M | TODO | | | 2 | +- |
| M | defs.h | | | 62 | +++++++++++++++++++++++++++++++------------------------------- |
| M | table.1.in | | | 24 | +++++++++++++++++++++++- |
| M | table.c | | | 210 | ++++++++++++++++++++++++++++++++++++++++++++++++------------------------------- |
измењених датотека: 4, додавања: 184(+), брисања: 114(-)
diff --git a/TODO b/TODO
@@ -3,7 +3,7 @@ TODO
[ ] Add column alignment
-< > Add switch to turn off processing of quotes; have tsvtable use it
+<x> Add switch to turn off processing of quotes; have tsvtable use it
automatically
diff --git a/defs.h b/defs.h
@@ -4,49 +4,49 @@
#include "utf8.h"
-#define BUFSIZE 4096
+#define BUFSIZE 4096
#define SMALL_BUFSIZE 256
-//#define ANSI_SGR_RESET "\e[0m\e[?25h"
+// #define ANSI_SGR_RESET "\e[0m\e[?25h"
#define ANSI_SGR_BOLD_ON "\e[1m"
#define ANSI_SGR_BOLD_OFF "\e[0m"
typedef unsigned char UBYTE;
-typedef unsigned int UINT;
+typedef unsigned int UINT;
typedef unsigned long ULONG;
-typedef enum
-{
- CMD_NONE,
- CMD_COLUMNS,
- CMD_DELIMITER,
- CMD_FORMAT,
- CMD_SYMBOLS,
- CMD_VERSION
+typedef enum {
+ CMD_NONE,
+ CMD_COLUMNS,
+ CMD_DELIMITER,
+ CMD_FORMAT,
+ CMD_QUOTES,
+ CMD_SYMBOLS,
+ CMD_VERSION
} Command;
-enum
-{
- TABLE_SYMBOLS_ASCII,
- TABLE_SYMBOLS_SINGLE,
- TABLE_SYMBOLS_DOUBLE,
- TABLE_SYMBOLS_EMPTY
+enum { Q_PROCESS, Q_IGNORE };
+
+enum {
+ TABLE_SYMBOLS_ASCII,
+ TABLE_SYMBOLS_SINGLE,
+ TABLE_SYMBOLS_DOUBLE,
+ TABLE_SYMBOLS_EMPTY
};
-enum
-{
- TABLE_INNER_ASCII_ASCII,
- TABLE_INNER_SINGLE_SINGLE,
- TABLE_INNER_SINGLE_DOUBLE,
- TABLE_INNER_DOUBLE_SINGLE,
- TABLE_INNER_DOUBLE_DOUBLE,
- TABLE_INNER_EMPTY_EMPTY,
- TABLE_INNER_ASCII_EMPTY,
- TABLE_INNER_SINGLE_EMPTY,
- TABLE_INNER_DOUBLE_EMPTY,
- TABLE_INNER_EMPTY_ASCII,
- TABLE_INNER_EMPTY_SINGLE,
- TABLE_INNER_EMPTY_DOUBLE,
+enum {
+ TABLE_INNER_ASCII_ASCII,
+ TABLE_INNER_SINGLE_SINGLE,
+ TABLE_INNER_SINGLE_DOUBLE,
+ TABLE_INNER_DOUBLE_SINGLE,
+ TABLE_INNER_DOUBLE_DOUBLE,
+ TABLE_INNER_EMPTY_EMPTY,
+ TABLE_INNER_ASCII_EMPTY,
+ TABLE_INNER_SINGLE_EMPTY,
+ TABLE_INNER_DOUBLE_EMPTY,
+ TABLE_INNER_EMPTY_ASCII,
+ TABLE_INNER_EMPTY_SINGLE,
+ TABLE_INNER_EMPTY_DOUBLE,
};
static const u32* table_symbols[][9] =
diff --git a/table.1.in b/table.1.in
@@ -34,7 +34,7 @@ is a synonym for
.br
.B tsvtable
is a synonym for
-.BR "table -d \(dq$(printf '\et')\(dq" .
+.BR "table -d \(dq$(printf '\et')\(dq -q ignore" .
.
.SH SYNOPSIS
.
@@ -54,6 +54,7 @@ is a synonym for
.OP "\-m \fR|\fP \-\-msdos"
.OP "\-n \fR|\fP \-\-no\-ansi"
.OP "\-p \fR|\fP \-\-pause"
+.OP "\-q \fR|\fP \-\-quotes=" behavior
.OP "\-s \fR|\fP \-\-symbols=" set
.OP "\-t \fR|\fP \-\-expand-tabs"
.YS
@@ -191,6 +192,27 @@ from file managers which don't pause after executing programs or as a single
command from terminal emulators.
.
.TP
+.BI \-q " behavior"
+.TQ
+.BI \-\-quotes= behavior
+.br
+.I behavior
+can be one of the following:
+.
+.RS
+.IP \fBprocess\fP
+Treats everything between the quotes as a single column.
+Treats consequtive quotes within the quoted text as literal quotes.
+This is the default.
+.IP \fBignore\fP
+Ignores the special meaning of quotes (like TSV).
+This is the default if
+.B table
+is called as
+.BR tsvtable .
+.RE
+.
+.TP
.BI \-s " set"
.TQ
.BI \-\-symbols= set
diff --git a/table.c b/table.c
@@ -81,6 +81,7 @@ int handle_ansi = 1;
int msdos = 0;
int pause = 0;
int expand_tabs = 0;
+int quotes = Q_PROCESS;
int
version()
@@ -95,8 +96,9 @@ usage()
printf("Usage: %s [-b|--border-mode] [-c <cols>|--columns=<cols>] [-d"
" <delim>|--delimiter=<delim>] [-f <format>|--format=<format>]"
" [-h|--help] [-m|--msdos] [-n|--no-ansi]"
- " [-p|--pause] [-s <set>|--symbols=<set>] [-t|--expand-tabs] "
- "[-v|--version]\n",
+ " [-p|--pause] [-q <behavior>|--quotes=<behavior>]"
+ " [-s <set>|--symbols=<set>] [-t|--expand-tabs]"
+ " [-v|--version]\n",
PROGRAMNAME);
return 0;
}
@@ -311,6 +313,18 @@ set_format(const char* arg, ULONG** format, size_t* format_size)
return 0;
}
+int
+set_quotes_behavior(const char* arg, int* quotes)
+{
+ if (!strcmp(arg, "process"))
+ *quotes = Q_PROCESS;
+ else if (!strcmp(arg, "ignore"))
+ *quotes = Q_IGNORE;
+ else
+ return 1;
+ return 0;
+}
+
/* Return number of columns based on the input line */
size_t
number_of_columns(const u8* input, u32 delimiter)
@@ -365,7 +379,10 @@ main(int argc, char** argv)
progname = sep + 1;
if (!strcmp(progname, "tsvtable"))
+ {
delimiter = L'\t';
+ quotes = Q_IGNORE;
+ }
else if (!strcmp(progname, "tablep"))
pause = 1;
@@ -431,6 +448,15 @@ do_arg:
arg += strlen("pause");
pause = 1;
}
+ else if (startswith(arg, "quotes="))
+ {
+ arg += strlen("quotes=");
+ if (set_quotes_behavior(arg, "es))
+ return error(EINVAL,
+ "Invalid argument: "
+ "'%s'",
+ arg);
+ }
else if (startswith(arg, "symbols="))
{
arg += strlen("symbols=");
@@ -477,6 +503,9 @@ do_arg:
case 'p':
pause = 1;
break;
+ case 'q':
+ cmd = CMD_QUOTES;
+ break;
case 's':
cmd = CMD_SYMBOLS;
break;
@@ -516,6 +545,12 @@ do_arg:
return error(EINVAL, "Invalid argument: '%s'",
arg);
}
+ else if (cmd == CMD_QUOTES)
+ {
+ if (set_quotes_behavior(arg, "es))
+ return error(EINVAL, "Invalid argument: '%s'",
+ arg);
+ }
else if (cmd == CMD_SYMBOLS)
{
if (set_symbol_set(arg, ¤t_symbol_set,
@@ -543,15 +578,16 @@ done_arg:
else
input = stdin;
- u8* line = NULL;
- u8* pline = NULL;
- int quote = 0;
+ u8* line = NULL;
+ u8* pline = NULL;
+ int in_quote = 0;
u32 uch;
u8 u8ch[7];
size_t u8len = 0;
size_t ch_len = 0;
size_t output_lines = 0;
size_t column_start = 0;
+ u8* pch_end;
CALLOC(line, u8, BUFSIZE);
@@ -574,7 +610,7 @@ do_input:
if (!*line && lineno != 0)
goto empty_line;
- quote = 0;
+ in_quote = 0;
pline = line;
colno = 0;
current_rune_column = 0;
@@ -718,97 +754,109 @@ not_first:
do_line:
if (!pline || !*pline)
- goto done_line;
+ {
+ if (in_quote)
+ {
+ printf("\n");
+ return error(EINVAL, "Unmatched quote");
+ }
+ else
+ goto done_line;
+ }
- if (*pline == '"')
+ if (in_quote && *pline == '"' && *(pline + 1) == '"')
{
- quote = !quote;
pline++;
colno++;
+ goto continue_line;
}
- else
+ else if (quotes == Q_PROCESS && *pline == '"')
+ {
+ in_quote = !in_quote;
+ pline++;
+ colno++;
+ goto do_line;
+ }
+
+continue_line:
+ u8_char_to_u32(&uch, pline, &ch_len);
+ if (uch == delimiter && !in_quote
+ && current_table_column < table_columns - 1)
{
- u8* pch_end;
- u8_char_to_u32(&uch, pline, &ch_len);
- if (ch_len <= 0)
+ if (handle_ansi && lineno == 0)
+ printf("%s", ANSI_SGR_BOLD_OFF);
+
+ while (within_column(column_start))
{
- if (within_column(column_start))
- {
- printf("%c", *pline++);
- current_rune_column++;
- }
- colno++;
+ printf(" ");
+ current_rune_column++;
}
- else if (uch == (u32)L'\t' && expand_tabs)
+ column_start++;
+ if (format)
+ column_start += *(format + current_table_column);
+ else
+ column_start += format_value;
+ if (current_table_column != table_columns - 1)
{
- while (within_column(column_start))
- {
- printf(" ");
- current_rune_column++;
- if (current_rune_column % tab_length == 0)
- break;
- }
- pline++;
- colno++;
+ u8len = u32_char_to_u8(u8ch,
+ *table_inner_symbols[current_inner_symbol_set]
+ [1]);
+ u8ch[u8len] = 0;
+ printf("%s", u8ch);
+ current_rune_column++;
+ current_table_column++;
}
- else if (border_mode)
+
+ if (handle_ansi && lineno == 0)
+ printf("%s", ANSI_SGR_BOLD_ON);
+
+ pline += ch_len;
+ colno += ch_len;
+ }
+ else if (ch_len <= 0)
+ {
+ if (within_column(column_start))
{
- 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;
+ printf("%c", *pline++);
+ current_rune_column++;
}
- else if (uch == delimiter && !quote
- && current_table_column < table_columns - 1)
+ colno++;
+ }
+ else if (uch == (u32)L'\t' && expand_tabs)
+ {
+ while (within_column(column_start))
{
- if (handle_ansi && lineno == 0)
- printf("%s", ANSI_SGR_BOLD_OFF);
-
- while (within_column(column_start))
- {
- printf(" ");
- current_rune_column++;
- }
- column_start++;
- if (format)
- column_start
- += *(format + current_table_column);
- else
- column_start += format_value;
- if (current_table_column != table_columns - 1)
- {
- u8len = u32_char_to_u8(u8ch,
- *table_inner_symbols
- [current_inner_symbol_set][1]);
- u8ch[u8len] = 0;
- printf("%s", u8ch);
- current_rune_column++;
- current_table_column++;
- }
-
- if (handle_ansi && lineno == 0)
- printf("%s", ANSI_SGR_BOLD_ON);
-
- pline += ch_len;
- colno += ch_len;
+ printf(" ");
+ current_rune_column++;
+ if (current_rune_column % tab_length == 0)
+ break;
}
- else
+ pline++;
+ colno++;
+ }
+ else if (border_mode)
+ {
+ pch_end = pline + ch_len;
+ if (within_column(column_start))
{
- 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;
+ 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++;
}
+ pline = pch_end;
+ colno += ch_len;
}
goto do_line;