commit 268b91a3214f8035721190e5fe8016f6f0a0d513
parent e2facf9d06fe71e5992132faedcb80f2aac97901
Author: Remy Noulin <loader2x@gmail.com>
Date: Fri, 4 Jun 2021 21:54:13 +0200
display plot with braille dots
add from date argument
git-stats.c | 122 +++++++++++++++++++++++++++++++++++++++++++++++-------------
1 file changed, 96 insertions(+), 26 deletions(-)
Diffstat:
| M | git-stats.c | | | 122 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------- |
1 file changed, 96 insertions(+), 26 deletions(-)
diff --git a/git-stats.c b/git-stats.c
@@ -52,14 +52,29 @@ int main(int ARGC, char** ARGV) {
// fill the display with the plot
// show plot
+ char *from = null;
+ if (argc > 1) {
+ from = argv[1];
+ }
+
// get git statistics
cleanListP(dates) = execOut("git log --pretty=format:\"%ai\"");
- var c = lenG(dates);
-
// sort the dates
sortG(&dates);
+ int cut = 0;
+ enumerateS(dates, s, i) {
+ if (startsWithG(s, from)) {
+ cut = i;
+ break;
+ }
+ }
+
+ if (cut) {
+ delG(&dates, 0, cut);
+ }
+
// remove time, keep only the date in a slice: slDates
// count daily commits
typ struct {
@@ -131,7 +146,7 @@ int main(int ARGC, char** ARGV) {
sliceForEach(&slDates, date) {
time_t t = strToUnixTime(date->date, "%Y-%m-%d");
- int col = (f64)(t-earliest)/(f64)(latest-earliest) * (f64)(wz.cols-1/*-1 to make sure it writes inside the display*/);
+ int col = (f64)(t-earliest)/(f64)(latest-earliest) * (f64)(wz.cols*2-1/*-1 to make sure it writes inside the display*/);
if (col == p.col) {
p.value = MAX(date->count, p.value);
}
@@ -144,48 +159,103 @@ int main(int ARGC, char** ARGV) {
sliceAppend(&slPl, p);
// create a blank display array
- char *display[wz.cols][graphHeight];
+ u32 dotDisplay[wz.cols][graphHeight];
- char *BARS[] = {" ", "▁", "▂", "▃", "▄", "▅", "▆", "▇", "█"};
-
- // clear display
+ // clear dotDisplay
range(i, wz.cols) {
range(j, graphHeight) {
- display[i][j] = BARS[0];
+ dotDisplay[i][j] = ' ';
}
}
+ // for more information about braille, see:
+ // https://en.wikipedia.org/wiki/Braille_Patterns
+ const u32 brailleOffset = 0x2800;
+ const u32 braille[4][2] = {
+ {0x01, 0x08},
+ {0x02, 0x10},
+ {0x04, 0x20},
+ {0x40, 0x80},
+ };
+
+ void setPoint(i32 x, i32 y) {
+ dotDisplay[x/2][y/4] |= braille[y%4][x%2] + brailleOffset;
+ }
- // fill the display with the plot
- sliceForEach(&slPl, elm) {
- int dpHeight = (f64)(graphHeight*8) - (f64)elm->value/(f64)maxCount * (f64)(graphHeight*8);
- int bits = dpHeight & 7;
- int cbar = 8 - bits;
-
- // draw bar
- int h = dpHeight / 8;
-
- if (bits) {
- // print BARS[cbar]
- display[elm->col][h] = BARS[cbar];
- inc h;
+ void line(i32 x0, i32 y0, i32 x1, i32 y1) {
+ // bresenham's line algorithm
+ // https://en.wikipedia.org/wiki/Bresenham's_line_algorithm
+ i32 dx = abs(x1-x0);
+ i32 sx = x0<x1 ? 1 : -1;
+ i32 dy = -abs(y1-y0);
+ i32 sy = y0<y1 ? 1 : -1;
+ // error value e_xy
+ i32 err = dx+dy;
+ loopBreakerInit;
+ forever {
+ loopBreaker(10000);
+ setPoint(x0, y0);
+ if (x0 == x1 and y0 == y1) break;
+ i32 e2 = 2*err;
+ if (e2 >= dy) {
+ // e_xy+e_x > 0
+ err += dy;
+ x0 += sx;
+ }
+ if (e2 <= dx) {
+ // e_xy+e_y < 0
+ err += dx;
+ y0 += sy;
+ }
}
+ }
- rangeFrom(i, h, graphHeight) {
- display[elm->col][i] = BARS[8];
- }
+ // fill the display with the plot
+ sliceEnumerate(&slPl, sli, elm) {
+ if (sli > 0) {
+ int dpHeight = (f64)(graphHeight*4) - (f64)elm->value/(f64)maxCount * (f64)(graphHeight*4);
+ int prevHeight = (f64)(graphHeight*4) - (f64)sliceAt(&slPl,sli-1).value/(f64)maxCount * (f64)(graphHeight*4);
+ line(sliceAt(&slPl,sli-1).col, prevHeight, elm->col, dpHeight);
+ }
//logI("col %d, value %d", elm->col, elm->value);
- //logI("col %3d, value %4d %3d cbar %d bits %d", elm->col, dpHeight, h, cbar, bits);
}
// show plot
+ char maxC[20] = {0};
+ snprintf(maxC, sizeof(maxC), "%d", maxCount);
+ var ln = strlen(maxC);
+ snprintf(maxC, sizeof(maxC), BLD"%d"RST, maxCount);
+ #define HORIZONTAL_DASH "┈"
+ printf(maxC);
+ rangeFrom(i, ln, wz.cols) {
+ printf(HORIZONTAL_DASH);
+ }
+ put;
range(j, graphHeight) {
range(i, wz.cols) {
- printf(display[i][j]);
+ char dots[10] = {0};
+ bRune2CodeUTF8(dots, dotDisplay[i][j]);
+ printf(BLD"%s"RST, dots);
}
put;
}
+ range(i, wz.cols) {
+ printf(HORIZONTAL_DASH);
+ }
+ put;
+ int col = strlen(sliceFirst(&slDates).date);
+ printf(BLD"%s"RST, sliceFirst(&slDates).date);
+ time_t halfTime = (earliest+latest)/2;
+ char hT[5];
+ bLTimeToYMDS(hT, sizeof(hT), halfTime);
+ int spaces = (wz.cols/2-2)-col;
+ col += spaces + 4 /*halfTime string length*/;
+ range(i, spaces) printf(" ");
+ printf(BLD"%s"RST, hT);
+ spaces = wz.cols - strlen(sliceLast(&slDates).date) - col;
+ range(i, spaces) printf(" ");
+ printf(BLD"%s"RST, sliceLast(&slDates).date);
sliceFree(&slPl);