URI: 
       make plootxt draw an empty grid - ploot - simple plotting tools
  HTML git clone git://bitreich.org/ploot git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/ploot
   DIR Log
   DIR Files
   DIR Refs
   DIR Tags
   DIR README
   DIR LICENSE
       ---
   DIR commit 97913fd518557ed58a07f52204fef1271af2bb32
   DIR parent 817580dbf249b75e747cc81f56f930d80600c59e
  HTML Author: Josuah Demangeon <mail@josuah.net>
       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(-)
       ---
   DIR 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
   DIR 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 width)
                        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 width)
        /*
         * 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;
        }
   DIR 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