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 | |
parent | aba5ca85720ebc98c393edd8641d14ff5a5468e5 (diff) | |
download | sayeth-69c056ff6083aabf46a12779f43c3f5fa573e9b5.tar.gz |
Implement art drivers as configs
-rw-r--r-- | CMakeLists.txt | 14 | ||||
-rw-r--r-- | config.h.in | 6 | ||||
-rw-r--r-- | drivers/fierrhea.art | 35 | ||||
-rw-r--r-- | drivers/jenkins.art | 37 | ||||
-rw-r--r-- | drivers/romero.art | 55 | ||||
-rw-r--r-- | main.c | 289 |
6 files changed, 386 insertions, 50 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index f6c6069..819e8d1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,4 +3,16 @@ project(sayeth C) set(CMAKE_C_STANDARD 99) -add_executable(sayeth main.c fierrhea.h jenkins.h romero.h) +add_executable(sayeth main.c) +set(DRIVER_DIR ${CMAKE_INSTALL_PREFIX}/share/${CMAKE_PROJECT_NAME}) + +option(DEV_ENABLE "Developer mode" OFF) +if(DEV_ENABLE) + set(DRIVER_DIR ${CMAKE_SOURCE_DIR}/drivers) +endif() + +configure_file(config.h.in config.h @ONLY) +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +install(TARGETS sayeth DESTINATION bin) +install(DIRECTORY drivers DESTINATION ${DRIVER_DIR}) diff --git a/config.h.in b/config.h.in new file mode 100644 index 0000000..257cfa0 --- /dev/null +++ b/config.h.in @@ -0,0 +1,6 @@ +#ifndef SAYETH_CONFIG_H +#define SAYETH_CONFIG_H + +#cmakedefine DRIVER_DIR "@DRIVER_DIR@" + +#endif //SAYETH_CONFIG_H diff --git a/drivers/fierrhea.art b/drivers/fierrhea.art new file mode 100644 index 0000000..643fbde --- /dev/null +++ b/drivers/fierrhea.art @@ -0,0 +1,35 @@ +# Driver name +fierrhea +# Box Indent +22 +# Box elements (top-left, top, top-right, sides, bottom-left, bottom-right) +/-\|\-/ +# Box caret pos (0=above, 1=below) +1 +# Box caret indent +21 +# Box caret attached to art (0=no, 1=yes) +1 +# Box caret +\ /\n \/ +# Data + ,▌ + ▄▓ + ÆJ▓ , + Æ ▀█▄ ██ + ▐ ▄▓▄▀█▄, █▐█ + █ █▌██ `▓ █ ▐▓ + ▐▌ ▐█ ▀▀██▀ ▀█, + ╒█▄▄▄▄▄,█ █ ▐█ ╒█ ▀µ ,█ + █ ▀ ,▀▀` ▐██ █æ▀'▄ + ▐▄ ═▀▀▄▄╦▓▓▌▀`▀ⁿw ▀ + ▐` æ'` ▓▓▓', ¬r' V ▐ + ▄P Æ ` '' ▄ ,▀ + F Æ 4▀▀▓ ▀▀ ▄ ▄▀ + █ █ ]█N` ▀█ⁿ ,, ▐ '▌ ▄▄m + █ ▐█ ╘▀' ╙▀² /// ▌ ▌ ,▓══ +▄ⁿHÅ█,╙ ╟ ╒A█▓R▄ ```⌐`█w,▄W' +▀M▀▄ ▀█▄▄'Y ▀▓▓▌ ┌ < Æ √` + ╙m'`▀▀ ╙w ` ,∞ ,, + ⁿw, ,+²' + `
\ No newline at end of file diff --git a/drivers/jenkins.art b/drivers/jenkins.art new file mode 100644 index 0000000..275f561 --- /dev/null +++ b/drivers/jenkins.art @@ -0,0 +1,37 @@ +# Driver name +jenkins +# Box Indent +19 +# Box elements (top-left, top, top-right, sides, bottom-left, bottom-right) +/-\|\-/ +# Box caret pos (0=above, 1=below) +0 +# Box caret indent +19 +# Box caret attached to art (0=no, 1=yes) +0 +# Box caret +\n| /\n| /\n|/ +# Data + ┌╓╓┌ + ▄▄▓▀▀╙└└└▀▀▀▄┌ + ▄▀▄▓▀ ░░░░░░░░░░▀█┐ + ▓▀▌▓▌░░┌▄▀╛░░░░░░▀▀█─ + █╫▓▓▓▀░░╨░░░╥░░░─░░▐ ▌ + ██▓▓▓▓ ░░░░░▄▄▓░░▀░┌▄▌█ + ╫▌▐▓▄▀╜░░░░░ └ ░░░▀▄░░█ + █░─ ░░░░░░░░░╒┌┌▄╫╜▐▌ + ▀▓█ ░░░░░░ ░╪▄█▄▄▓▀█▒ + █─░░╨▄ ░░▐▀╪╪╧ ╥█▒ + ▒▓██▄┌░ ▀▄▄┌┌┌▄▄▓███▓▒ +▓██▓▓▓▓██▀▄▌▒▀████▀▒▒█▓▓█ +█▓▓▓▓▓▓▓▓▓▓▌╫╫▒█▀▀▓▓▓█▓▓▌ +██▓▓▓▓▓▓▓▓▓█▓▓▀▒▓▐▐▒▄█▓█ +╫█▓▓▓▓▓▓▌▓▓▓█▓▄▄▒▓▐▓▓▓█▒▓▓█─ +██▌▓▓▓▓████▀▀▀▀▀▀████▀▌▀▄ █ + ▀█▓▓▓▓▓█ ░▓▓█ ▌ ╚┌ ▐▌ + █▓▓▓▓▓█ ░█▓█▄▀▄▄▄▄▓─ + ╙▀▀███▌ ░▌▀▌ + █ ░▌░█ + └▌ ░█▀└ + ╙▀▀▀▀▀▀└
\ No newline at end of file diff --git a/drivers/romero.art b/drivers/romero.art new file mode 100644 index 0000000..226c639 --- /dev/null +++ b/drivers/romero.art @@ -0,0 +1,55 @@ +# Driver name +romero +# Box Indent +11 +# Box elements (top-left, top, top-right, sides, bottom-left, bottom-right) +/-\|\-/ +# Box caret pos (0=above, 1=below) +0 +# Box caret indent +11 +# Box caret attached to art (0=no, 1=yes) +0 +# Box caret +\n \ |\n \ |\n \| +# Data + ▒╫▄╦ ▒╫▓▄▄▓▓▓▄▓▒╦╦▄▓▓▒╩ ╫▓▓▒▒╫ + ╫▓▓▓▓▒ ╦▓▓▓▓▓▓██▓▓▓▓▓██▓▓░▓▓▓▓▓▓▓▀▓ + └ ╦▓▓▓▓▓▓▒▄▓█▓██████████████▄▓████▓▓▄▓▄▒▒╨ + ▒▒╦┌▒▒╦╦▓▓█▓▓▓▓▓▓███████████████▓▓███████▓▓▓▓▓▒╥ + ╦ ╫▀▓▓▓▓█████▓▓█████████████████▓███████▓▓▓▓▓▓▓▓▓▓▀╙ + ╫▓▓▓▓██████████████████████████▓███████▓▓▓███████╬ + ▐▓▓█████████████████████████████████████████████▓▓▀▒▒░ + ╥▓▓██████████████████████▓███████████████████████▓▓▓╨┘ + ▓▓▄╥╓╥▓█▓██████████████████████████████████████▓███████▓▓▓▄╦▄╗▄ + ▓▓▓▓▓█▓▓█▓██████████████████████████████████████████▓▓██████▓▓▓▓▓▓▓▓▓▄▄╦╥ + ╥▀█████████████▓██████▓█▓▓▓▓▓▓▓▓▓▓▓▓▓████████████████████▓▓█████▓╫▒ ╥▓▓█▓▓▀▀╫ + ░░▓███████████████▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓█████████████▓▓▓▓▓████▓▓▓████▓▓▒▒▒▒ + ╥╫▓██████████████▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓██████████▓▓▓██████████▓▓▓▌░ + ▒▓▓█████████████▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓███████████████████▓▓▓▓▒╦░ + ╘╫▓████████████▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓╫▓▓▓▓▓▓▓▓▓▓███████████▓▓▓▓▓▓█▓▓▓╫▒▒▒▒ + ╦▒▓▓██████████▓▓▓▓▓▓▓▓▓▓╫╫▒╫╫▓╫▓▓▓▓▓▓▓▓▓▓▓▓▓▓╫▓▓▓▓▓▓▓▀▓▓▓██▓██████▓█████▓▓▓▒▒▒ + ╫▓▓▓███████▓████████▓▓▓▓╫╫╫▒╫▒▒▒▒▒▒▒╫╫▓╫▒╫▒╫▓▓▓▓▓▓▓╫╫▓▓▓▓▓▓▓███▓▓▓████▓▓▓▒ + ╨▓█▓▓█████████▓▓▓▓██████▓▓▓▓▒▒▒╫▓▓▓▓▓▓▓▓▓╫▒▒╫▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓████▓▓▒ + ▒▓▓█████████████▓▓█▓████▓▓▓╫╫▓▓▓▓████████▓▓▓╫╫╫▓▓▓▓██████▓█████▓█████▓▓▓▒ + ╝▓▓█████████▓▓▓█████████▓▓▓▓▓▓▓▓▓▓█▓█▓▓▓███▓▄▒▓▓▓███████████▓███████▓▓▓▒ + ▀██████▓█████████▓██▓▓▓▓▓▓███▓▓█▓▀▓▓█████▓▓▓╫▓▓████████▓▓▓▓▓██████▓▀▒ + ╘▓██▓▓▓▓▓█▓████▓▓▓▓▓▓▓▒╫▓▓▓██▓▓▓▓▓███████▓▓▓▓▓▓█████████▓▓██████▓▓▓▓▒ + ╫▓█▓▓▓▓▓▓▓▓▓▓▓██▓▓▓▓▓▓▓▓▓▓▓▓▓████▓██▓█████▓▓█▓▓██████████████▓▓▓▓▓▓▒ + ▓█▓▓▓▓▓▓▓▓▓▓█████▓▓▓██▓▓▓▓▓▀▓▓▓██████▓▓▓▓▓▓▓▓▓█████████████████▓▓▓▓╜ + ▓███▓▓▓▓▓▓▓▓▓▓███████████▓▓▓▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓████████████▓▀▀╨ ╨ + ▓███▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒╫▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓██████████▓▓▓▓▒ + ═████▓▓▓▓▓██████▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓╫▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓██████████▓▓▓▓ + ▓███▓▓▓█████▀█▀██████▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓█▓█▓█▓▓▓▓▓▓▓▓██▓▓▓▓▀╩ + ▓███▓▓▓███▓▓▓▓╫▓▓▒╫▓▀╫███▓▓▓▓▓▓▓▓███▓████▓█████▓▓▓▓▓▓█▓▒▓▓▓░ + ▐███▓▓▓▓█████████▓██▄▓▒▓██▓▓▓▓▓▓▓█████▓████▓█▓▓▓▓╫▓▓▓▓▓ ▀▀ + ███▓▓████████████████████▓▓▓▓▓▓████▓▓▓█████▓▓▓▓▓▓▓▓▀╨╨ + ███▓▓██████▓███████████▓▓▓▓▓▓▓███▓▓▓▓▓████▓▓▓▓▓▓▓▀╩ + ▓████▓██████████████████▓▓▓▓▓▓██▓▓▓▓▓██▓▓▓▓▓▓▓▓▒ + ████▓▓▓▓▓█████▓▓▓▓█▓▓▓▓▓▓▓▓▓██▓▓▓▓▓▓█▓▓██▓▓▓▓▓▓░ + ▓███████▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓█▓▓▓▓▓▓█████████▓▓▓▓ + █████▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓██████████▓▓▓▓▓ + ▓███████████████████████████████▓▓▓▓╩ ╙╨░╨╩▀▓▓▒ + █████████████████████████████▓▓▓▓▓▓▌ ╨╩ + ████████▓▓▓▓███████████████▓▓▓▓▓▓▓▓▌ + ▄▓▓█▓▄▓████████▓▓▓▓▓╫▓▓▓▓▓▓▓▓▓██▓▓▓▓▓▓▓▓▓▓▓╦
\ No newline at end of file @@ -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; } |