#include #include #include #include #include #include #include double atime() { struct timespec now; clock_gettime(CLOCK_REALTIME, &now); return now.tv_sec + now.tv_nsec * 1e-9; } int main() { double *wt; int c, l, t, ttyfd, wi, *wl, ws; struct termios orig, raw; ws = 100; /* allocated number of words */ wl = malloc(ws * sizeof(int)); /* word lengths */ if (wl == NULL) err(1, "malloc"); wt = malloc(ws * sizeof(double)); /* word times */ if (wt == NULL) err(1, "malloc"); for (int i = 0; i < ws; i++) wt[i] = 0; l = 0; /* current word length */ wi = -1; /* index of current word in order */ /* enter "raw" mode */ ttyfd = open("/dev/tty", O_RDWR); if (ttyfd == -1) err(1, "open"); tcgetattr(ttyfd, &orig); raw = orig; raw.c_lflag &= ~(ECHO | ICANON); tcsetattr(ttyfd, TCSANOW, &raw); /* read loop */ while (read(ttyfd, &c, 1)) { /* backspace */ if (c == 127) { l--; write(ttyfd, &c, 1); if (l == -1) { wi--; fprintf(stderr, "<\n"); } continue; } /* back to previous word (after backspace) */ if (l == -1) { l = wl[wi]; fprintf(stderr, "%d\n", wl[wi-1]); } /* new word */ if (c != ' ' && c != '\n' && (l == 0 || l == -1)) { wi++; t = atime(); /* current word start time */ fprintf(stderr, "*\n"); } /* end word */ if (c == ' ' || c == '\n') { wl[wi] = l; if (t > -1) { wt[wi] += atime() - t; // fprintf(stderr, "[+%f]", atime() - t); } l = 0; t = -1; } else l++; if (c == '\n') break; write(ttyfd, &c, 1); } write(ttyfd, "\n", 1); /* print statistics */ double tt = 0; int tl = 0; for (int i = 0; i <= wi; i++) { tt += wt[i]; tl += wl[i]; } printf("%f seconds per word (%d)\n", tt / (wi + 1), wi + 1); printf("%f seconds per word character (%d)\n", tt / tl, tl); /* restore original terminal settings */ tcsetattr(ttyfd, TCSANOW, &orig); }