diff options
Diffstat (limited to 'caln/caln.c')
-rw-r--r-- | caln/caln.c | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/caln/caln.c b/caln/caln.c new file mode 100644 index 0000000..5c36db9 --- /dev/null +++ b/caln/caln.c @@ -0,0 +1,178 @@ +#include <time.h> +#include <stdio.h> +#include <stdbool.h> +#include <string.h> +#include <stdlib.h> + +#define DATEFMT "%a %d %b %Y" +#define SEP " ~> " + +typedef struct event { + char *name; + time_t time; +} event; + +static bool cal = true; + +static const char *days[] = { + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" +}; + +static const char *months[] = { + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec" +}; + +static const int daysinmonth[] = { + 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 +}; + +static bool +isleap(int year) { + if ((year % 4) == 0 && (year % 100) != 0) + return true; + else if ((year % 400) == 0) + return true; + return false; +} + +static void +print_month(struct tm *t) { + printf(" %s %d\n", months[t->tm_mon], t->tm_year + 1900); +} + +static void +print_days() { + for (int i = 0; i < 7; i++) + printf("%s ", days[i]); + putchar('\n'); +} + +static void +print_padded(int n, int l) { + int i = 1; +loop: + if ((n / i) > 0) { + i *= 10; + l--; + goto loop; + } + + if (l != 0) + printf("%*s", l, " "); + if (l < 0) + return; + + printf("%d", n); +} + +static void +print_month_grid(struct tm *t) { + int day = 1; + int total = daysinmonth[t->tm_mon]; + if (t->tm_mon == 1 && isleap(t->tm_year + 1900)) + total += 1; + + int offset = (t->tm_yday % 7) - 1; + for (int i = 0; i < offset; i++) + printf(" "); + + for (; day < total + 1; day++) { + if (day == t->tm_mday) { + printf("\e[4;34m"); + print_padded(day, 2); + printf("\e[0m"); + } else + print_padded(day, 2); + putchar(' '); + if (((day + offset) % 7) == 0) + putchar('\n'); + } + putchar('\n'); +} + +static void +print_cal(struct tm *t) { + print_month(t); + print_days(); + print_month_grid(t); +} + +static event * +read_event(FILE *f) { + event *e = malloc(sizeof(event)); + char buf[256] = {0}; + if (!fgets(buf, 256, f)) { + free(e); + return NULL; + } + char *time = buf; + char *name = strchr(buf, '|'); + if (!name) { + fprintf(stderr, "invalid event! %s\n", buf); + exit(1); + } + *name = 0; + name++; + + e->name = strdup(name); + e->time = atoll(time); + return e; +} + +static void +print_event(event *e) { + struct tm *t = localtime(&e->time); + char buf[256]; + strftime(buf, 256, DATEFMT, t); + printf("%s" SEP "%s", buf, e->name); +} + +static void +free_event(event *e) { + free(e->name); + free(e); +} + +int +main(int argc, char **argv) { + if (argc > 1) + if (strcmp(argv[1], "-h") == 0) + cal = false; + + time_t ulocal = time(NULL); + struct tm *local = localtime(&ulocal); + + if (cal) + print_cal(local); + + bool dirty = false; + event *e; + while (e = read_event(stdin)) { + if (ulocal + (86400 * 30) > e->time) { + print_event(e); + dirty = true; + } + free_event(e); + } + if (!dirty) + printf("You have nothing upcoming\n"); + + return 0; +} |