slweb

Једноставни генератор статичких веб страна
git clone https://git.sr.ht/~strahinja/slweb
Дневник | Датотеке | Референце | ПРОЧИТАЈМЕ | ЛИЦЕНЦА

чување c15bc34aac15891e81a82821ee93bfb0f203929f
родитељ d4ee9a453c59abeb98daede3fea017c0d6b165a0
Аутор: Страхиња Радић <contact@strahinja.org>
Датум:   Sun, 28 Apr 2024 20:20:00 +0200

Add {csv-count} and {tsv-count}; set input_dirname even for stdin

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

Diffstat:
Mslweb.1.in | 12++++++++++--
Mslweb.c | 92++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
измењених датотека: 2, додавања: 94(+), брисања: 10(-)

diff --git a/slweb.1.in b/slweb.1.in @@ -830,7 +830,8 @@ for \fCposts/blog-post.slw\fR. . .IP \[bu] .BR "TSV/CSV templating" . -Directive \fC{tsv "\f[CI]tsvfile\fC" \f[CI]iter\fC}{/tsv}\fR marks a template. +Directive \fC{tsv "\f[CI]tsvfile\f[CR]" \f[CI]iter\f[CR]}{/tsv}\fR marks a +template. Whatever is between \fC{tsv}\fR and \fC{/tsv}\fR will be processed by .B slweb and collected as a template. Afterwards, file \fItsvfile.tsv\fR will be read and @@ -921,6 +922,13 @@ thousands of units sold (for $) were as follows: .SM TSV directives can't be nested and doing so will produce an error. . +.IP "" 4 +The directives \f[CR]{csv\-count "\f[CI]csvfile\f[CR]"}\fR and \f[CR]{tsv\-count +"\f[CI]tsvfile\f[CR]"}\fR output the number of \[lq]records\[rq] in the file +\fIcsvfile.csv\fR or \fItsvfile.tsv\fR (number of lines minus one for the header +row). +No newline is output following the number. +. .SS Special YAML variables . .IP \[bu] 4 @@ -1060,7 +1068,7 @@ containing a list of values to be inserted into meta tags. The first row of this TSV file is treated as the header row and ignored. First column in this TSV file contains the meta variable names, and the second column contains meta variable values. For each row, a \fC<meta name="\f[CI]firstcol\fC" -content="\f[CI]secondcol\fC">\fR is inserted, where +content="\f[CI]secondcol\f[CR]">\fR is inserted, where .I firstcol is the first column, and .I secondcol diff --git a/slweb.c b/slweb.c @@ -974,6 +974,11 @@ int process_tsv(FILE* output, const u8* arg_token, const int read_yaml_macros_and_links, const int end_tag) { + u8* saveptr = NULL; + u8* args = NULL; + size_t args_len; + u8* args_base = NULL; + if (end_tag) { state &= ~ST_TSV_BODY; @@ -999,20 +1004,18 @@ process_tsv(FILE* output, const u8* arg_token, if (read_yaml_macros_and_links) return 0; - tsv_iter = 0; - u8* saveptr = NULL; - u8* args = (u8*)strtok_r((char*)arg_token, " ", - (char**)&saveptr); - args = (u8*)strtok_r(NULL, " ", (char**)&saveptr); + tsv_iter = 0; + args = (u8*)strtok_r((char*)arg_token, " ", (char**)&saveptr); + args = (u8*)strtok_r(NULL, " ", (char**)&saveptr); if (!args) exit(error(EINVAL, (u8*)"tsv: Arguments required")); - size_t args_len = strlen((char*)args); + args_len = strlen((char*)args); if (*args != '"' || *(args + args_len - 1) != '"') exit(error(EINVAL, (u8*)"tsv: First argument must be a string")); if (!tsv_filename) CALLOC(tsv_filename, u8, BUFSIZE); - u8* args_base = (u8*)strdup((char*)args + 1); + args_base = (u8*)strdup((char*)args + 1); *(args_base + strlen((char*)args_base) - 1) = 0; snprintf(tsv_filename, BUFSIZE, "%s/%s.tsv", input_dirname, (char*)args_base); @@ -1032,6 +1035,72 @@ process_tsv(FILE* output, const u8* arg_token, return 0; } +int +process_tsv_count(FILE* output, const u8* arg_token, + const int read_yaml_macros_and_links, const int is_tsv) +{ + FILE* tsv = NULL; + u8* saveptr = NULL; + u8* args = NULL; + size_t args_len; + u8* args_base = NULL; + char* bufline = NULL; + size_t tsv_lines = 0; + + if (read_yaml_macros_and_links) + return 0; + + tsv_iter = 0; + + args = (u8*)strtok_r((char*)arg_token, " ", (char**)&saveptr); + args = (u8*)strtok_r(NULL, " ", (char**)&saveptr); + if (!args) + exit(error(EINVAL, (u8*)"%csv-count: Arguments required", + is_tsv ? 't' : 'c')); + args_len = strlen((char*)args); + if (*args != '"' || *(args + args_len - 1) != '"') + exit(error(EINVAL, + (u8*)"%csv-count: First argument must be a string", + is_tsv ? 't' : 'c')); + if (!tsv_filename) + CALLOC(tsv_filename, u8, BUFSIZE); + args_base = (u8*)strdup((char*)args + 1); + *(args_base + strlen((char*)args_base) - 1) = 0; + snprintf(tsv_filename, BUFSIZE, "%s/%s.%csv", input_dirname, + (char*)args_base, is_tsv ? 't' : 'c'); + free(args_base); + + // output, tsv_filename, print_tsv_row + if (!(tsv = fopen(tsv_filename, "rt"))) + exit(error(ENOENT, (u8*)"%csv-count: No such file: %s", + is_tsv ? 't' : 'c', tsv_filename)); + + CALLOC(bufline, char, BUFSIZE); + + while (!feof(tsv)) + { + char* eol = NULL; + if (!fgets(bufline, BUFSIZE, tsv)) + break; + eol = strchr(bufline, '\n'); + if (eol) + { + *eol = 0; + tsv_lines++; + } + } + fclose(tsv); + + /* And take back one kadam for the header row */ + print_output(output, "%ld", tsv_lines - 1); + + free(bufline); + free(tsv_filename); + tsv_filename = NULL; + + return 0; +} + #define PRINTCSVIF(format, arg) \ do \ { \ @@ -2175,9 +2244,13 @@ process_tag(FILE* output, const u8* token, const char* source_filename, { process_git_log(output); } + else if (startswith((char*)token, "csv-count")) /* {csv-count} */ + process_tsv_count(output, token, read_yaml_macros_and_links, 0); else if (startswith((char*)token, "csv")) /* {csv} */ process_csv(output, token, read_yaml_macros_and_links, end_tag); - else if (startswith((char*)token, "tsv")) /* {csv} */ + else if (startswith((char*)token, "tsv-count")) /* {tsv-count} */ + process_tsv_count(output, token, read_yaml_macros_and_links, 1); + else if (startswith((char*)token, "tsv")) /* {tsv} */ process_tsv(output, token, read_yaml_macros_and_links, end_tag); else if (startswith((char*)token, "include")) /* {include} */ { @@ -5630,6 +5703,9 @@ main(const int argc, const char** argv) input = stdin; + CALLOC(input_dirname, char, 2); + *input_dirname = '.'; + CALLOC(bufline, u8, BUFSIZE); buffer_size = BUFSIZE; CALLOC(buffer, u8, buffer_size);