make plootxt draw an empty grid - ploot - simple plotting tools | |
git clone git://bitreich.org/ploot git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65… | |
Log | |
Files | |
Refs | |
Tags | |
README | |
LICENSE | |
--- | |
commit 97913fd518557ed58a07f52204fef1271af2bb32 | |
parent 817580dbf249b75e747cc81f56f930d80600c59e | |
Author: Josuah Demangeon <[email protected]> | |
Date: Mon, 7 May 2018 01:10:39 +0200 | |
make plootxt draw an empty grid | |
Diffstat: | |
M ploot.c | 2 ++ | |
M plootxt.c | 199 +++++++++++++++++++----------… | |
A test.csv | 30 ++++++++++++++++++++++++++++++ | |
3 files changed, 157 insertions(+), 74 deletions(-) | |
--- | |
diff --git a/ploot.c b/ploot.c | |
@@ -110,6 +110,8 @@ read_values(Vlist *v, int ncol) | |
bufsize = 0; | |
for (nval = 0; esfgets(line, sizeof(line), stdin) != NULL; nval++) | |
bufsize = add_row(v, bufsize, ncol, nval, line); | |
+ if (nval == 0) | |
+ fputs("no value could be read\n", stderr), exit(1); | |
} | |
static void | |
diff --git a/plootxt.c b/plootxt.c | |
@@ -12,72 +12,46 @@ | |
#define LEN(x) (sizeof(x) / sizeof(*x)) | |
#define WIDTH_MAX 1024 | |
+#define BRAILLE_START 10240 | |
-int screenwidth = 80; | |
+int wflag = 80; | |
char *argv0; | |
-static void | |
-usage(void) | |
-{ | |
- fprintf(stderr, "usage: %s <csv\n", argv0); | |
- exit(1); | |
-} | |
- | |
-void | |
-fmt_labels(char out[LINE_MAX], int ncol, char *labels[LINE_MAX / 2]) | |
-{ | |
- int i, w; | |
- | |
- w = screenwidth / ncol; | |
- for (i = 0; i < ncol; labels++, i++) | |
- out += snprintf(out, w - 1, " %.*s", w - 1, *labels); | |
-} | |
- | |
/* | |
- * Label must be able to store all pointers to token buf has to | |
- * offer: sizeof(*buf / 2). | |
+ * Turn the bit at position (row, col) on in the . | |
*/ | |
-static int | |
-read_labels(char out[LINE_MAX]) | |
+static void | |
+plot_dot(long *out, int row, int col) | |
{ | |
- int ncol; | |
- char *l, line[LINE_MAX], *labels[LINE_MAX / 2], *tok; | |
- | |
- l = line; | |
- if (esfgets(line, LINE_MAX, stdin) == NULL) | |
- fputs("missing label line\n", stderr), exit(1); | |
- | |
- if (strcmp(strsep(&l, ","), "epoch") != 0) | |
- fputs("first label must be \"epoch\"\n", stderr), exit(1); | |
- | |
- for (ncol = 1; (tok = strsep(&l, ",")) != NULL; ncol++) | |
- *labels = tok; | |
- *labels = NULL; | |
- | |
- if (ncol < 2) | |
- fputs("no label found\n", stderr), exit(1); | |
- | |
- fmt_labels(out, ncol, labels); | |
- | |
- return ncol; | |
+ long flags[4][2] = { | |
+ { 0x01, 0x08 }, | |
+ { 0x02, 0x10 }, | |
+ { 0x04, 0x20 }, | |
+ { 0x40, 0x80 }, | |
+ }, f; | |
+ | |
+ f = flags[row][col]; | |
+ puts("."), fflush(stdout); | |
+ *out |= f; | |
} | |
-void | |
-plot_val(char *out, double val, int nrow, int width) | |
+static void | |
+plot_val(long *out, double val, double max, int row, int width) | |
{ | |
- (void)val; | |
- (void)out; | |
- (void)nrow; | |
- (void)width; | |
+ int col; | |
+ | |
+ col = (int)((double)(val * width * 2) / max); | |
+ for (; col > 0; out++, col--) | |
+ plot_dot(out + col / 2, row, col % 2); | |
} | |
/* | |
* Change the braille characters on a whole row, this for all the | |
* values line. | |
*/ | |
-time_t | |
-plot_row(char *out, char *line, int nrow, int ncol, int width) | |
+static time_t | |
+plot_row(long *out, char *line, double *max, int nrow, int ncol, int width) | |
{ | |
time_t epoch; | |
double val; | |
@@ -88,11 +62,11 @@ plot_row(char *out, char *line, int nrow, int ncol, int wid… | |
fputs("*** missing epoch value\n", stderr), exit(1); | |
epoch = eatol(tok); | |
- for (n = 1; (tok = strsep(&line, ",")) != NULL; n++) { | |
+ for (n = 0; (tok = strsep(&line, ",")) != NULL; n++) { | |
if (n >= ncol) | |
fputs("too many values\n", stderr), exit(1); | |
val = eatof(tok); | |
- plot_val(out + n * width, nrow, val, width); | |
+ plot_val(out + n * width, max[n - 1], nrow, val, width); | |
} | |
if (n < ncol) | |
fputs("not enough values\n", stderr), exit(1); | |
@@ -103,23 +77,27 @@ plot_row(char *out, char *line, int nrow, int ncol, int wi… | |
/* | |
* Read enough input in order to print one line and plot it into 'out'. | |
*/ | |
-time_t | |
-plot_line(char *out, int ncol, int width) | |
+static time_t | |
+plot_line(long *out, double *max, int ncol, int width) | |
{ | |
time_t epoch; | |
- int nrow; | |
+ int n, nrow; | |
+ long *o, rune; | |
char line[LINE_MAX]; | |
+ for (rune = BRAILLE_START, o = out, n = ncol * width; n > 0; o++, n--) | |
+ memcpy(o, &rune, sizeof(rune)); | |
+ *o = '\0'; | |
for (nrow = 0; nrow < 4; nrow++) { | |
if ((esfgets(line, LINE_MAX, stdin)) == NULL) | |
exit(0); | |
- epoch = plot_row(out, line, nrow, ncol, width); | |
+ epoch = plot_row(out, line, max, nrow, ncol, width); | |
} | |
return epoch; | |
} | |
-void | |
+static void | |
put_time(time_t epoch, time_t last, int nline) | |
{ | |
char *out, buf[sizeof("XXxXXxXX |")]; | |
@@ -141,48 +119,121 @@ put_time(time_t epoch, time_t last, int nline) | |
fputs(out, stdout); | |
} | |
-void | |
-plot(char labels[LINE_MAX], int ncol) | |
+static void | |
+print_utf8_3bytes(long rune) | |
+{ | |
+ putchar((char)(0xe0 | (0x0f & (rune >> 12)))); /* 1110xxxx */ | |
+ putchar((char)(0x80 | (0x3f & (rune >> 6)))); /* 10xxxxxx */ | |
+ putchar((char)(0x80 | (0x3f & (rune)))); /* 10xxxxxx */ | |
+} | |
+ | |
+static void | |
+put_line(long *out) | |
+{ | |
+ for (; *out != '\0'; out++) | |
+ print_utf8_3bytes(*out); | |
+ putchar('|'); | |
+ putchar('\n'); | |
+} | |
+ | |
+static void | |
+plot(char labels[LINE_MAX], double *max, int ncol) | |
{ | |
time_t epoch, last_epoch; | |
+ long out[WIDTH_MAX + 1]; | |
int n, width; | |
- char out[WIDTH_MAX * 3 + 1]; | |
- width = screenwidth / ncol; | |
+ width = (wflag - sizeof("XXxXXxXX _|")) / ncol - sizeof("|"); | |
last_epoch = epoch = 0; | |
- for (n = 0;; n++) { | |
- if (n >= 20) { | |
- puts(labels); | |
- n = 0; | |
- } | |
+ for (n = 0;; n = n == 20 ? 0 : n + 1) { | |
+ if (n == 0) | |
+ put_time(0, 0, 2), puts(labels); | |
- epoch = plot_line(out, ncol, width); | |
+ epoch = plot_line(out, max, ncol, width); | |
put_time(epoch, last_epoch, n); | |
last_epoch = epoch; | |
- puts(out); | |
+ put_line(out); | |
fflush(stdout); | |
} | |
} | |
-void | |
-parse_args(int argc, char **argv) | |
+static void | |
+fmt_labels(char out[LINE_MAX], int ncol, char *labels[LINE_MAX / 2]) | |
+{ | |
+ int i, w; | |
+ | |
+ w = wflag / ncol; | |
+ for (i = 0; i < ncol; labels++, i++) | |
+ out += snprintf(out, w - 1, " %.*s", w - 1, *labels); | |
+} | |
+ | |
+/* | |
+ * Label must be able to store all pointers to token buf has to | |
+ * offer: sizeof(*buf / 2). | |
+ */ | |
+static int | |
+read_labels(char out[LINE_MAX]) | |
+{ | |
+ int ncol; | |
+ char *l, line[LINE_MAX], **lab, *labels[LINE_MAX / 2], *tok; | |
+ | |
+ if ((l = esfgets(line, LINE_MAX, stdin)) == NULL) | |
+ fputs("missing label line\n", stderr), exit(1); | |
+ | |
+ if (strcmp(strsep(&l, ","), "epoch") != 0) | |
+ fputs("first label must be \"epoch\"\n", stderr), exit(1); | |
+ | |
+ lab = labels; | |
+ for (ncol = 0; (tok = strsep(&l, ",")) != NULL; ncol++, lab++) | |
+ *lab = tok; | |
+ *lab = NULL; | |
+ | |
+ if (ncol < 1) | |
+ fputs("no label found\n", stderr), exit(1); | |
+ | |
+ fmt_labels(out, ncol, labels); | |
+ | |
+ return ncol; | |
+} | |
+ | |
+static void | |
+usage(void) | |
{ | |
+ fprintf(stderr, "usage: %s maxval... <csv\n", argv0); | |
+ exit(1); | |
+} | |
+ | |
+static int | |
+parse_args(int argc, char **argv, double *max) | |
+{ | |
+ int n; | |
+ | |
argv0 = *argv; | |
- if (argc != 1) | |
+ argv++, argc--; | |
+ | |
+ if (argc == 0) | |
usage(); | |
+ | |
+ for (n = argc; n > 0; n--, argv++, max++) | |
+ *max = eatof(*argv); | |
+ | |
+ return argc; | |
} | |
int | |
main(int argc, char **argv) | |
{ | |
+ double max[LINE_MAX / 2]; | |
+ int ncol, nmax; | |
char labels[LINE_MAX]; | |
- int ncol; | |
- parse_args(argc, argv); | |
+ nmax = parse_args(argc, argv, max); | |
ncol = read_labels(labels); | |
- plot(labels, ncol); | |
+ if (ncol != nmax) | |
+ fputs("not as many labels and arguments\n", stderr), exit(0); | |
+ plot(labels, max, ncol); | |
return 0; | |
} | |
diff --git a/test.csv b/test.csv | |
@@ -0,0 +1,30 @@ | |
+epoch,value | |
+1525186140,34.691934 | |
+1525187040,34.405857 | |
+1525187940,32.498299 | |
+1525188840,27.619718 | |
+1525189740,30.942743 | |
+1525190640,32.813887 | |
+1525191540,32.230595 | |
+1525192440,30.917799 | |
+1525193340,31.829373 | |
+1525194240,30.912565 | |
+1525195140,32.899966 | |
+1525196040,31.234834 | |
+1525196940,31.196973 | |
+1525197840,30.626265 | |
+1525198740,30.734170 | |
+1525199640,29.900881 | |
+1525200540,28.375837 | |
+1525201440,28.976500 | |
+1525202340,27.949893 | |
+1525203240,26.158816 | |
+1525204140,23.383114 | |
+1525205040,26.615605 | |
+1525205940,30.636621 | |
+1525206840,28.831401 | |
+1525207740,29.878943 | |
+1525208640,22.641583 | |
+1525209540,30.158785 | |
+1525210440,30.718469 | |
+1525211340,30.369028 |