diff options
author | Ariadna Vigo <arivigodr@gmail.com> | 2020-06-19 16:03:23 +0200 |
---|---|---|
committer | Ariadna Vigo <arivigodr@gmail.com> | 2020-06-19 16:03:23 +0200 |
commit | 68a2b8706a41273b27dc3cfefbafd2c19dba7645 (patch) | |
tree | d632a5e09b8b0f360d478e46c46fb194995f9d6c /cras.c |
Initial commit
Diffstat (limited to 'cras.c')
-rw-r--r-- | cras.c | 204 |
1 files changed, 204 insertions, 0 deletions
@@ -0,0 +1,204 @@ +/* See LICENSE file for copyright and license details. */ + +#include <errno.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +static char *argv0; /* Required here by arg.h */ +#include "arg.h" +#include "tasklst.h" + +enum { + SHORT_OUTPUT, + LONG_OUTPUT +}; + +static void die(const char *fmt, ...); +static void print_short_output(TaskLst tasks); +static void print_output(TaskLst tasks); +static void read_crasfile(TaskLst *tasks, const char *crasfile); +static void write_crasfile(const char *crasfile, TaskLst tasks); +static void read_user_input(TaskLst *tasks, FILE *fp); + +static void usage(void); +static void set_tasks_mode(const char *crasfile); +static void output_mode(const char *crasfile, int mode); +static void mark_tasks_mode(const char *crasfile, const char *id, int mode); + +/* + * crasfile_path defined here just for testing. It will be moved later to + * config.(def.)h + */ +static char crasfile_path[] = "crasfile"; + +static void die(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + + vfprintf(stderr, fmt, ap); + fputc('\n', stderr); + + va_end(ap); + + exit(1); +} + +static void +print_short_output(TaskLst tasks) +{ + printf("%d/%d/%d to do/done/total\n", tasklst_tasks_todo(tasks), + tasklst_tasks_done(tasks), tasklst_tasks_total(tasks)); +} + +static void +print_output(TaskLst tasks) +{ + int i; + + printf("Tasks due for: %s\n", ctime(&tasks.expiry)); + + for(i = 0; i < TASK_LST_MAX_NUM; ++i) { + if (tasks.status[i] != TASK_VOID) + printf("#%02d [%s] %s\n", i + 1, + (tasks.status[i] == TASK_TODO) ? "TODO" : "DONE", + tasks.tdesc[i]); + } + + if (i > 0) + putchar('\n'); + + print_short_output(tasks); +} + +static void +read_crasfile(TaskLst *tasks, const char *crasfile) +{ + int read_stat; + FILE *fp; + + if ((fp = fopen(crasfile, "r")) == NULL) + die("Could not read from %s: %s", crasfile, strerror(errno)); + + read_stat = tasklst_read_from_file(tasks, fp); + fclose(fp); + + if (read_stat < 0) + die("Parsing error: task file corrupted."); + + if (tasklst_expired(*tasks) == 0) + die("Current task file expired: Set a new one!"); +} + +static void +write_crasfile(const char *crasfile, TaskLst tasks) +{ + FILE *fp; + + if ((fp = fopen(crasfile, "w")) == NULL) + die("Could not write to %s: %s", crasfile, strerror(errno)); + + tasklst_write_to_file(fp, tasks); + fclose(fp); +} + +static void +read_user_input(TaskLst *tasks, FILE *fp) +{ + char linebuf[TASK_LST_DESC_MAX_SIZE]; + int i; + + for (i = 0; i < TASK_LST_MAX_NUM; ++i) { + fgets(linebuf, TASK_LST_DESC_MAX_SIZE, fp); + if (feof(fp) != 0) + break; + + linebuf[strlen(linebuf) - 1] = '\0'; + strncpy(tasks->tdesc[i], linebuf, TASK_LST_DESC_MAX_SIZE); + tasks->status[i] = TASK_TODO; + } +} + +static void +usage(void) +{ + die("[STUB: Usage info]"); +} + +static void +set_tasks_mode(const char *crasfile) +{ + TaskLst tasks; + + tasklst_init(&tasks); + read_user_input(&tasks, stdin); /* Only stdin for now */ + + tasklst_set_expiration(&tasks); + write_crasfile(crasfile, tasks); +} + +static void +output_mode(const char *crasfile, int mode) +{ + TaskLst tasks; + + tasklst_init(&tasks); + read_crasfile(&tasks, crasfile); + + if (mode == SHORT_OUTPUT) + print_short_output(tasks); + else + print_output(tasks); +} + +static void +mark_tasks_mode(const char *crasfile, const char *id, int mode) +{ + int tasknum; + char *endptr; + TaskLst tasks; + + tasknum = strtol(id, &endptr, 10); + if (endptr[0] != '\0') + die("%s not a number", id); + + tasklst_init(&tasks); + read_crasfile(&tasks, crasfile); + + if (tasknum <= tasklst_tasks_total(tasks)) + tasks.status[tasknum - 1] = mode; + else + die("Task #%d does not exist.", tasknum); + + write_crasfile(crasfile, tasks); +} + +int +main(int argc, char *argv[]) +{ + ARGBEGIN { + case 's': + set_tasks_mode(crasfile_path); + return 0; + case 'o': + output_mode(crasfile_path, SHORT_OUTPUT); + return 0; + case 't': + mark_tasks_mode(crasfile_path, EARGF(usage()), + TASK_DONE); + return 0; + case 'T': + mark_tasks_mode(crasfile_path, EARGF(usage()), + TASK_TODO); + return 0; + default: + usage(); /* usage() dies, so nothing else needed. */ + } ARGEND; + + /* Default behavior: long-form output */ + output_mode(crasfile_path, LONG_OUTPUT); + return 0; +} |