summaryrefslogtreecommitdiff
path: root/caln/caln.c
diff options
context:
space:
mode:
Diffstat (limited to 'caln/caln.c')
-rw-r--r--caln/caln.c178
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;
+}