diff options
Diffstat (limited to 'src/todo.c')
-rw-r--r-- | src/todo.c | 211 |
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"); +} |