aboutsummaryrefslogtreecommitdiff
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
parentaba5ca85720ebc98c393edd8641d14ff5a5468e5 (diff)
downloadsayeth-69c056ff6083aabf46a12779f43c3f5fa573e9b5.tar.gz
Implement art drivers as configs
-rw-r--r--CMakeLists.txt14
-rw-r--r--config.h.in6
-rw-r--r--drivers/fierrhea.art35
-rw-r--r--drivers/jenkins.art37
-rw-r--r--drivers/romero.art55
-rw-r--r--main.c289
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
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;
}