diff --git a/include/subcmds.h b/include/subcmds.h index 6fdb456..e99c66d 100644 --- a/include/subcmds.h +++ b/include/subcmds.h @@ -6,6 +6,7 @@ */ void timer_subcmd(void *, int argc, char *argv[]); +void stopwatch_subcmd(void *, int argc, char *argv[]); void subcmds_dev(void *, int argc, char *argv[]); void motd_subcmd(void *, int argc, char *argv[]); void subcmds_subcmd(void *, int argc, char *argv[]); diff --git a/lib/ds b/lib/ds index 16470f2..5e4ae41 160000 --- a/lib/ds +++ b/lib/ds @@ -1 +1 @@ -Subproject commit 16470f259286856e5c48cf02bd3b653bfaa72c9b +Subproject commit 5e4ae41113e63004bd131010853e5265b31302d3 diff --git a/src/main.c b/src/main.c index 1ba379a..54b91e5 100644 --- a/src/main.c +++ b/src/main.c @@ -96,6 +96,7 @@ main(int argc, char *argv[]) /* setup for subcommands */ register_subcmd("motd", motd_subcmd, NULL); register_subcmd("timer", timer_subcmd, NULL); + register_subcmd("stopwatch", stopwatch_subcmd, NULL); register_subcmd("subcmds", subcmds_subcmd, NULL); register_subcmd("dev", subcmds_dev, NULL); diff --git a/src/subcmds/clock.c b/src/subcmds/clock.c index 8c8ac66..7d28eb7 100644 --- a/src/subcmds/clock.c +++ b/src/subcmds/clock.c @@ -1,15 +1,21 @@ +#include #include +#include #include #include #include #include #include #include +#include +#include #include #include +#include "log.h" #include "util.h" #include "subcmds.h" +#include "ds.h" #define S_AS_MSEC 1000000 #define PB_LEN 30 @@ -29,7 +35,24 @@ } \ } while (0) -int i, total_delay_s; +int i, total_delay_s, up = 0; +struct termios oldt; + +static void +termios_noecho(void) +{ + struct termios newt; + tcgetattr(STDIN_FILENO, &oldt); + newt = oldt; + newt.c_lflag &= ~(ECHO); + tcsetattr(STDIN_FILENO, TCSANOW, &newt); +} + +static void +termios_restore(void) +{ + tcsetattr(STDIN_FILENO, TCSANOW, &oldt); +} /** * @brief convert a time to a string in seconds ie: @@ -244,6 +267,124 @@ timer_subcmd(void *, int argc, char *argv[]) } static void +stopwatch_exit(void) +{ + char *time_str; + time_t t; + struct tm tm; + + termios_restore(); + printf("\033[?25h"); + + time_str = sec2str(i); + t = time(NULL); + tm = *localtime(&t); + printf( + "\033[%dA\033[43;30;1m wom stopwatch \033[0m %s elapsed at %d/%02d/%02d %02d:%02d:%02d\n", + 3 + up, + time_str, + tm.tm_year + 1900, + tm.tm_mon + 1, + tm.tm_mday, + tm.tm_hour, + tm.tm_min, + tm.tm_sec + ); + free(time_str); +} + +static void +stopwatch_sig_exit(int sig) +{ + puts("\n"); + stopwatch_exit(); + exit(sig); +} + +void stopwatch_subcmd(void *, int argc, char *argv[]) { + int j, k, wi, pl; + char *pb_elapsed, *pb_left, *time_str, buf[PATH_MAX]; + ds_dll_t *laps; + struct pollfd pfd = { + .fd = stdin->_fileno, + .events = POLLIN, + .revents = 0 + }; + + /* disable terminal echoing */ + termios_noecho(); + atexit(stopwatch_exit); + signal(SIGINT, stopwatch_sig_exit); + + /* create the progress bar */ + pb_left = calloc(strlen(PB_FULL), sizeof(char) + 1); + strcpy(pb_left, PB_FULL); + pb_elapsed = calloc(strlen(PB_FULL), sizeof(char) + 1); + + /* initalizie the linked list */ + laps = ds_dll_init(); + + /* render ui */ + printf("\033[?25l"); + puts(""); + + for (j = i = 0;; i++) { + pl = poll(&pfd, 1, 0); + if (pl < 0) { + log_trace("pl: %d", pl); + /* TODO: error */ + exit(1); + } + + if (i != 0) { + printf("\033[%dA", 2 + (up > 0 ? up + 1 : 0)); + } + + if (pfd.revents & POLLIN) { + read(pfd.fd, buf, PATH_MAX); + ds_dll_insert(laps, (void *)(long)i); + up++; + } + + printf("\033[2K\033[43;30;1m wom stopwatch \033[0m \033[33m%s\033[30m%s\033[0m\n", pb_elapsed, pb_left); + time_str = sec2str(i); + printf("\033[2K\033[90m %s\033[0m\n", time_str); + free(time_str); + + if (up) { + printf("\033[2K\033[0m lap time\033[0m\n"); + } + k = 1; + for (ds_dll_t *cur = laps; cur; cur = cur->next, k++) { + if ((int)(long)cur->data) { + time_str = sec2str((int)(long)cur->data); + printf("\033[2K\033[0m %03d %s\033[0m\n", k, time_str); + free(time_str); + } + } + + /* change the progress bar */ + if (i % 2 == 1) { + if (i % 60 == 1) { + strcpy(pb_left, PB_FULL); + bzero(pb_elapsed, strlen(PB_FULL)); + j = 0; + } + wi = strlen(PB_FULL) - (j * strlen("┃")) - strlen("┃"); + strncat(pb_elapsed, "┃", strlen(PB_FULL)); + pb_left[wi] = '\0'; + j++; + } + + sleep(1); + } + + printf("\033[?25h"); + + free(pb_left); + free(pb_elapsed); + + return; }