aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEl-BG-1970 <elouan.gros.fr@gmail.com>2021-10-13 11:58:17 +0200
committerEl-BG-1970 <elouan.gros.fr@gmail.com>2021-10-13 11:58:17 +0200
commit8140d75aeb50e45aaa2d4ce34bfc84509fd2e91d (patch)
treed8101114f28661364135f73ad72595c258b33d60
downloadorg-to-conky-8140d75aeb50e45aaa2d4ce34bfc84509fd2e91d.tar.gz
first commit
-rw-r--r--.gitignore5
-rw-r--r--Makefile26
-rw-r--r--agenda_entry.c109
-rw-r--r--agenda_entry.h29
-rw-r--r--date.c77
-rw-r--r--date.h25
-rw-r--r--main.c122
7 files changed, 393 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..d3622f1
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+*.o
+otc
+valgrind*
+massif*
+*.org
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..fa24083
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,26 @@
+TARGET=otc
+
+CC=clang #--std=c99
+CXX=clang #--std=c++11
+CFLAGS=-Wall -Wextra -Werror -g
+LIBS=
+BLDFLAGS=-O2 -g
+
+DEPS=main.c agenda_entry.c date.c
+HEAD=agenda_entry.h date.h
+OBJ=${DEPS:.c=.o}
+
+.PHONY: all clean $(TARGET)
+
+all: $(TARGET)
+
+$(OBJ): $(HEAD)
+
+%.o: %.c
+ $(CC) -o $@ -c $< $(CFLAGS)
+
+$(TARGET): $(OBJ)
+ $(CC) -o $@ $(OBJ) $(LIBS) $(BLDFLAGS)
+
+clean:
+ rm -f *.o *~ *.core $(OBJ) $(TARGET)
diff --git a/agenda_entry.c b/agenda_entry.c
new file mode 100644
index 0000000..fa933c6
--- /dev/null
+++ b/agenda_entry.c
@@ -0,0 +1,109 @@
+#include "agenda_entry.h"
+
+char *next_word(char *str) { return strstr(str, " ")+1; }
+char *next_line(char *str) { return strstr(str, "\n")+1; }
+char *next_entry(char *str) {
+ char *tmp = strstr(str, "\n*");
+ if (tmp) tmp += 1;
+ return tmp; }
+
+entry read_agenda_entry(char *agenda) {
+ entry agenda_entry;
+ char *cursor = agenda;
+ char *lookahead, *tmp;
+ char *nextentry = next_entry(cursor);
+ if (nextentry == NULL)
+ nextentry = agenda + strlen(agenda) - 1;
+
+ while ((*cursor == '\n') ||
+ (*cursor == '\t') ||
+ (*cursor == ' '))
+ cursor++;
+ while (*(cursor++) == '*'); // trim the * out
+
+ //find out if there is a tag, and extract it
+ lookahead = strstr(cursor, ":\n");
+ if (lookahead && (lookahead < nextentry)) {
+ tmp = strstr(cursor, ":");
+ agenda_entry.tag = (char *)malloc(lookahead - tmp);
+ strncpy(agenda_entry.tag, tmp+1, lookahead - tmp - 1);
+ agenda_entry.tag[lookahead - tmp - 1] = '\0'; // here we're actually modifying lookahead-tmp cause the array is zero indexed
+ lookahead = tmp;
+ } else {
+ lookahead = strstr(cursor, "\n");
+ agenda_entry.tag = NULL;
+ }
+ agenda_entry.title = (char *)malloc(lookahead - cursor + 1);
+ strncpy(agenda_entry.title, cursor, lookahead - cursor);
+ agenda_entry.title[lookahead - cursor] = '\0'; // here we're actually modifying lookahead-cursor cause the array is zero indexed
+
+ //find out if there is a deadline and extract it
+ cursor = next_line(cursor);
+ if (((lookahead = strstr(cursor, "DEADLINE:")) &&
+ (lookahead < nextentry)) ||
+ ((lookahead = strstr(cursor, "SCHEDULED:")) &&
+ (lookahead < nextentry))) {
+ //there is a deadline or event is scheduled
+ tmp = strstr(lookahead, ">");
+ lookahead = strstr(lookahead, "<");
+ char *date = (char *)malloc(tmp - lookahead + 1);
+ strncpy(date, lookahead+1, tmp - lookahead - 1);
+ agenda_entry.date = extract_date(date);
+ free(date);
+ } else {
+ agenda_entry.date = (Date){ 0, 0, 0 };
+ }
+
+ return agenda_entry;
+}
+
+char *format_entry(entry e) {
+ char *ret = calloc(125, 1);
+ if (e.tag)
+ snprintf(ret, 124, " * %s \t:%s:", e.title, e.tag);
+ else
+ snprintf(ret, 124, " * %s", e.title);
+ return ret;
+}
+
+void sort_entry_array(entry *arr, int n) {
+ if (n == 1) return;
+
+ int halfway = n/2;
+ sort_entry_array(arr, halfway);
+ sort_entry_array(arr+halfway, n - halfway);
+
+ int i = 0,
+ j = halfway;
+ entry *tmp;
+ entry sw;
+ while ((i < j) && (j < n)) {
+ if (smaller(arr[i].date, arr[j].date))
+ i++;
+ else {
+ tmp = arr + j - 1;
+ while (tmp >= arr + i) {
+ sw = tmp[1];
+ tmp[1] = tmp[0];
+ tmp[0] = sw;
+ tmp--;
+ }
+ i++;
+ j++;
+ }
+ }
+}
+
+void print_entry(entry e) {
+ char *tmp = print_date_to_string(e.date);
+ printf("%s\n%s\n>%s\n",
+ e.title,
+ e.tag,
+ tmp);
+ free(tmp);
+}
+
+void destroy_entry(entry e) {
+ free(e.tag);
+ free(e.title);
+}
diff --git a/agenda_entry.h b/agenda_entry.h
new file mode 100644
index 0000000..49a141b
--- /dev/null
+++ b/agenda_entry.h
@@ -0,0 +1,29 @@
+#ifndef __AGENDA_ENTRY_H__
+#include <stdlib.h>
+#include <string.h>
+#include "date.h"
+
+typedef struct entry {
+ //struct entry *parent;
+ //struct entry *children;
+ //int8_t level;// nesting level of the entry
+ //char *todo; // TODO keyword
+ char *tag; // tag keyword
+ char *title; // the actual entry
+ //char *text; // description (if there is one)
+ Date date; // scheduled or deadline date
+} entry;
+
+char *next_word(char *str);
+char *next_line(char *str);
+char *next_entry(char *str);
+
+entry read_agenda_entry(char *agenda);
+char *format_entry(entry e);
+
+void sort_entry_array(entry *arr, int n);
+void print_entry(entry e);
+void destroy_entry(entry e);
+
+#define __AGENDA_ENTRY_H__
+#endif
diff --git a/date.c b/date.c
new file mode 100644
index 0000000..4cab1d2
--- /dev/null
+++ b/date.c
@@ -0,0 +1,77 @@
+#include "date.h"
+#define _BSD_SOURCE
+
+enum month {JAN=1, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC} month;
+
+Date extract_date(char *str) {
+ Date ret;
+ sscanf(str, "%d-%d-%d",
+ &ret.year,
+ &ret.month,
+ &ret.day);
+ return ret;
+}
+
+bool smaller(Date a, Date b) {
+ if (zero(b)) return true;
+ if (zero(a)) return false;
+ return ((a.year < b.year) ||
+ ((a.year == b.year) && (a.month < b.month)) ||
+ ((a.year == b.year) && (a.month == b.month) && (a.day <= b.day)));
+}
+
+bool eql(Date a, Date b) {
+ return (a.day == b.day) &&
+ (a.month == b.month) &&
+ (a.year == b.year);
+}
+
+bool zero(Date a) {
+ return ((a.year == 0) ||
+ (a.month == 0) ||
+ (a.day == 0));
+}
+
+void print_date(Date date) {
+ printf("%i/%i/%i\n", date.month, date.day, date.year);
+}
+
+char *print_date_to_string(Date date) {
+ char *ret = (char *)calloc(16, 1);
+ sprintf(ret, "%i/%i/%i", date.month, date.day, date.year);
+ return ret;
+}
+
+Date today() {
+ FILE *pipe = popen("date \"+%Y-%m-%d\"", "r");
+ char *td = (char *)malloc(12);
+ td = fgets(td, 12, pipe);
+ Date ret = extract_date(td);
+
+ pclose(pipe);
+ free(td);
+ return ret;
+}
+
+Date nextweek(Date td) {
+ Date nw = { td.day+7, td.month, td.year };
+ if (nw.month == FEB && nw.day > 28) {
+ if (nw.year % 4 == 0 && nw.day > 29) {
+ nw.day -= 29; nw.month++;
+ } else {
+ nw.day -= 28; nw.month++;
+ }
+ } else if (nw.month == JAN || nw.month == MAR || nw.month == MAY || nw.month == JUL ||
+ nw.month == AUG || nw.month == OCT || nw.month == DEC) {
+ if (nw.day > 31 && nw.month == DEC) {
+ nw.day -= 31; nw.month = 1;
+ } else if (nw.day > 31) {
+ nw.day -= 31; nw.month++;
+ }
+ } else if (nw.month == APR || nw.month == JUN || nw.month == SEP || nw.month == NOV) {
+ if (nw.day > 30) {
+ nw.day -= 30; nw.month++;
+ }
+ }
+ return nw;
+}
diff --git a/date.h b/date.h
new file mode 100644
index 0000000..649b90f
--- /dev/null
+++ b/date.h
@@ -0,0 +1,25 @@
+#ifndef __DATE_H__
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+typedef struct Date {
+ int day;
+ int month;
+ int year;
+} Date;
+
+Date extract_date(char *str);
+bool smaller(Date a, Date b);
+bool eql(Date a, Date b);
+bool zero(Date a);
+
+void print_date(Date date);
+char *print_date_to_string(Date date);
+
+Date today();
+Date nextweek(Date td);
+
+#define __DATE_H__
+#endif
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..c11ce29
--- /dev/null
+++ b/main.c
@@ -0,0 +1,122 @@
+#include <stdio.h>
+#include <unistd.h>
+#include "agenda_entry.h"
+#define BS 100 //blocksize for buffers
+
+void destroy_entry_array(entry *array, int elements) {
+ for (int i = 0; i < elements; i++)
+ destroy_entry(array[i]);
+ free(array);
+}
+
+char *read_file_to_buffer(char *filename) {
+ FILE *fd = fopen(filename, "r");
+ int bufsize = BS,
+ bufread = 0;
+ char *buf = (char *)malloc(bufsize);
+ char *newbuf;
+
+ while (fread(buf + bufread, 1, 100, fd) == BS) {
+ newbuf = (char *)malloc(bufsize + BS);
+ strncpy(newbuf, buf, bufsize);
+ free(buf);
+ buf = newbuf;
+ bufsize += BS;
+ bufread += BS;
+ }
+ fclose(fd);
+ return buf;
+}
+
+// this function does not work... to debug!
+entry *read_entries_to_array(char *buffer, int *entries) {
+ int numentries = 5,
+ idx = 0;
+ entry *ret = (entry *)malloc(numentries * sizeof(entry));
+ char *cursor = buffer;
+ while (cursor) {
+ if (idx == numentries) {
+ entry *newret = (entry *)malloc((numentries + 5) * sizeof(entry));
+ memcpy(newret, ret, (idx)*sizeof(entry));
+ free(ret);
+ ret = newret;
+ numentries += 5;
+ }
+ ret[idx++] = read_agenda_entry(cursor);
+ cursor = next_entry(cursor);
+ }
+ *entries = idx;
+ return ret;
+}
+
+int main(int argc, char **argv) {
+ // unbuffering stdout in order to prevent leaks
+ // has the added benefit of reducing memory usage too
+ setvbuf(stdout, NULL, _IONBF, 0);
+ if (argc <= 1) {
+ printf("no agenda file supplied!\nUsage: otc <agendafile>\n");
+ return -1;
+ }
+
+ // read file into buf
+ char *buf = read_file_to_buffer(argv[1]);
+ if (strlen(buf) == 0) return -1; // don't do empty buffers
+
+ // read entries into array
+ int idx = 0;
+ entry *agenda = read_entries_to_array(buf, &idx);
+ free(buf);
+ /*char *tmp = buf;
+ entry *agenda;
+ int numentries = 10,
+ idx = 0,
+ buflen = strlen(buf);
+ agenda = (entry *)malloc(numentries * sizeof(entry));
+ while (buf) {
+ agenda[idx++] = read_agenda_entry(buf);
+ tmp = next_entry(buf);
+ if (tmp == NULL) buflen = 0;
+ else buflen -= (tmp - buf);
+ buf = tmp;
+ }*/
+
+ // sort entries
+ sort_entry_array(agenda, idx);
+
+ // format nicely
+ char *e;
+ Date td = today();
+ Date nw = nextweek(td);
+ Date last_date = agenda[0].date;
+ if (!zero(last_date)) {
+ e = print_date_to_string(last_date);
+ if (smaller(last_date, td))
+ printf("\n%s [OUTATIME]:\n", e);
+ else if (smaller(last_date, nw))
+ printf("\n%s:\n", e);
+ free(e);
+ }
+ for (int i = 0; i < idx; i++) {
+ if (!eql(agenda[i].date, last_date)) {
+ last_date = agenda[i].date;
+ if (!zero(last_date)) {
+ e = print_date_to_string(last_date);
+ if (smaller(last_date, td))
+ printf("\n%s [OUTATIME]:\n", e);
+ else if (smaller(last_date, nw))
+ printf("\n%s:\n", e);
+ free(e);
+ } else {
+ printf("\nUnscheduled:\n");
+ }
+ }
+ e = format_entry(agenda[i]);
+ if (zero(agenda[i].date) || smaller(agenda[i].date, nw)) puts(e);
+ free(e);
+ }
+
+ // free up the memory
+ fclose(stdout);
+ destroy_entry_array(agenda, idx);
+ return 0;
+}