aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkatherine <ageha@airen-no-jikken.icu>2019-12-20 09:28:54 -0700
committerkatherine <ageha@airen-no-jikken.icu>2019-12-20 09:28:54 -0700
commit41f73b0a45ba3e63ac33ebdc99f12481f5b7cdab (patch)
treecb863c4372a1386a27cd1e655afeeb160f396d46
parent31632d4edbd903826cbf8f6bb93969f0d1a983fb (diff)
downloadevery-41f73b0a45ba3e63ac33ebdc99f12481f5b7cdab.tar.gz
implement printing
-rw-r--r--src/calendar.c125
-rw-r--r--src/calendar.h2
-rw-r--r--src/entry.c219
-rw-r--r--src/entry.h4
-rw-r--r--src/err.h19
-rw-r--r--src/main.c10
-rw-r--r--src/opt.h6
-rw-r--r--src/print.c246
-rw-r--r--src/print.h9
9 files changed, 427 insertions, 213 deletions
diff --git a/src/calendar.c b/src/calendar.c
index 1240547..06d80d7 100644
--- a/src/calendar.c
+++ b/src/calendar.c
@@ -20,6 +20,7 @@ struct state_s {
size_t line, col;
size_t last_line, last_col;
struct entry_interval_s cur_warn;
+ struct entry_interval_s cur_stay;
bool cur_urgent;
bool cur_local;
FILE *f;
@@ -30,6 +31,7 @@ enum cmd_type_e {
CMD_TYPE_WARN,
CMD_TYPE_URGENT,
CMD_TYPE_LOCAL,
+ CMD_TYPE_STAY,
};
struct cmd_s {
@@ -364,6 +366,17 @@ static inline struct cmd_s sub_get_cmd_warn(struct state_s *s)
return cmd;
}
+static inline struct cmd_s sub_get_cmd_stay(struct state_s *s)
+{
+ struct cmd_s cmd = {
+ .type = CMD_TYPE_STAY
+ };
+
+ cmd.iv = sub_get_interval(s);
+
+ return cmd;
+}
+
static bool sub_get_bool(struct state_s *s)
{
bool r = false;
@@ -526,7 +539,19 @@ static inline struct cmd_s sub_get_cmd(struct state_s *s)
) {
s->col += 5;
sub_eat_spaces(s);
- return sub_get_cmd_urgent(s);
+ return sub_get_cmd_local(s);
+ }
+ break;
+
+ case 's':
+ if (
+ getc(s->f) == 't' &&
+ getc(s->f) == 'a' &&
+ getc(s->f) == 'y'
+ ) {
+ s->col += 4;
+ sub_eat_spaces(s);
+ return sub_get_cmd_stay(s);
}
break;
}
@@ -545,7 +570,7 @@ static char* sub_get_msg(struct state_s *s)
while ( (c = getc(s->f)) != '\n' && c != EOF) {
s->col++;
- if (count == width) {
+ if (count == width || count + 1 == width) {
width += step_size;
msg = realloc(msg, width * sizeof(*msg));
@@ -568,6 +593,7 @@ static char* sub_get_msg(struct state_s *s)
count++;
}
+ msg[count] = '\0';
s->col = 0;
s->line++;
@@ -577,10 +603,18 @@ static char* sub_get_msg(struct state_s *s)
static inline struct entry_s sub_get_entry_on(struct state_s *s)
{
struct entry_s e = {
- .type = ENTRY_TYPE_ON
+ .type = ENTRY_TYPE_ON,
+ .urgent = s->cur_urgent,
+ .local = s->cur_local,
+ .warn = s->cur_warn,
+ .stay = s->cur_stay,
};
time_t rt;
int c;
+ struct pos_s p = {
+ .line = s->last_line,
+ .col = s->last_col,
+ };
rt = sub_get_date(s);
if (s->err_flag)
@@ -593,19 +627,10 @@ static inline struct entry_s sub_get_entry_on(struct state_s *s)
c = getc(s->f);
if (c != ',') {
- if (c == 'w'
- && getc(s->f) == 'a'
- && getc(s->f) == 'r'
- && getc(s->f) == 'n'
- ) {
- s->col += 4;
- e.warn = sub_get_interval(s);
- if (s->err_flag)
- return e;
- } else {
- ungetc(c, s->f);
- return e;
- }
+ sub_set_pos(s, p);
+ ERRP("invalid calendar entry");
+ s->err_flag = true;
+ return e;
}
s->col++;
@@ -622,8 +647,9 @@ static inline struct entry_s sub_get_entry_every(struct state_s *s)
.urgent = s->cur_urgent,
.local = s->cur_local,
.warn = s->cur_warn,
+ .stay = s->cur_stay,
};
- bool from_seen = false, to_seen = false, warn_seen = false;
+ bool from_seen = false, to_seen = false;
char c;
struct pos_s p = {
.line = s->last_line,
@@ -685,29 +711,6 @@ static inline struct entry_s sub_get_entry_every(struct state_s *s)
break;
}
- case 'w':
- if (
- getc(s->f) == 'a' &&
- getc(s->f) == 'r' &&
- getc(s->f) == 'n'
- ) {
- if (warn_seen) {
- ERRP("invalid calendar entry");
- s->err_flag = true;
- return e;
- }
- warn_seen = true;
-
- s->col += 4;
- sub_eat_spaces(s);
- e.warn = sub_get_interval(s);
-
- if (s->err_flag)
- return e;
-
- break;
- }
-
default:
goto done;
}
@@ -792,22 +795,6 @@ static inline void sub_cal_push(struct state_s *s, struct calendar_s *cal,
cal->count++;
}
-static void sub_cal_free(struct calendar_s *cal)
-{
- size_t i;
-
- if (cal->entries == NULL)
- return;
-
- for (i = 0; i < cal->count; i++) {
- if (cal->entries[i].msg != NULL)
- free(cal->entries[i].msg);
- }
-
- free(cal->entries);
- cal->entries = NULL;
-}
-
struct calendar_s calendar_parse(FILE *f)
{
struct calendar_s cal = {
@@ -821,6 +808,9 @@ struct calendar_s calendar_parse(FILE *f)
.cur_warn = {
.day = 1,
},
+ .cur_stay = {
+ .day = 1,
+ },
.cur_urgent = false,
.cur_local = true,
.f = f,
@@ -843,7 +833,7 @@ struct calendar_s calendar_parse(FILE *f)
cmd = sub_get_cmd(&s);
if (s.err_flag) {
- sub_cal_free(&cal);
+ calendar_wipe(&cal);
cal.err_flag = true;
return cal;
}
@@ -858,6 +848,9 @@ struct calendar_s calendar_parse(FILE *f)
case CMD_TYPE_LOCAL:
s.cur_local = cmd.b;
break;
+ case CMD_TYPE_STAY:
+ s.cur_stay = cmd.iv;
+ break;
}
continue;
@@ -867,7 +860,7 @@ struct calendar_s calendar_parse(FILE *f)
e = sub_get_entry(&s);
if (s.err_flag) {
- sub_cal_free(&cal);
+ calendar_wipe(&cal);
cal.err_flag = true;
return cal;
}
@@ -876,3 +869,19 @@ struct calendar_s calendar_parse(FILE *f)
return cal;
}
+
+void calendar_wipe(struct calendar_s *cal)
+{
+ size_t i;
+
+ if (cal->entries == NULL)
+ return;
+
+ for (i = 0; i < cal->count; i++) {
+ if (cal->entries[i].msg != NULL)
+ free(cal->entries[i].msg);
+ }
+
+ free(cal->entries);
+ cal->entries = NULL;
+}
diff --git a/src/calendar.h b/src/calendar.h
index ccf59bb..cee6f3d 100644
--- a/src/calendar.h
+++ b/src/calendar.h
@@ -14,4 +14,6 @@ struct calendar_s {
struct calendar_s calendar_parse(FILE *f);
+void calendar_wipe(struct calendar_s *cal);
+
#endif
diff --git a/src/entry.c b/src/entry.c
index f903d97..13208ca 100644
--- a/src/entry.c
+++ b/src/entry.c
@@ -2,177 +2,100 @@
#include <assert.h>
-static int sub_inc_year(struct tm *t, int n)
-{
- if (n == 0)
- return 0;
-
- t->tm_year += n;
-
- if (mktime(t) == -1)
- return -1;
-
- return 0;
-}
+static time_t rt;
-static int sub_inc_month(struct tm *t, int n)
+/* super inefficient, but should best-possible avoid any weird leap
+ * years/seconds/dst-problems/other future changes */
+time_t* entry_is_active(struct entry_s *e, time_t now)
{
- unsigned i;
-
- if (n == 0)
- return 0;
-
- for (i = 0; i < n; i++) {
- t->tm_mon++;
- if (mktime(t) == -1) {
- t->tm_mon = 0;
- if (sub_inc_year(t, 1) == -1)
- return -1;
- }
- }
-
- return 0;
-}
+ struct tm t, ttmp, *tmp;
+ time_t rttmp, now_plus_warn, now_minus_stay;
+
+ assert(e != NULL);
-static int sub_inc_day(struct tm *t, int n)
-{
- unsigned i;
+ tmp = localtime(&now);
+ if (tmp == NULL)
+ return NULL;
+ t = *tmp;
+ ttmp = t;
- if (n == 0)
- return 0;
+ t.tm_year += e->warn.year;
+ t.tm_mon += e->warn.month;
+ t.tm_mday += e->warn.day;
+ t.tm_hour += e->warn.hour;
+ t.tm_min += e->warn.minute;
+ t.tm_sec += e->warn.second;
- for (i = 0; i < n; i++) {
- t->tm_mday++;
- if (mktime(t) == -1) {
- t->tm_mday = 1;
- if (sub_inc_month(t, 1) == -1)
- return -1;
- }
- }
+ now_plus_warn = mktime(&t);
- return 0;
-}
+ ttmp.tm_year -= e->stay.year;
+ ttmp.tm_mon -= e->stay.month;
+ ttmp.tm_mday -= e->stay.day;
+ ttmp.tm_hour -= e->stay.hour;
+ ttmp.tm_min -= e->stay.minute;
+ ttmp.tm_sec -= e->stay.second;
-static int sub_inc_hour(struct tm *t, int n)
-{
- unsigned i;
+ now_minus_stay = mktime(&ttmp);
- if (n == 0)
- return 0;
+ if (now_plus_warn == -1 || now_minus_stay == -1)
+ return NULL;
- for (i = 0; i < n; i++) {
- t->tm_hour++;
- if (mktime(t) == -1) {
- t->tm_hour = 0;
- if (sub_inc_day(t, 1) == -1)
- return -1;
+ if (e->type == ENTRY_TYPE_ON) {
+ if (e->start >= now_minus_stay && e->start <= now_plus_warn) {
+ rt = e->start;
+ return &rt;
}
- }
-
- return 0;
-}
-
-static int sub_inc_minute(struct tm *t, int n)
-{
- unsigned i;
- if (n == 0)
- return 0;
-
- for (i = 0; i < n; i++) {
- t->tm_min++;
- if (mktime(t) == -1) {
- t->tm_min = 0;
- if (sub_inc_hour(t, 1) == -1)
- return -1;
- }
+ return NULL;
}
- return 0;
-}
-
-static int sub_inc_second(struct tm *t, int n)
-{
- time_t rt;
- struct tm *tmp;
-
- if (n == 0)
- return 0;
-
- rt = mktime(t);
-
- if (rt + n <= rt)
- return -1;
- rt += n;
+ if (e->has_end && now_minus_stay > e->end)
+ return NULL;
- tmp = localtime(&rt);
- *t = *tmp;
-
- return 0;
-}
+ tmp = localtime( &(e->start) );
+ if (tmp == NULL)
+ return NULL;
+ t = *tmp;
-/* super inefficient, but should best-possible avoid any weird leap
- * years/seconds/dst-problems/other future changes */
-bool entry_is_active(struct entry_s *e, time_t now)
-{
- struct tm t, *tmp;
- time_t rt, now_plus_warn;
-
- assert(e != NULL);
+ for (rt = e->start;;) {
+ if (rt > now_plus_warn)
+ return NULL;
- tmp = localtime(&now);
- assert(tmp != NULL);
- t = *tmp;
+ if (rt >= now_minus_stay)
+ return &rt;
- if (sub_inc_year(&t, e->warn.year))
- return false;
- if (sub_inc_month(&t, e->warn.month))
- return false;
- if (sub_inc_day(&t, e->warn.day))
- return false;
- if (sub_inc_hour(&t, e->warn.hour))
- return false;
- if (sub_inc_minute(&t, e->warn.minute))
- return false;
- if (sub_inc_second(&t, e->warn.second))
- return false;
+ ttmp = t;
- now_plus_warn = mktime(&t);
+ t.tm_year += e->every.year;
+ t.tm_mon += e->every.month;
+ t.tm_mday += e->every.day;
+ t.tm_hour += e->every.hour;
+ t.tm_min += e->every.minute;
+ t.tm_sec += e->every.second;
- if (e->type == ENTRY_TYPE_ON) {
- if (e->start >= now && e->start <= now_plus_warn)
- return true;
+ rt = mktime(&t);
- return false;
- }
+ if (rt == -1) {
+ rttmp = mktime(&ttmp);
+ if (rttmp == -1)
+ return NULL;
- tmp = localtime(&(e->start));
- assert(tmp != NULL);
- t = *tmp;
+ tmp = localtime(&rttmp);
+ if (tmp == NULL)
+ return NULL;
+ t = *tmp;
- if (e->has_end && now > e->end)
- return false;
+ t.tm_year += e->every.year;
+ t.tm_mon += e->every.month;
+ t.tm_mday += e->every.day;
+ t.tm_hour += e->every.hour;
+ t.tm_min += e->every.minute;
+ t.tm_sec += e->every.second;
- for (rt = e->start;;) {
- rt = mktime(&t);
+ rt = mktime(&t);
- if (rt > now_plus_warn)
- return false;
-
- if (rt >= now)
- return true;
-
- if (sub_inc_year(&t, e->every.year))
- return false;
- if (sub_inc_month(&t, e->every.month))
- return false;
- if (sub_inc_day(&t, e->every.day))
- return false;
- if (sub_inc_hour(&t, e->every.hour))
- return false;
- if (sub_inc_minute(&t, e->every.minute))
- return false;
- if (sub_inc_second(&t, e->every.second))
- return false;
+ if (rt == -1)
+ return NULL;
+ }
}
}
diff --git a/src/entry.h b/src/entry.h
index 41b7808..6c9791f 100644
--- a/src/entry.h
+++ b/src/entry.h
@@ -18,13 +18,13 @@ struct entry_s {
enum entry_type_e type;
bool has_end;
time_t start, end;
- struct entry_interval_s every, warn;
+ struct entry_interval_s every, warn, stay;
bool urgent;
bool local;
char *msg;
};
/* test if an entry needs warning */
-bool entry_is_active(struct entry_s *e, time_t now);
+time_t* entry_is_active(struct entry_s *e, time_t now);
#endif
diff --git a/src/err.h b/src/err.h
new file mode 100644
index 0000000..dd097fc
--- /dev/null
+++ b/src/err.h
@@ -0,0 +1,19 @@
+#ifndef EVERY_ERR_H
+#define EVERY_ERR_H
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define ERRM(...) \
+ do { \
+ fprintf(stderr, "err: " __VA_ARGS__); \
+ fprintf(stderr, "\n"); \
+ } while (0)
+
+#define ERR(...) \
+ do { \
+ ERRM(__VA_ARGS__); \
+ exit(EXIT_FAILURE); \
+ } while (0)
+
+#endif
diff --git a/src/main.c b/src/main.c
index 5c01fe0..27c5349 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,10 +1,10 @@
#include "opt.h"
#include "err.h"
+#include "calendar.h"
+#include "print.h"
#include "../reqs/simple-xdg-bdirs/simple-xdg-bdirs.h"
-#include "calendar.h"
-
#include <stdbool.h>
#include <unistd.h>
@@ -115,6 +115,12 @@ int main(int argc, char **argv)
exit(EXIT_FAILURE);
/* output commands */
+ if (cmd == OPT_COMMAND_CONSOLE)
+ print_console(&cal);
+ else
+ print_script(&cal);
+
+ calendar_wipe(&cal);
return 0;
}
diff --git a/src/opt.h b/src/opt.h
index dee767c..45bc0bd 100644
--- a/src/opt.h
+++ b/src/opt.h
@@ -2,9 +2,9 @@
#define EVERY_OPT_H
enum opt_command_e {
- OPT_COMMAND_CONSOLE = 0,
- OPT_COMMAND_SCRIPT = 1,
- OPT_COMMAND_EDIT = 1,
+ OPT_COMMAND_CONSOLE,
+ OPT_COMMAND_SCRIPT,
+ OPT_COMMAND_EDIT,
};
void opt_parse(int argc, char **argv);
diff --git a/src/print.c b/src/print.c
new file mode 100644
index 0000000..93ce295
--- /dev/null
+++ b/src/print.c
@@ -0,0 +1,246 @@
+#include "print.h"
+
+#include "entry.h"
+#include "opt.h"
+#include "err.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+static const char *weekday_names[] = {
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+};
+
+static const char *weekday_names_l[] = {
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+};
+
+static const char *month_names[] = {
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+};
+
+struct buf_s {
+ time_t rt;
+ struct entry_s e;
+};
+
+static int buf_cmp(const void *a, const void *b)
+{
+ const struct buf_s *a1 = a, *b1 = b;
+
+ if (b1->e.urgent && !(a1->e.urgent))
+ return 1;
+
+ if (a1->e.urgent && !(b1->e.urgent))
+ return -1;
+
+ if (a1->rt > b1->rt)
+ return 1;
+
+ if (b1->rt > a1->rt)
+ return -1;
+
+ return 0;
+}
+
+void print_console(struct calendar_s *cal)
+{
+ size_t i, j;
+ struct tm t = { 0 }, ttmp;
+ time_t now = time(NULL), *rttmp;
+ time_t ototois_end, yesterdays_end, todays_end, tomorrows_end, weeks_end;
+ bool has_urgent = false, urgent_printed = false;
+
+ struct buf_s *buf = malloc(cal->count * sizeof(*buf));
+
+ if (buf == NULL) {
+ ERRM("failed to allocate memory");
+ return;
+ }
+
+ /* get interval limits */
+
+ t = *localtime(&now);
+
+ ttmp.tm_year = t.tm_year;
+ ttmp.tm_mon = t.tm_mon;
+ ttmp.tm_mday = t.tm_mday - 1;
+ ttmp.tm_hour = 0;
+ ttmp.tm_min = 0;
+ ttmp.tm_sec = 0;
+ ttmp.tm_isdst = -1;
+
+ ototois_end = mktime(&ttmp);
+
+ ttmp.tm_mday++;
+
+ yesterdays_end = mktime(&ttmp);
+
+ ttmp.tm_mday++;
+
+ todays_end = mktime(&ttmp);
+
+ ttmp.tm_mday++;
+
+ tomorrows_end = mktime(&ttmp);
+
+ ttmp.tm_mday = t.tm_mday + (6 - t.tm_wday) + 1;
+
+ weeks_end = mktime(&ttmp);
+
+ printf("%s %d %s %02d %02d:%02d\n\n",
+ weekday_names[t.tm_wday],
+ t.tm_year + 1900,
+ month_names[t.tm_mon],
+ t.tm_mday,
+ t.tm_hour,
+ t.tm_min
+ );
+
+ /* fill buffer with active events */
+ for (i = 0, j = 0; i < cal->count; i++) {
+ if ( !(rttmp = entry_is_active( &(cal->entries[i]), now)) )
+ continue;
+
+ buf[j].rt = *rttmp;
+ buf[j].e = cal->entries[i];
+
+ if (buf[j].e.urgent)
+ has_urgent = true;
+
+ j++;
+ }
+
+ qsort(buf, j, sizeof(*buf), buf_cmp);
+
+ /* print from buffer */
+ if (has_urgent)
+ printf("\n[ URGENT ]\n\n");
+
+ for (i = 0; i < j; i++) {
+ t = *localtime( &(buf[i].rt) );
+
+ if (has_urgent && !urgent_printed && !(buf[i].e.urgent) ) {
+ printf("\n\n[ normal ]\n\n");
+ urgent_printed = true;
+ }
+
+ /* date */
+ if (ototois_end > buf[i].rt) {
+ printf("%04d %s %02d",
+ t.tm_year + 1900,
+ month_names[t.tm_mon],
+ t.tm_mday
+ );
+ } else if (yesterdays_end > buf[i].rt) {
+ printf("Yesterday ");
+ } else if (todays_end > buf[i].rt) {
+ printf("Today ");
+ } else if (tomorrows_end > buf[i].rt) {
+ printf("Tomorrow ");
+ } else if (weeks_end > buf[i].rt) {
+ printf("%-11s", weekday_names_l[t.tm_wday]);
+ } else {
+ printf("%04d %s %02d",
+ t.tm_year + 1900,
+ month_names[t.tm_mon],
+ t.tm_mday
+ );
+ }
+
+ /* time */
+ if (t.tm_hour != 0 || t.tm_min != 0 || t.tm_sec != 0) {
+ printf(" %02d:%02d", t.tm_hour, t.tm_min);
+
+ if (t.tm_sec != 0)
+ printf(":%02d", t.tm_sec);
+ }
+
+
+ if (buf[i].e.msg != NULL)
+ printf(" %s", buf[i].e.msg);
+
+ puts("");
+ }
+
+ free(buf);
+}
+
+void print_script(struct calendar_s *cal)
+{
+ size_t i, j;
+ struct tm t = { 0 };
+ time_t now = time(NULL), *rttmp;
+ char cd;
+ bool first = true;
+ struct buf_s *buf = malloc(cal->count * sizeof(*buf));
+
+ if (buf == NULL) {
+ ERRM("failed to allocate memory");
+ return;
+ }
+
+ cd = opt_col_delim();
+
+ /* fill buffer with active events */
+ for (i = 0, j = 0; i < cal->count; i++) {
+ if ( !(rttmp = entry_is_active( &(cal->entries[i]), now)) )
+ continue;
+
+ buf[j].rt = *rttmp;
+ buf[j].e = cal->entries[i];
+
+ j++;
+ }
+
+ qsort(buf, j, sizeof(*buf), buf_cmp);
+
+ /* print from buffer */
+ for (i = 0; i < j; i++) {
+ t = *localtime( &(buf[i].rt) );
+
+ if (!first)
+ printf("%c", opt_line_delim());
+
+ printf(
+ "%d%c%d%c%d%c%d%c%d%c%d%c" /* date */
+ "%d%c" /* urgent */
+ "%d%c" /* local */
+ "%s" /* msg */
+ ,
+ t.tm_year + 1900, cd, t.tm_mon + 1, cd, t.tm_mday, cd,
+ t.tm_hour, cd, t.tm_min, cd, t.tm_sec, cd,
+ cal->entries[i].urgent, cd,
+ cal->entries[i].local, cd,
+ (cal->entries[i].msg == NULL ? "" : cal->entries[i].msg)
+ );
+
+ first = false;
+ }
+
+ free(buf);
+}
diff --git a/src/print.h b/src/print.h
new file mode 100644
index 0000000..5bbc2c1
--- /dev/null
+++ b/src/print.h
@@ -0,0 +1,9 @@
+#ifndef EVERY_PRINT_H
+#define EVERY_PRINT_H
+
+#include "calendar.h"
+
+void print_console(struct calendar_s *cal);
+void print_script(struct calendar_s *cal);
+
+#endif