aboutsummaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
authorJoseph Hunkeler <jhunkeler@gmail.com>2022-10-21 21:32:59 -0400
committerJoseph Hunkeler <jhunkeler@gmail.com>2022-10-21 21:32:59 -0400
commit69c056ff6083aabf46a12779f43c3f5fa573e9b5 (patch)
treeaa9e473f1ce5af5e985f845bc5d07e71d332b5d6 /main.c
parentaba5ca85720ebc98c393edd8641d14ff5a5468e5 (diff)
downloadsayeth-69c056ff6083aabf46a12779f43c3f5fa573e9b5.tar.gz
Implement art drivers as configs
Diffstat (limited to 'main.c')
-rw-r--r--main.c289
1 files changed, 240 insertions, 49 deletions
diff --git a/main.c b/main.c
index 05c274d..adbc4bd 100644
--- a/main.c
+++ b/main.c
@@ -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;
}