From d7d0f8f5d00aaaee8cf880047920b6ce74776982 Mon Sep 17 00:00:00 2001
From: katherine <ageha@airen-no-jikken.icu>
Date: Wed, 11 Dec 2019 13:31:15 -0700
Subject: implement edit command

---
 src/calendar.c |   1 +
 src/calendar.h |  13 +++++++
 src/main.c     | 111 +++++++++++++++++++++++++++++++++++++++------------------
 src/opt.c      |  68 +++++++++++++++++++++++++----------
 src/opt.h      |  11 +++---
 5 files changed, 147 insertions(+), 57 deletions(-)

(limited to 'src')

diff --git a/src/calendar.c b/src/calendar.c
index e69de29..46fd68c 100644
--- a/src/calendar.c
+++ b/src/calendar.c
@@ -0,0 +1 @@
+#include "calendar.h"
diff --git a/src/calendar.h b/src/calendar.h
index ebfe64a..ed54c4f 100644
--- a/src/calendar.h
+++ b/src/calendar.h
@@ -1,4 +1,17 @@
 #ifndef EVERY_CALENDAR_H
 #define EVERY_CALENDAR_H
 
+enum every_calendar_entry_type {
+	EVERY_CALENDAR_ENTRY_TYPE_ON,
+	EVERY_CALENDAR_ENTRY_TYPE_EVERY,
+};
+
+struct every_calendar_entry {
+	enum every_calendar_entry_type type;
+};
+
+struct every_calendar {
+	struct every_calendar_entry *entries;
+};
+
 #endif
diff --git a/src/main.c b/src/main.c
index 625e860..86369d2 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,65 +1,108 @@
 #include "opt.h"
+#include "err.h"
 
 #include "../reqs/simple-xdg-bdirs/simple-xdg-bdirs.h"
 
