commit 2bb5384da11a7487e29b2354c8e5a00dcefea2c3
parent 4f3c7fe232f50f0ea15a2aeab7ba910f0276eaa7
Author: Remy Noulin <loader2x@gmail.com>
Date: Sat, 5 Jun 2021 16:09:56 +0200
add option bar to show barchart instead of plot
README.md | 7 ++-
git-stats.c | 183 ++++++++++++++++++++++++++++++++++++++++--------------------
2 files changed, 128 insertions(+), 62 deletions(-)
Diffstat:
| M | README.md | | | 7 | ++++++- |
| M | git-stats.c | | | 183 | +++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------- |
2 files changed, 128 insertions(+), 62 deletions(-)
diff --git a/README.md b/README.md
@@ -1,4 +1,9 @@
-This version creates a plot:
+This version adds the option 'bar' to show a barchart instead of a dot plot
+
+git-stats bar
+git-stats 2021 bar
+
+commit 4f3c7fe232f50f0ea15a2aeab7ba910f0276eaa7 creates a plot:
50┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
⡧
diff --git a/git-stats.c b/git-stats.c
@@ -21,8 +21,7 @@ typ struct {u16 rows; u16 cols;} winSizet;
#include <unistd.h>
// get terminal window size
-winSizet wsize (void)
-{
+winSizet wsize (void) {
struct winsize w;
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
@@ -32,7 +31,7 @@ winSizet wsize (void)
time_t earliest, latest;
char *firstDate = null, *lastDate = null;
-void drawGraph(char *from, char *gitopts, bool setTimeRange) {
+void drawGraph(char *from, char *gitopts, bool setTimeRange, bool barchart) {
// Steps
// get git statistics
@@ -54,6 +53,7 @@ void drawGraph(char *from, char *gitopts, bool setTimeRange) {
sortG(&dates);
char *ld = getG(dates, unusedV, -1);
+ if (!ld) /*dates is empty, stop.*/ return;
ld[4] = 0;
if (parseInt(ld) < parseInt(from)) /* the last date is earlier than from, stop. */ return;
ld[4] = '-';
@@ -149,7 +149,11 @@ void drawGraph(char *from, char *gitopts, bool setTimeRange) {
sliceForEach(&slDates, date) {
time_t t = strToUnixTime(date->date, "%Y-%m-%d");
- int col = (f64)(t-earliest)/(f64)(latest-earliest) * (f64)(wz.cols*2-1/*-1 to make sure it writes inside the display*/);
+ int col;
+ if (barchart)
+ col = (f64)(t-earliest)/(f64)(latest-earliest) * (f64)(wz.cols-1/*-1 to make sure it writes inside the display*/);
+ else
+ 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);
}
@@ -162,66 +166,107 @@ void drawGraph(char *from, char *gitopts, bool setTimeRange) {
sliceAppend(&slPl, p);
// create a blank display array
+ // create a blank display array
+ char *display[wz.cols][graphHeight];
+
+ char *BARS[] = {" ", "▁", "▂", "▃", "▄", "▅", "▆", "▇", "█"};
+
u32 dotDisplay[wz.cols][graphHeight];
- // clear dotDisplay
- range(i, wz.cols) {
- range(j, graphHeight) {
- dotDisplay[i][j] = ' ';
+ if (barchart) {
+ // clear display
+ range(i, wz.cols) {
+ range(j, graphHeight) {
+ display[i][j] = BARS[0];
+ }
}
}
-
- // 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;
+ else {
+ // clear dotDisplay
+ range(i, wz.cols) {
+ range(j, graphHeight) {
+ dotDisplay[i][j] = ' ';
+ }
+ }
}
- 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 (barchart) {
+ // 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;
}
- if (e2 <= dx) {
- // e_xy+e_y < 0
- err += dx;
- y0 += sy;
+
+ rangeFrom(i, h, graphHeight) {
+ display[elm->col][i] = BARS[8];
}
+
+ //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);
}
}
+ else {
+ // 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;
+ }
+
+ 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;
+ }
+ }
+ }
- // 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);
+ // 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 %d, value %d", elm->col, elm->value);
}
// show plot
@@ -235,13 +280,23 @@ void drawGraph(char *from, char *gitopts, bool setTimeRange) {
printf(HORIZONTAL_DASH);
}
put;
- range(j, graphHeight) {
- range(i, wz.cols) {
- char dots[10] = {0};
- bRune2CodeUTF8(dots, dotDisplay[i][j]);
- printf(BLD"%s"RST, dots);
+ if (barchart) {
+ range(j, graphHeight) {
+ range(i, wz.cols) {
+ printf(display[i][j]);
+ }
+ put;
+ }
+ }
+ else {
+ range(j, graphHeight) {
+ range(i, wz.cols) {
+ char dots[10] = {0};
+ bRune2CodeUTF8(dots, dotDisplay[i][j]);
+ printf(BLD"%s"RST, dots);
+ }
+ put;
}
- put;
}
range(i, wz.cols) {
printf(HORIZONTAL_DASH);
@@ -276,12 +331,18 @@ int main(int ARGC, char** ARGV) {
//disableLibsheepyErrorLogs;
- char *from = null;
+ char *from = null;
+ bool barchart = no;
if (argc > 1) {
- from = argv[1];
+ if (isInt(argv[1])) {
+ from = argv[1];
+ barchart = argv[2] and eqG(argv[2], "bar");
+ }
+ else
+ barchart = argv[1] and eqG(argv[1], "bar");
}
- drawGraph(from, "", /*setTimeRange*/ yes);
+ drawGraph(from, "", /*setTimeRange*/ yes, barchart);
// get list of authors
// git shortlog -sn
@@ -292,7 +353,7 @@ int main(int ARGC, char** ARGV) {
forEachS(authors, l) {
puts(&l[7]);
cleanCharP(auth) = formatS("--author=\"%s\"", &l[7]);
- drawGraph(from, auth, /*setTimeRange*/ no);
+ drawGraph(from, auth, /*setTimeRange*/ no, barchart);
}
freeManyS(firstDate, lastDate);