main.c (4846B)
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <libterm.h> 4 5 #include "util.h" 6 #include "post.h" 7 #include "edit.h" 8 9 #define UNUSED(x) (void)(x) 10 11 char *POET_DB = NULL; 12 13 bool do_edit_post(int id) { 14 post_t *post = db_post_get(POET_DB, id); 15 char filename[100]; 16 snprintf(filename, 100, "poet-%d.md", post->id); 17 edit_write(filename, post); 18 term_write("\x1b[?25h"); 19 term_flush(); 20 char *editor = getenv("EDITOR"); 21 if (editor == NULL) { 22 editor = "vim"; 23 } 24 char command[200]; 25 snprintf(command, 200, "%s %s", editor, filename); 26 system(command); 27 term_write("\x1b[?25l"); 28 term_write("\x1b[?1049h"); 29 term_flush(); 30 post_t *changes = NULL; 31 edit_read(filename, &changes); 32 bool changed = post_changed(post, changes); 33 if (changed) { 34 db_post_update(POET_DB, id, post, changes); 35 } 36 post_free(changes); 37 post_free(post); 38 return changed; 39 } 40 41 bool do_toggle_post(int id) { 42 post_t *post = db_post_get(POET_DB, id); 43 post_t *changes = malloc(sizeof(post_t)); 44 post_init(changes); 45 changes->is_public = malloc(sizeof(bool)); 46 *changes->is_public = !*post->is_public; 47 db_post_update(POET_DB, post->id, post, changes); 48 post_free(changes); 49 post_free(post); 50 return true; 51 } 52 53 int main(void) { 54 POET_DB = getenv("POET_DB"); 55 if (POET_DB == NULL) { 56 printf("Environment variable 'POET_DB' needs to be set!\n"); 57 return 1; 58 } 59 term_enable_raw_mode(); 60 term_write("\x1b[?25l"); 61 term_write("\x1b[?1049h"); 62 bool quit = false; 63 bool update = true; 64 bool render = true; 65 int index = 0; 66 int offset = 0; 67 int height = 0; 68 post_result_t *post_result = NULL; 69 while (!quit) { 70 int rows = 0; 71 int cols = 0; 72 term_read_window_size(&rows, &cols); 73 if (rows - 4 != height) { 74 if (index > rows - 4) { 75 offset = index - (rows - 4) + 1; 76 } 77 else { 78 offset = 0; 79 } 80 render = true; 81 } 82 height = rows - 4; 83 if (update) { 84 post_result = db_post_search(POET_DB, ""); 85 update = false; 86 } 87 if (render) { 88 term_write("\x1b[H"); 89 term_write("\x1b[K\r\n q = quit, j/k = move, g = goto, n = create, i = edit, d = delete, x = public/private\x1b[K\r\n\x1b[K\r\n"); 90 for (int i = 0; i < post_result->len; i++) { 91 if (i == height) { 92 break; 93 } 94 post_t *post = &post_result->result[i + offset]; 95 if (i + offset == index) { 96 term_write(" \x1b[38;2;255;221;71m>>\x1b[39m "); 97 } 98 else { 99 term_write(" "); 100 } 101 if (*post->is_public) { 102 term_writef("\x1b[38;2;255;255;255m%s\x1b[39m", post->title); 103 } 104 else { 105 term_writef("%s", post->title); 106 } 107 char *date = util_format_json_date(post->date, "%Y-%m-%d"); 108 term_writef(" \x1b[38;2;124;182;84m(%s)\x1b[39m\x1b[K\r\n", date); 109 free(date); 110 } 111 term_write("\x1b[J"); 112 term_flush(); 113 render = false; 114 } 115 int c = term_poll_key(500); 116 switch (c) { 117 case 'q': { 118 quit = true; 119 break; 120 } 121 case 'j': { 122 if (index + 1 < post_result->len) { 123 index++; 124 if (index - offset == height) { 125 offset++; 126 } 127 render = true; 128 } 129 break; 130 } 131 case 'k': { 132 if (index > 0) { 133 index--; 134 if (index < offset) { 135 offset--; 136 } 137 render = true; 138 } 139 break; 140 } 141 case 'i': { 142 if (do_edit_post(post_result->result[index].id)) { 143 update = true; 144 } 145 render = true; 146 break; 147 } 148 case 'd': { 149 // TODO delete 150 break; 151 } 152 case 'n': { 153 // TODO create 154 break; 155 } 156 case '/': { 157 // TODO search 158 break; 159 } 160 case 'x': { 161 if (do_toggle_post(post_result->result[index].id)) { 162 update = true; 163 render = true; 164 } 165 break; 166 } 167 case 'g': { 168 int c = term_read_key(); 169 switch (c) { 170 case 'e': { 171 if (post_result->len > 1) { 172 index = post_result->len - 1; 173 if (index > height) { 174 offset = index - height + 1; 175 } 176 } 177 else { 178 index = 0; 179 offset = 0; 180 } 181 render = true; 182 break; 183 } 184 case 'g': { 185 index = 0; 186 offset = 0; 187 render = true; 188 break; 189 } 190 default: 191 break; 192 } 193 break; 194 } 195 default: 196 break; 197 } 198 } 199 if (post_result != NULL) { 200 post_result_free(post_result); 201 } 202 term_write("\x1b[3J"); 203 term_write("\x1b[2J"); 204 term_write("\x1b[?25h"); 205 term_write("\x1b[H"); 206 term_write("\x1b[?1049l"); 207 term_flush(); 208 return 0; 209 }