From 147932ae2da02b5eceb6be6e1d704e1199bcb72e Mon Sep 17 00:00:00 2001 From: Lukasz Kasprzak Date: Fri, 21 Aug 2026 09:51:36 +0200 Subject: fix(colitur-x): detect the CSV header instead of assuming it Skipping the first line unconditionally punished the obvious way to view one month -- colitur emit --format csv ... | grep '^2027-04' | colitur-x -- by silently eating 1 April, because grep had already removed the header the program still expected. A filter is exactly what this program should compose with. A header is the line beginning 'date,'; anything else is a day. Verified all three ways: full year with header 365 rows from 01-01, a grepped month without header 30 rows from 04-01, and the old head -1 incantation still 30 rows. --- colitur-x.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'colitur-x.c') diff --git a/colitur-x.c b/colitur-x.c index def42fa..06f2f1a 100644 --- a/colitur-x.c +++ b/colitur-x.c @@ -55,15 +55,28 @@ static int split(char *line, char **out) return n; } +/* The header line is DETECTED, not assumed. Skipping the first line + unconditionally punishes the obvious way to look at one month -- + `... | grep "^2027-04" | colitur-x` -- by silently eating the 1st, + which is a filter this program should compose with rather than fight. + A header is exactly the line beginning "date,"; anything else is a day. */ +static int is_header(const char *line) +{ + return strncmp(line, "date,", 5) == 0; +} + static void load(void) { char buf[4096]; - if (!fgets(buf, sizeof buf, stdin)) return; /* header */ + int first = 1; while (nrows < MAXDAYS && fgets(buf, sizeof buf, stdin)) { buf[strcspn(buf, "\n")] = 0; + if (first && is_header(buf)) { first = 0; continue; } + first = 0; + if (buf[0] == 0) continue; char *dup = strdup(buf); if (!dup) break; - if (split(dup, rows[nrows].f) >= 12) nrows++; + if (split(dup, rows[nrows].f) >= 12) nrows++; else free(dup); } } -- cgit v1.3