commit bae29417270798f60d0348c22cd9fb21b5f3d8f8
parent 6cb461a040f4b53f0f01421da92007fc682a7310
Author: Louis Burda <quent.burda@gmail.com>
Date: Tue, 22 Jun 2021 00:05:34 +0200
Added preview of next line and fixed input parsing
Diffstat:
M | main.c | | | 61 | ++++++++++++++++++++++++++++++++++++++++++------------------- |
1 file changed, 42 insertions(+), 19 deletions(-)
diff --git a/main.c b/main.c
@@ -36,11 +36,13 @@ enum {
STYLE_MAGENTA_FG = 35,
STYLE_CYAN_FG = 36,
STYLE_WHITE_FG = 37,
+ STYLE_GREY_FG = 90,
};
static const int style_wrong[] = { STYLE_RED_FG, STYLE_BOLD, STYLE_END };
static const int style_right[] = { STYLE_GREEN_FG, STYLE_END };
static const int style_reset[] = { STYLE_RESET, STYLE_END };
+static const int style_preview[] = { STYLE_GREY_FG, STYLE_END };
struct termios oldt;
@@ -53,7 +55,7 @@ die(const char *fmtstr, ...)
va_list ap;
va_start(ap, fmtstr);
- vprintf(fmtstr, ap);
+ vfprintf(stderr, fmtstr, ap);
va_end(ap);
exit(EXIT_FAILURE);
@@ -84,22 +86,20 @@ time_sub(struct timespec *new, struct timespec *old)
}
int
-type(const char *text)
+type(const char *text, const char *preview)
{
char input[1024];
int c, right, wrong, tlen;
struct timespec start = { 0 }, end;
float cps;
- printf("%s", text);
-
tlen = strlen(text);
- right = wrong = 0;
- while ((c = getchar()) > 0) {
- printf("\x1b[2K"); /* clear line */
- printf("\r"); /* cursor to beginning of line */
+ c = right = wrong = 0;
+ do {
+ printf("\r\x1b[2K"); /* goto beginning of row and clear */
+ printf("\x1b[1A\x1b[2K"); /* up a row and clear */
- if (!start.tv_sec)
+ if (c && !start.tv_sec)
clock_gettime(CLOCK_REALTIME, &start);
switch (c) {
@@ -108,9 +108,10 @@ type(const char *text)
return 1;
case C_DEL:
if (wrong) wrong--;
- else right--;
+ else if (right) right--;
break;
case u'\n':
+ case u'\0':
break;
default:
if (right + wrong == tlen) break;
@@ -127,8 +128,12 @@ type(const char *text)
print_style(style_reset);
printf("%.*s", tlen - right - wrong, text + right + wrong);
+ print_style(style_preview);
+ printf("\n\r%s", preview);
+ print_style(style_reset);
+
if (!wrong && right + wrong == tlen) break;
- }
+ } while ((c = getchar()) > 0);
clock_gettime(CLOCK_REALTIME, &end);
time_sub(&end, &start);
@@ -137,7 +142,22 @@ type(const char *text)
if (!typed) gcps = cps;
else gcps = LINTERP(gcps, cps, typed * 1.f / (typed + tlen));
- printf("\n\r");
+ return 0;
+}
+
+int
+getl(FILE *f, char *buf, size_t size)
+{
+ int i;
+
+ do {
+ if (!fgets(buf, size, f))
+ return 1;
+
+ for (i = strlen(buf) - 1; *buf; buf[i--] = '\0')
+ if (!strchr("\n\r", buf[i])) break;
+ } while (!*buf);
+
return 0;
}
@@ -151,7 +171,8 @@ int
main(int argc, const char **argv)
{
struct termios t;
- char linebuf[256];
+ char cur[256], next[256];
+ int eof;
FILE *f;
if (argc < 2)
@@ -170,12 +191,14 @@ main(int argc, const char **argv)
if (!tcsetattr(0, TCSANOW, &t)) atexit(reset);
- while (fgets(linebuf, sizeof(linebuf), f) > 0) {
- if (!*linebuf) break;
- if (linebuf[strlen(linebuf)-1] == '\n')
- linebuf[strlen(linebuf)-1] = '\0';
- if (!*linebuf) continue;
- if (type(linebuf)) break;
+ if (getl(f, next, sizeof(next)))
+ die("Empty input file\n");
+
+ printf("\n");
+ for (eof = 0; !eof; ) {
+ memcpy(cur, next, sizeof(cur));
+ eof |= getl(f, next, sizeof(next));
+ if (type(cur, eof ? "" : next)) break;
}
printf("CPM: %0.2f\n\r", gcps * 60);