+#include <stdbool.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
 int main(int argc, char **argv)
 {
-	enum every_opt_outputmode omode;
-	FILE *calendar;
+	enum every_opt_command cmd;
+
+	char *calpath;
+	FILE *cal;
 
-	char **rdirs, **cur, *s;
+	char *ed;
+	pid_t pid;
+	int wstatus;
+
+	char **rdirs, **cur;
+	bool calpath_alloced = false;
 
 	opt_parse(argc, argv);
 
-	omode = opt_outputmode();
+	cmd = opt_command();
 
 	if (opt_calpath() != NULL) {
-		s = opt_calpath();
-
-		calendar = fopen(s, "r");
-		if (calendar == NULL) {
-			printf("err: could not read calendar at `%s`\n", s);
-			exit(EXIT_FAILURE);
-		}
+		calpath = opt_calpath();
 	} else {
 		rdirs = simple_xdg_bdirs_read_dirs(SIMPLE_XDG_BDIRS_CONFIG);
 
-		if (rdirs == NULL) {
-			printf(
-				"err: no calendar specified, and default was not found or "
-				"readable\n"
-			);
-			exit(EXIT_FAILURE);
-		}
+		if (rdirs == NULL)
+			ERR("no calendar specified, and default was not found or readable");
 
-		s = simple_xdg_bdirs_fullpath_read("every/calendar", rdirs);
+		calpath = simple_xdg_bdirs_fullpath_read("every/calendar", rdirs);
 
 		for (cur = rdirs; *cur != NULL; cur++)
 			free(*cur);
 		free(rdirs);
 
-		if (s == NULL) {
-			printf(
-				"err: no calendar specified, and default was not found or "
-				"readable\n"
-			);
-			exit(EXIT_FAILURE);
+		if (calpath == NULL)
+			ERR("no calendar specified, and default was not found or readable");
+	}
+
+	/* edit command */
+	if (cmd == OPT_COMMAND_EDIT) {
+		ed = opt_editor();
+
+		if (ed == NULL) {
+			ERR("no editor specified, and $EDITOR was not found");
 		}
 
-		calendar = fopen(s, "r");
+		pid = fork();
+
+		if (pid == 0) {
+			if (execlp(ed, ed, calpath, (char*)NULL) == -1)
+				exit(EXIT_FAILURE);
+		} else if (pid == -1) {
+			if (calpath_alloced)
+				free(calpath);
 
-		free(s);
+			ERR("editor failed to spawn");
+		} else {
+			if (waitpid(pid, &wstatus, 0) == -1) {
+				if (calpath_alloced)
+					free(calpath);
 
-		if (calendar == NULL) {
-			printf(
-				"err: no calendar specified, and default was not found or "
-				"readable\n"
-			);
-			exit(EXIT_FAILURE);
+				ERR("editor failed to spawn");
+			}
+
+			if (calpath_alloced)
+				free(calpath);
+
+			if (!WIFEXITED(wstatus) || WEXITSTATUS(wstatus))
+				ERR("editor failed to spawn or exited abnormally");
+
+			exit(EXIT_SUCCESS);
 		}
+
+		if (calpath_alloced)
+			free(calpath);
+
+		exit(EXIT_SUCCESS);
 	}
 
-	fclose(calendar);
+	/* output commands */
+	cal = fopen(calpath, "r");
+	if (cal == NULL) {
+		fprintf(stderr, "err: could not read calendar at `%s`\n", calpath);
+
+		if (calpath_alloced)
+			free(calpath);
+
+		exit(EXIT_FAILURE);
+	}
+
+	if (calpath_alloced)
+		free(calpath);
+
+	if (cmd == OPT_COMMAND_CONSOLE)
+
+	fclose(cal);
 	
 	return 0;
 }
diff --git a/src/opt.c b/src/opt.c
index eb796e7..c051388 100644
--- a/src/opt.c
+++ b/src/opt.c
@@ -1,15 +1,12 @@
-#include "version.h"
 #include "opt.h"
 
+#include "version.h"
+#include "err.h"
+
 #include "../reqs/simple-opt/simple-opt.h"
 
 #include <stdlib.h>
-
-const char *set[] = {
-	[EVERY_OPT_OUTPUTMODE_CONSOLE] = "console",
-	[EVERY_OPT_OUTPUTMODE_SCRIPT]  = "script",
-	NULL,
-};
+#include <string.h>
 
 static struct simple_opt options[] = {
 	{ SIMPLE_OPT_FLAG, 'h', "help", false,
@@ -18,16 +15,15 @@ static struct simple_opt options[] = {
 		"print the version of every in use and exit" },
 	{ SIMPLE_OPT_STRING, 'c', "calendar", true,
 		"path to calendar", "<file>" },
-	{ SIMPLE_OPT_STRING_SET, 'm', "output-mode", true,
-		"output mode (default is console)",
-		"(console|script)", set },
+	{ SIMPLE_OPT_STRING, 'e', "editor", true,
+		"text editor for editing calendars", "<file>" },
 	{ SIMPLE_OPT_END }
 };
 
+static struct simple_opt_result result;
+
 void opt_parse(int argc, char **argv)
 {
-	struct simple_opt_result result;
-
 	result = simple_opt_parse(argc, argv, options);
 
 	/* parse err */
@@ -51,11 +47,27 @@ void opt_parse(int argc, char **argv)
 		exit(EXIT_SUCCESS);
 	}
 
-	/* bad calendar path*/
-	if (options[2].was_seen && options[2].val.v_string[0] == '\0') {
-		printf("err: could not read calendar at ``\n");
-		exit(EXIT_FAILURE);
+	/* bad command */
+	if (result.argc > 0) {
+		if (result.argc > 1)
+			ERR("too many commands");
+
+		if (strlen(result.argv[0]) > 1)
+			ERR("unrecognised command `%s`", result.argv[0]);
+
+		switch (result.argv[0][0]) {
+		case 'c':
+		case 's':
+		case 'e':
+			break;
+		default:
+			ERR("unrecognised command `%s`", result.argv[0]);
+		}
 	}
+
+	/* bad calendar path */
+	if (options[2].was_seen && options[2].val.v_string[0] == '\0')
+		ERR("err: could not read calendar at ``");
 }
 
 char* opt_calpath(void)
@@ -66,10 +78,28 @@ char* opt_calpath(void)
 	return NULL;
 }
 
-enum every_opt_outputmode opt_outputmode(void)
+char* opt_editor(void)
 {
 	if (options[3].was_seen)
-		return options[3].val.v_string_set_idx;
+		return options[3].val.v_string;
+
+	return getenv("EDITOR");
+}
+
+enum every_opt_command opt_command(void)
+{
+	if (result.argc > 0) {
+		switch (result.argv[0][0]) {
+		case 'c':
+			return OPT_COMMAND_CONSOLE;
+		case 's':
+			return OPT_COMMAND_SCRIPT;
+		case 'e':
+			return OPT_COMMAND_EDIT;
+		default:
+			break;
+		}
+	}
 
-	return EVERY_OPT_OUTPUTMODE_CONSOLE;
+	return OPT_COMMAND_CONSOLE;
 }
diff --git a/src/opt.h b/src/opt.h
index f751232..4e8921a 100644
--- a/src/opt.h
+++ b/src/opt.h
@@ -1,14 +1,17 @@
 #ifndef EVERY_OPT_H
 #define EVERY_OPT_H
 
-enum every_opt_outputmode {
-	EVERY_OPT_OUTPUTMODE_CONSOLE = 0,
-	EVERY_OPT_OUTPUTMODE_SCRIPT = 1,
+enum every_opt_command {
+	OPT_COMMAND_CONSOLE = 0,
+	OPT_COMMAND_SCRIPT = 1,
+	OPT_COMMAND_EDIT = 1,
 };
 
 void opt_parse(int argc, char **argv);
 
 char* opt_calpath(void);
-enum every_opt_outputmode opt_outputmode(void);
+char* opt_editor(void);
+
+enum every_opt_command opt_command(void);
 
 #endif
-- 
cgit v1.2.3