hachem.wtf
aboutsummaryrefslogtreecommitdiff
path: root/todo.c
diff options
context:
space:
mode:
Diffstat (limited to 'todo.c')
-rw-r--r--todo.c110
1 files changed, 99 insertions, 11 deletions
diff --git a/todo.c b/todo.c
index 6d35169..1ac93e8 100644
--- a/todo.c
+++ b/todo.c
@@ -18,6 +18,20 @@
#define TODO_PROGRAM "todo"
#define TODO_VERSION "0.1.0"
+#define MAX_ITEMS 4096
+#define MAX_TEXT 256
+#define MAX_COMMAND 64
+#define MAX_HISTORY 64
+
+_Static_assert(MAX_ITEMS >= 1, "MAX_ITEMS must be positive");
+_Static_assert(MAX_TEXT >= 16, "MAX_TEXT too small");
+_Static_assert(MAX_COMMAND >= 8, "MAX_COMMAND too small");
+_Static_assert(MAX_HISTORY >= 1, "MAX_HISTORY must be positive");
+_Static_assert(LEFT_MARGIN >= 0, "LEFT_MARGIN must be non-negative");
+_Static_assert(SECTION_INDENT >= 0, "SECTION_INDENT must be non-negative");
+_Static_assert(SUBTASK_INDENT >= 0, "SUBTASK_INDENT must be non-negative");
+_Static_assert(WRAP_COLUMN > LEFT_MARGIN + SUBTASK_INDENT + 8, "WRAP_COLUMN too small for the indents");
+
#define CLEAR_EOL "\x1b[K"
#define CURSOR_HOME "\x1b[H"
#define CURSOR_SHOW "\x1b[?25h"
@@ -583,35 +597,56 @@ static int archive_done(struct List* list, const char* path)
if (file == NULL)
return -1;
+ bool ok = true;
int archived = 0;
- int kept = 0;
- int i = 0;
- while (i < list->count)
+ for (int i = 0; i < list->count; )
{
int end = item_block_end(list, i);
- bool drop = is_task(&list->items[i]) && list->items[i].state == STATE_DONE;
- if (drop)
+ if (is_task(&list->items[i]) && list->items[i].state == STATE_DONE)
for (int j = i; j < end; j++)
{
const struct Item* it = &list->items[j];
+ int written;
if (is_section(it) || is_note(it))
- (void) fprintf(file, "%s\n", it->text);
+ written = fprintf(file, "%s\n", it->text);
else
- (void) fprintf(file, "[%c] %s\n", state_char(it->state), it->text);
+ written = fprintf(file, "[%c] %s\n", state_char(it->state), it->text);
+
+ if (written < 0)
+ ok = false;
archived++;
}
- else
+
+ i = end;
+ }
+
+ if (ok && fflush(file) != 0)
+ ok = false;
+
+ (void) fsync(fileno(file));
+
+ if (fclose(file) != 0)
+ ok = false;
+
+ if (!ok)
+ return -1;
+
+ int kept = 0;
+ for (int i = 0; i < list->count; )
+ {
+ int end = item_block_end(list, i);
+
+ if (!(is_task(&list->items[i]) && list->items[i].state == STATE_DONE))
for (int j = i; j < end; j++)
list->items[kept++] = list->items[j];
i = end;
}
- (void) fclose(file);
list->count = kept;
return archived;
}
@@ -632,7 +667,10 @@ static int save(struct List* list, const char* path)
{
normalize_tasks(list);
- FILE* file = fopen(path, "w");
+ char tmp[4096];
+ (void) snprintf(tmp, sizeof tmp, "%s.tmp", path);
+
+ FILE* file = fopen(tmp, "w");
if (file == NULL)
return -1;
@@ -651,11 +689,22 @@ static int save(struct List* list, const char* path)
ok = false;
}
+ if (ok && fflush(file) != 0)
+ ok = false;
+
+ (void) fsync(fileno(file));
+
if (fclose(file) != 0)
ok = false;
+ if (ok && rename(tmp, path) != 0)
+ ok = false;
+
if (!ok)
+ {
+ (void) remove(tmp);
return -1;
+ }
dirty = false;
return 0;
@@ -667,6 +716,42 @@ static void commit(struct List* list)
sort_list(list);
}
+static void apply_prose(struct List* list, int skip)
+{
+ if (!PROSE)
+ return;
+
+ for (int i = 0; i < list->count; i++)
+ {
+ if (i == skip)
+ continue;
+
+ struct Item* item = &list->items[i];
+ int len = (int) strlen(item->text);
+
+ for (int c = 0; c < len; c++)
+ {
+ if (item->text[c] >= 'a' && item->text[c] <= 'z')
+ {
+ item->text[c] = (char) (item->text[c] - 32);
+ break;
+ }
+ if (item->text[c] >= 'A' && item->text[c] <= 'Z')
+ break;
+ }
+
+ if (is_section(item) || is_important(item) || len == 0)
+ continue;
+
+ char last = item->text[len - 1];
+ if (last != '.' && last != '!' && last != '?' && len + 1 < (int) sizeof item->text)
+ {
+ item->text[len] = '.';
+ item->text[len + 1] = '\0';
+ }
+ }
+}
+
struct Snapshot
{
struct Item* items;
@@ -896,7 +981,8 @@ static void restore_terminal(void)
static void on_signal(int signal_number)
{
(void) signal_number;
- exit(EXIT_SUCCESS);
+ restore_terminal();
+ _exit(EXIT_SUCCESS);
}
static int enter_raw_mode(void)
@@ -2988,6 +3074,8 @@ static void run(struct List* list, const char* path)
for (;;)
{
+ apply_prose(list, is_editing(editor.mode) ? editor.cursor : -1);
+
if (editor.cursor >= list->count)
editor.cursor = list->count - 1;
if (editor.cursor < 0)