make the timer fancy
This commit is contained in:
1
include/util.h
Normal file
1
include/util.h
Normal file
@@ -0,0 +1 @@
|
||||
#define numlen(x) (x > 0 ? floor(log10(abs(x))) + 1 : 0)
|
@@ -27,10 +27,14 @@ srcfiles = files(
|
||||
'src/conf.c'
|
||||
) + luafiles + subcmds
|
||||
|
||||
cc = meson.get_compiler('c')
|
||||
math_dep = cc.find_library('m', required: true)
|
||||
|
||||
# build the executable
|
||||
executable('wom', srcfiles,
|
||||
dependencies: [
|
||||
dependency('lua', version: '>=5.1 <6.0'),
|
||||
math_dep,
|
||||
],
|
||||
include_directories: [
|
||||
include_directories('include'),
|
||||
|
12
src/main.c
12
src/main.c
@@ -69,8 +69,7 @@ main(int argc, char *argv[])
|
||||
int l;
|
||||
lua_State *L;
|
||||
const char *cag_path;
|
||||
char *config_path;
|
||||
bool show_help = false;
|
||||
char *config_path = { 0 };
|
||||
cag_option_context context;
|
||||
|
||||
/* general options for womblic */
|
||||
@@ -87,8 +86,7 @@ main(int argc, char *argv[])
|
||||
case 'h':
|
||||
printf("Usage: wom [OPTION]...\n");
|
||||
cag_option_print(options, CAG_ARRAY_SIZE(options), stdout);
|
||||
show_help = true;
|
||||
break;
|
||||
exit(0);
|
||||
case '?':
|
||||
cag_option_print_error(&context, stdout);
|
||||
break;
|
||||
@@ -117,12 +115,6 @@ main(int argc, char *argv[])
|
||||
lua_pop(L, lua_gettop(L));
|
||||
}
|
||||
|
||||
/* show help info about which subcmds are available */
|
||||
if (show_help) {
|
||||
subcmds_subcmd(NULL, 0, NULL);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
run_subcmds(argc, argv);
|
||||
|
||||
lua_close(L);
|
||||
|
@@ -1,10 +1,92 @@
|
||||
#include <math.h>
|
||||
#include <signal.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "subcmds.h"
|
||||
|
||||
#define S_AS_MSEC 1000000
|
||||
#define PB_LEN 30
|
||||
#define PB_FULL "┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃"
|
||||
|
||||
#define set_str_len(u, us, hu) str_len += (u > 0) ? (numlen(u) + 1 + (u > 1 ? strlen(us"s") : strlen(us)) + ((hu > 0) ? 1 : 0)) : 0
|
||||
#define write_str(u, us) do { \
|
||||
if (u > 0) { \
|
||||
if (str[0] != '\0') { \
|
||||
strcat(str, " "); \
|
||||
} \
|
||||
size_t sz = numlen(u) + (u > 1 ? strlen(us"s") : strlen(us)) + 2; \
|
||||
tmp = calloc(sz, sizeof(char)); \
|
||||
snprintf(tmp, sz, "%d %s", u, u > 1 ? us"s" : us); \
|
||||
strcat(str, tmp); \
|
||||
free(tmp); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
int i, total_delay_s;
|
||||
|
||||
/**
|
||||
* @brief convert a time to a string in seconds ie:
|
||||
* 12 -> 12 seconds
|
||||
*
|
||||
* 720 -> 12 minutes
|
||||
*
|
||||
* 43,200 -> 12 hours
|
||||
*
|
||||
* 1,036,800 -> 12 days
|
||||
*
|
||||
* @param sec input time
|
||||
* @return time
|
||||
*/
|
||||
static char
|
||||
*sec2str(int sec)
|
||||
{
|
||||
int days, hours, minutes, seconds, str_len;
|
||||
char *str, *tmp;
|
||||
|
||||
if (sec < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (str_len = days = hours = minutes = seconds = 0; sec > 0;) {
|
||||
if (sec >= 60 * 60 * 24) {
|
||||
sec -= 60 * 60 * 24;
|
||||
days++;
|
||||
} else if (sec >= 60 * 60) {
|
||||
sec -= 60 * 60;
|
||||
hours++;
|
||||
} else if (sec >= 60) {
|
||||
sec -= 60;
|
||||
minutes++;
|
||||
} else if (sec >= 1) {
|
||||
sec -= 1;
|
||||
seconds++;
|
||||
}
|
||||
}
|
||||
|
||||
set_str_len(days, "day", 0);
|
||||
set_str_len(hours, "hour", days);
|
||||
set_str_len(minutes, "minute", hours);
|
||||
set_str_len(seconds, "second", minutes);
|
||||
str_len += 1;
|
||||
|
||||
str = malloc(str_len * sizeof(char));
|
||||
str[0] = '\0';
|
||||
|
||||
write_str(days, "day");
|
||||
write_str(hours, "hour");
|
||||
write_str(minutes, "minute");
|
||||
write_str(seconds, "second");
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief convert a sting to a time in seconds ie:
|
||||
* 12s -> 12 seconds
|
||||
@@ -19,75 +101,144 @@
|
||||
* @return time in seconds
|
||||
*/
|
||||
static int
|
||||
string2time(char *str)
|
||||
str2sec(char *str)
|
||||
{
|
||||
char *d;
|
||||
int i;
|
||||
double time;
|
||||
char *time_buffer;
|
||||
int i, si, ei, ste, temp_total, total;
|
||||
|
||||
/* find the length of the string */
|
||||
for (i = 0; str[i] != '\0'; i++)
|
||||
;
|
||||
for (total = si = ei = i = 0; i < strlen(str); i++, temp_total = 0) {
|
||||
/**
|
||||
* if the char is not a number we need to take all the previous numbers
|
||||
* and attempt to convert this to a proper time
|
||||
*/
|
||||
if (str[i] < '0' || str[i] > '9') {
|
||||
ei = i - 1;
|
||||
ste = ei - si + 1;
|
||||
time_buffer = malloc((ste * sizeof(char)) + 1);
|
||||
memcpy(time_buffer, str + si, ste);
|
||||
time_buffer[ste] = '\0';
|
||||
temp_total += strtol(time_buffer, NULL, 10);
|
||||
free(time_buffer);
|
||||
|
||||
/* if there is a trailing character make sure to remove it */
|
||||
if (str[i] < '0' || str[i] > '9') {
|
||||
i--;
|
||||
}
|
||||
switch (str[i]) {
|
||||
default: case 's': break;
|
||||
case 'm': temp_total *= 60; break;
|
||||
case 'h': temp_total *= 60 * 60; break;
|
||||
case 'd': temp_total *= 60 * 60 * 24; break;
|
||||
}
|
||||
|
||||
/* allocate space for numerical string */
|
||||
d = (char *)calloc(i, sizeof(char));
|
||||
strncpy(d, str, i);
|
||||
total += temp_total;
|
||||
si = i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* atoi the numerical string into an int */
|
||||
time = atof(d);
|
||||
free(d);
|
||||
|
||||
/* modify the time using the last trailing character */
|
||||
switch (str[i]) {
|
||||
case 's': break;
|
||||
case 'm': time *= 60; break;
|
||||
case 'h': time *= 60 * 60; break;
|
||||
case 'd': time *= 60 * 60 * 24; break;
|
||||
default: return -1; break;
|
||||
}
|
||||
|
||||
return time;
|
||||
return total;
|
||||
}
|
||||
|
||||
static void
|
||||
timer_exit(void)
|
||||
{
|
||||
char *time_str;
|
||||
time_t t;
|
||||
struct tm tm;
|
||||
|
||||
printf("\033[?25h");
|
||||
|
||||
time_str = sec2str(total_delay_s - i);
|
||||
t = time(NULL);
|
||||
tm = *localtime(&t);
|
||||
printf(
|
||||
"\033[3A\033[43;30;1m wom timer \033[0m %s elapsed at %d/%02d/%02d %02d:%02d:%02d\n",
|
||||
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
|
||||
timer_sig_exit(int sig)
|
||||
{
|
||||
puts("\n");
|
||||
timer_exit();
|
||||
exit(sig);
|
||||
}
|
||||
|
||||
void
|
||||
timer_subcmd(void *, int argc, char *argv[])
|
||||
{
|
||||
int i, l, sum;
|
||||
char *s;
|
||||
bool first;
|
||||
int j, slp, sec, rollover, wi, tick, sub;
|
||||
char *pb_elapsed, *pb_left, *time_str;
|
||||
|
||||
for (i = 1, sum = 0, l = 0; i < argc; i++) {
|
||||
sum += string2time(argv[i]);
|
||||
l += strlen(argv[i]);
|
||||
for (i = 1, total_delay_s = 0; i < argc; i++) {
|
||||
total_delay_s += str2sec(argv[i]);
|
||||
}
|
||||
|
||||
/* allocate and populate a string with the length of the timer */
|
||||
s = (char *)calloc(l + i - 1, sizeof(char));
|
||||
for (i = 1; i < argc; i++) {
|
||||
/* TODO: reorder based on magnitude */
|
||||
s = strcat(s, argv[i]);
|
||||
if (i != argc - 1) {
|
||||
s = strcat(s, " ");
|
||||
}
|
||||
}
|
||||
|
||||
if (sum <= 0) {
|
||||
if (total_delay_s <= 0) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* print out the number of time */
|
||||
printf("Waiting for %s...\n", s);
|
||||
/* 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);
|
||||
|
||||
/* TODO: instead of sleeping implement polling that way if need be we can have
|
||||
* a countdown */
|
||||
sleep(sum);
|
||||
/* render ui */
|
||||
printf("\033[?25l");
|
||||
atexit(timer_exit);
|
||||
signal(SIGINT, timer_sig_exit);
|
||||
puts("");
|
||||
rollover = 0;
|
||||
first = true;
|
||||
tick = (total_delay_s / (float)PB_LEN) * S_AS_MSEC;
|
||||
|
||||
puts("returned");
|
||||
for (sub = j = 0, i = total_delay_s; i > 0; i--) {
|
||||
/* sub second handler */
|
||||
for (sec = S_AS_MSEC; sec > 0;) {
|
||||
if (!first) {
|
||||
printf("\033[2A");
|
||||
}
|
||||
first = false;
|
||||
|
||||
if (rollover > 0) {
|
||||
sub = rollover;
|
||||
rollover = 0;
|
||||
} else {
|
||||
sub = tick;
|
||||
}
|
||||
if (sec - sub < 0) {
|
||||
slp = sec;
|
||||
rollover = fabs((float)sec - sub);
|
||||
sec = 0;
|
||||
} else {
|
||||
sec -= sub;
|
||||
slp = sub;
|
||||
}
|
||||
|
||||
printf("\033[2K\033[43;30;1m wom timer \033[0m \033[33m%s\033[30m%s\033[0m\n", pb_left, pb_elapsed);
|
||||
time_str = sec2str(i);
|
||||
printf("\033[2K\033[90m %s\033[0m\n", time_str);
|
||||
free(time_str);
|
||||
|
||||
/* change the progress bar */
|
||||
if (rollover == 0) {
|
||||
wi = strlen(PB_FULL) - (j * strlen("┃")) - strlen("┃");
|
||||
strncat(pb_elapsed, "┃", strlen(PB_FULL));
|
||||
pb_left[wi] = '\0';
|
||||
j++;
|
||||
}
|
||||
|
||||
usleep(slp);
|
||||
}
|
||||
}
|
||||
|
||||
free(pb_left);
|
||||
free(pb_elapsed);
|
||||
|
||||
return;
|
||||
}
|
||||
|
Reference in New Issue
Block a user