diff options
author | Joseph Hunkeler <jhunkeler@gmail.com> | 2022-10-21 21:32:59 -0400 |
---|---|---|
committer | Joseph Hunkeler <jhunkeler@gmail.com> | 2022-10-21 21:32:59 -0400 |
commit | 69c056ff6083aabf46a12779f43c3f5fa573e9b5 (patch) | |
tree | aa9e473f1ce5af5e985f845bc5d07e71d332b5d6 /main.c | |
parent | aba5ca85720ebc98c393edd8641d14ff5a5468e5 (diff) | |
download | sayeth-69c056ff6083aabf46a12779f43c3f5fa573e9b5.tar.gz |
Implement art drivers as configs
Diffstat (limited to 'main.c')
-rw-r--r-- | main.c | 289 |
1 files changed, 240 insertions, 49 deletions
@@ -3,14 +3,23 @@ #include <stdlib.h> #include <stdarg.h> #include <unistd.h> -#include "fierrhea.h" -#include "romero.h" -#include "jenkins.h" +#include <ctype.h> +#include <dirent.h> +#include <errno.h> +#include "config.h" #define INPUT_BUFSIZ 4096 +#define DATA_BUFSIZ 8192 size_t START_Y = 0; const char *A_TAB = " "; +char box_top_left = '\0'; +char box_top = '\0'; +char box_top_right = '\0'; +char box_side = '\0'; +char box_bottom_left = '\0'; +char box_bottom = '\0'; +char box_bottom_right = '\0'; void repchar(char ch, size_t limit) { while (limit > 0) { @@ -49,26 +58,26 @@ size_t get_longest_line(char *s) { void box_draw_top(size_t y, size_t longest) { repchar(' ', y); - repchar('/', 1); - repchar('-', longest); - repchar('\\', 1); + repchar(box_top_left, 1); + repchar(box_top, longest); + repchar(box_top_right, 1); } void box_draw_bottom(size_t y, size_t longest) { repchar(' ', y); - repchar('\\', 1); - repchar('-', longest); - repchar('/', 1); + repchar(box_bottom_left, 1); + repchar(box_bottom, longest); + repchar(box_bottom_right, 1); } void box_draw_next_line(size_t y) { repchar(' ', y); - repchar('|', 1); + repchar(box_side, 1); } void box_draw_end_line(size_t longest, size_t len) { repchar(' ', longest - len); - repchar('|', 1); + repchar(box_side, 1); } int boxprintf(const char *fmt, ...) { @@ -123,35 +132,6 @@ int boxprintf(const char *fmt, ...) { return count; } -void driver_fierrhea(char *input) { - START_Y = 22; - printf("%s", FIERRHEA); - printf("\\ /\n"); - printf(" \\/\n"); - boxprintf(input); - puts(""); -} - -void driver_jenkins(char *input) { - START_Y = 18; - boxprintf(input); - puts(""); - printf(" | /\n"); - printf(" | /\n"); - printf(" |/\n"); - puts(JENKINS); -} - -void driver_romero(char *input) { - START_Y = 11; - boxprintf(input); - puts(""); - printf(" \\ |\n"); - printf(" \\ |\n"); - printf(" \\|\n"); - puts(ROMERO); -} - void usage(char *prog) { printf("usage: %s [-d driver_name] [-] {input}\n" "-h Show this help message\n" @@ -161,10 +141,190 @@ void usage(char *prog) { "input A quoted string\n", prog); } +void caret_draw(char *data, size_t indent, size_t attached) { + if (!attached) + repchar(' ', START_Y); + + for (size_t i = 0; i < strlen(data); i++) { + if (data[i] == '\\' && isalpha(data[i + 1])) { + i++; + switch (data[i]) { + case 'n': + putc('\n', stdout); + if (i < strlen(data) - 1) + i++; + repchar(' ', indent); + break; + } + } + putc(data[i], stdout); + } + puts(""); +} + + +struct Driver { + char *name; + size_t box_indent; + char *box_elements; + size_t caret_pos; + size_t caret_indent; + size_t caret_attached; + char *caret; + char *data; +}; + +struct Driver *driver_load(char *filename) { + FILE *fp = NULL; + struct Driver *driver = NULL; + + driver = calloc(1, sizeof(*driver)); + if (!driver) { + return NULL; + } + + fp = fopen(filename, "r"); + if (!fp) { + return NULL; + } + + for (size_t i = 0; i < 8; i++) { + char buf[INPUT_BUFSIZ] = {0}; + if (fgets(buf, sizeof(buf) - 1, fp) == NULL) { + break; + } + if (!strlen(buf) || buf[0] == '#') { + i--; + continue; + } + buf[strlen(buf) - 1] = '\0'; + switch (i) { + case 0: + driver->name = strdup(buf); + if (!driver->name) { + fclose(fp); + return NULL; + } + break; + case 1: + driver->box_indent = strtol(buf, NULL, 10); + break; + case 2: + driver->box_elements = strdup(buf); + if (!driver->box_elements) { + fclose(fp); + return NULL; + } + break; + case 3: + driver->caret_pos = strtol(buf, NULL, 10); + break; + case 4: + driver->caret_indent = strtol(buf, NULL, 10); + break; + case 5: + driver->caret_attached = strtol(buf, NULL, 10); + break; + case 6: + driver->caret = strdup(buf); + if (!driver->caret) { + fclose(fp); + return NULL; + } + break; + case 7: + driver->data = calloc(DATA_BUFSIZ, sizeof(*driver->data)); + if (!driver->data) { + fclose(fp); + return NULL; + } + strncpy(driver->data, buf, sizeof(buf)); + strcat(driver->data, "\n"); + fread(driver->data + strlen(driver->data), 1, DATA_BUFSIZ - 1, fp); + break; + default: + break; + } + } + fclose(fp); + return driver; +} + +struct Driver **drivers = NULL; +const size_t drivers_alloc_default = 128; +size_t drivers_alloc = drivers_alloc_default; +size_t drivers_used = 0; + +int driver_register(struct Driver *driver) { + if (!drivers) { + drivers = calloc(drivers_alloc, sizeof(**drivers)); + } + + if (drivers_used > drivers_alloc) { + struct Driver **tmp; + drivers_alloc += drivers_alloc_default; + tmp = realloc(drivers, (sizeof(**drivers) * drivers_alloc)); + if (!tmp) { + return -1; + } + drivers = tmp; + + for (size_t i = drivers_used; i < drivers_alloc; i++) { + drivers[i] = calloc(1, sizeof(*drivers[i])); + } + } + + drivers[drivers_used] = calloc(1, sizeof(*driver)); + memcpy(drivers[drivers_used], driver, sizeof(*driver)); + drivers_used++; +} + +int driver_run(struct Driver *driver, char *input) { + char *elem = driver->box_elements; + box_top_left = elem[0]; + box_top = elem[1]; + box_top_right = elem[2]; + box_side = elem[3]; + box_bottom_left = elem[4]; + box_bottom = elem[5]; + box_bottom_right = elem[6]; + START_Y = driver->box_indent; + + if (!driver->caret_pos) { + boxprintf(input); + caret_draw(driver->caret, driver->caret_indent, driver->caret_attached); + } + + printf("%s", driver->data); + + if (driver->caret_pos) { + caret_draw(driver->caret, driver->caret_indent, driver->caret_attached); + boxprintf(input); + } +} + +struct Driver *driver_lookup(char *name) { + for (size_t i = 0; drivers[i] != NULL; i++) { + if (!strcmp(drivers[i]->name, name)) { + return drivers[i]; + } + } + return NULL; +} + int main(int argc, char *argv[]) { char driver_name[255] = {0}; char input[INPUT_BUFSIZ] = {0}; - char *iptr = input; + struct Driver *driver = NULL; + char *driver_dir = getenv("SAYETH_DRIVERS"); + if (!driver_dir) { +#ifdef DRIVER_DIR + driver_dir = strdup(DRIVER_DIR); +#else + driver_dir = strdup("./drivers"); +#endif + } + // set default driver strcpy(driver_name, "fierrhea"); @@ -194,6 +354,41 @@ int main(int argc, char *argv[]) { } } + DIR *dir; + struct dirent *dp; + + dir = opendir(driver_dir); + if (!dir) { + perror(driver_dir); + exit(1); + } + + while ((dp = readdir(dir)) != NULL) { + struct Driver *drv; + char path[PATH_MAX] = {0}; + if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, driver_dir)) { + continue; + } + if (!strstr(dp->d_name, ".art")) { + continue; + } + snprintf(path, sizeof(path) - 1, "%s/%s", driver_dir, dp->d_name); + drv = driver_load(path); + if (!drv) { + fprintf(stderr, "unable to load driver: %s (%s)\n", path, strerror(errno)); + exit(1); + } + if (driver_register(drv) < 0) { + fprintf(stderr, "unable to register driver: %s (%s)\n", path, strerror(errno)); + exit(1); + } + } + + if (!drivers_used) { + fprintf(stderr, "No drivers present in '%s'?\n", driver_dir); + exit(1); + } + if (optind < argc) { strcpy(input, argv[optind]); } else { @@ -210,17 +405,13 @@ int main(int argc, char *argv[]) { input[strlen(input)] = '\n'; } - if (!strcmp(driver_name, "fierrhea")) { - driver_fierrhea(input); - } else if (!strcmp(driver_name, "jenkins")) { - driver_jenkins(input); - } else if (!strcmp(driver_name, "romero")) { - driver_romero(input); - } else { - fprintf(stderr, "invalid driver: '%s'\n", driver_name); + driver = driver_lookup(driver_name); + if (!driver) { + fprintf(stderr, "Driver not found\n"); exit(1); } + driver_run(driver, input); puts(""); return 0; } |