summaryrefslogtreecommitdiff
path: root/src/todo.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/todo.c')
-rw-r--r--src/todo.c211
1 files changed, 211 insertions, 0 deletions
diff --git a/src/todo.c b/src/todo.c
new file mode 100644
index 0000000..8d6334f
--- /dev/null
+++ b/src/todo.c
@@ -0,0 +1,211 @@
+/* This file is a part of todo
+ *
+ * Copyright (C) 2021 Robby Zambito
+ *
+ * todo is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * todo is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#define _GNU_SOURCE
+
+#include <errno.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static FILE *todo_file;
+
+static void puts_strikethrough(char *text) {
+ static const char *strike_overlay = "\u0336";
+ if (text != NULL) {
+ while (*text != '\0') {
+ printf("%s%c", strike_overlay, *text);
+ text++;
+ }
+ puts("");
+ }
+}
+
+static void apply_func_to_line(void (*func)(char *), size_t index) {
+ char *line = NULL;
+ size_t line_len = 0;
+
+ errno = 0;
+ todo_file = fopen("TODO", "r");
+ if (todo_file == NULL) {
+ perror("Could not open the TODO file");
+ exit(EXIT_FAILURE);
+ }
+
+ errno = 0;
+ FILE *temp_file = fopen(".TODO", "w");
+ if (temp_file == NULL) {
+ perror("Could not open temp TODO file");
+ exit(EXIT_FAILURE);
+ }
+
+ for (size_t i = 1; getline(&line, &line_len, todo_file) >= 0; i++) {
+ if (i == index) {
+ func(line);
+ }
+ fprintf(temp_file, "%s", line);
+ free(line);
+ }
+
+ fclose(todo_file);
+ fclose(temp_file);
+
+ // Clobber old TODO with new .TODO
+ rename(".TODO", "TODO");
+}
+
+void todo_list(void) {
+ static const char *bold_text = "\e[1m";
+ static const char *regular_text = "\e[0m";
+
+ char *line = NULL;
+ size_t line_len = 0;
+
+ errno = 0;
+ todo_file = fopen("TODO", "r");
+ if (todo_file == NULL) {
+ if (errno == ENOENT) {
+ // If the file doesn't exist, the list is simply empty
+ exit(EXIT_SUCCESS);
+ } else {
+ perror("Could not open TODO file");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ for (size_t i = 0; getline(&line, &line_len, todo_file) >= 0; i++) {
+ // Remove trailing newline by setting it to NULL char.
+ line[strcspn(line, "\n")] = '\0';
+
+ if (line_len > 5) {
+ // Print the index in bold
+ printf("%s%zu%s ", bold_text, i + 1, regular_text);
+
+ // Print the task with a strikethrough if completed
+ if (line[1] == ' ') {
+ puts(line + 4);
+ } else if (line[1] == '*') {
+ puts_strikethrough(line + 4);
+ }
+ }
+
+ free(line);
+ }
+
+ fclose(todo_file);
+}
+
+void todo_add(int argc, char **argv) {
+ if (argc < 1) {
+ fprintf(stderr, "todo add takes at least 1 argument\n");
+ exit(EXIT_FAILURE);
+ }
+
+ errno = 0;
+ todo_file = fopen("TODO", "a");
+ if (todo_file == NULL) {
+ perror("Could not open the TODO file");
+ exit(EXIT_FAILURE);
+ }
+
+ for (int i = 0; i < argc; i++) {
+ fprintf(todo_file, "[ ] %s\n", argv[i]);
+ }
+
+ fclose(todo_file);
+}
+
+static void blank(char *task) { task[0] = '\0'; }
+
+void todo_rm(int argc, char **argv) {
+ if (argc < 1) {
+ fprintf(stderr, "todo rm takes at least 1 argument\n");
+ exit(EXIT_FAILURE);
+ }
+
+ size_t remove_index = -1;
+
+ errno = 0;
+ sscanf(argv[0], "%zu", &remove_index);
+ if (errno != 0 || remove_index < 1) {
+ perror("Could not parse index");
+ exit(EXIT_FAILURE);
+ }
+
+ apply_func_to_line(blank, remove_index);
+}
+
+static void done(char *task) { task[1] = '*'; }
+
+void todo_done(int argc, char **argv) {
+ if (argc < 1) {
+ fprintf(stderr, "todo done takes at least 1 argument\n");
+ exit(EXIT_FAILURE);
+ }
+
+ size_t done_index = -1;
+
+ errno = 0;
+ sscanf(argv[0], "%zu", &done_index);
+ if (errno != 0 || done_index < 1) {
+ perror("Could not parse index");
+ exit(EXIT_FAILURE);
+ }
+
+ apply_func_to_line(done, done_index);
+}
+
+void todo_raw(int argc, char **argv) {
+ /*open_todo_file();*/
+ puts("raw");
+ fclose(todo_file);
+}
+
+void todo_sort(void) {
+ /*open_todo_file();*/
+ puts("sort");
+ fclose(todo_file);
+}
+
+void todo_help(void) {
+ puts("Usage: todo [COMMAND] [ARGUMENTS]\n"
+ "Todo is a super fast and simple tasks organizer written in C.\n"
+ "Example: todo list\n"
+ "Available commands:\n"
+ " - add [TASK/s]\n"
+ " adds new task/s\n"
+ " Example: todo add \"buy carrots\"\n"
+ " - list\n"
+ " lists all tasks\n"
+ " Example: todo list\n"
+ " - done [INDEX]\n"
+ " marks task as done\n"
+ " Example: todo done 2 3 (marks second and third tasks as "
+ "completed)\n"
+ " - rm [INDEX]\n"
+ " removes a task\n"
+ " Example: todo rm 4\n"
+ " - sort\n"
+ " sorts completed and uncompleted tasks\n"
+ " Example: todo sort\n"
+ " - raw [todo/done]\n"
+ " prints nothing but done/incompleted tasks in plain text, "
+ "useful for scripting\n"
+ " Example: todo raw done\n");
+}