diff options
author | wrmr | 2025-10-08 16:01:17 -0400 |
---|---|---|
committer | wrmr | 2025-10-08 16:01:17 -0400 |
commit | 8402bc583c0d3a9ff42c0a9883c6350c42ccfc18 (patch) | |
tree | 70f85e47edc44517a6a793a3b0858884d1e8d2bf | |
parent | 39aa3cfe0e44bcd91eb0dfa6899c15f248b724f0 (diff) |
various preparations for adding .cbinkrc
-rw-r--r-- | main.c | 101 | ||||
-rw-r--r-- | opt.h | 86 |
2 files changed, 148 insertions, 39 deletions
@@ -33,10 +33,12 @@ #define STR_IMPL #define STRIO_IMPL #define ARENA_IMPL +#define OPT_IMPL #include "str.h" #include "strio.h" #include "arena.h" +#include "opt.h" #define POST_LIMIT 200 /* see bink.py */ #define PAGE_LEN getmaxy(stdscr) @@ -60,24 +62,31 @@ /* colors */ -#define CPAIR_INIT_X(cp, fg, bg) init_pair(cp, fg, bg); -#define CPAIR_ENUM_X(cp, fg, bg) cp, +#define CPAIR_ENUM_X(cp, fg, bg, name) cp, +#define CPAIR_OPT_X(cp, fg_, bg_, name) opt.color[cp] = (ColorOpt) { .fg = fg_, .bg = bg_ }; +#define CPAIR_INIT_X(cp, fg_, bg_, name) init_pair(cp, opt.color[cp].fg, opt.color[cp].bg); +#define COLOR_NORM -1 +#define COLOR_FG COLOR_NORM +#define COLOR_BG COLOR_NORM #define CPAIR_LIST(X)\ - X(CPAIR_TEXT , COLOR_WHITE , COLOR_BLACK)\ - X(CPAIR_MENTION , COLOR_BLACK , COLOR_WHITE)\ - X(CPAIR_USER , COLOR_YELLOW , COLOR_BLACK)\ - X(CPAIR_PRONOUNS , COLOR_CYAN , COLOR_BLACK)\ - X(CPAIR_TIME , COLOR_BLUE , COLOR_BLACK)\ - X(CPAIR_PFP , COLOR_BLUE , COLOR_BLACK)\ - X(CPAIR_PFP_SELF , COLOR_YELLOW , COLOR_BLACK)\ - X(CPAIR_BANNER , COLOR_WHITE , COLOR_BLACK)\ - X(CPAIR_BORDER , COLOR_BLUE , COLOR_BLACK)\ - X(CPAIR_TAGLINE_OK , COLOR_GREEN , COLOR_BLACK)\ - X(CPAIR_TAGLINE_WARN , COLOR_YELLOW , COLOR_BLACK)\ - X(CPAIR_TAGLINE_ERR , COLOR_RED , COLOR_BLACK) + X(CPAIR_TEXT , COLOR_FG , COLOR_BG, "text")\ + X(CPAIR_MENTION , COLOR_BG , COLOR_FG, "mention")\ + X(CPAIR_USER , COLOR_YELLOW , COLOR_BG, "user")\ + X(CPAIR_PRONOUNS , COLOR_CYAN , COLOR_BG, "pronouns")\ + X(CPAIR_TIME , COLOR_BLUE , COLOR_BG, "time")\ + X(CPAIR_PFP , COLOR_BLUE , COLOR_BG, "pfp")\ + X(CPAIR_PFP_SELF , COLOR_YELLOW , COLOR_BG, "pfp.self")\ + X(CPAIR_BANNER , COLOR_FG , COLOR_BG, "banner")\ + X(CPAIR_BORDER , COLOR_BLUE , COLOR_BG, "border")\ + X(CPAIR_MSG_OK , COLOR_GREEN , COLOR_BG, "msg.ok")\ + X(CPAIR_MSG_WARN , COLOR_YELLOW , COLOR_BG, "msg.warn")\ + X(CPAIR_MSG_ERR , COLOR_RED , COLOR_BG, "msg.err") typedef enum { + /* not all curses implementation allow modifying cpair 0 */ + CPAIR_UNUSED, CPAIR_LIST(CPAIR_ENUM_X) + CPAIR_MAX } ColorPair; /* dynamic arrays */ @@ -132,12 +141,18 @@ int utf8_cp_to_byte(Str s, int dest) { /* options */ typedef struct { + int fg, bg; +} ColorOpt; + +typedef struct { struct { int pfp, pronouns; } see; struct { int left, right, top, bottom; } margin; + int default_colors; + ColorOpt color[CPAIR_MAX]; } Options; /* globals */ @@ -151,27 +166,28 @@ Options opt = { .margin = { .left = 0, .right = 0 - } + }, + .default_colors = 1 }; -/* tagline & logging */ +/* msg & logging */ -#define TAGLINE_MAX 1024 -char tagline[TAGLINE_MAX] = { 0 }; +#define MSG_MAX 1024 +char msg[MSG_MAX] = { 0 }; typedef enum { - TAGLINE_OK, - TAGLINE_WARN, - TAGLINE_ERR + MSG_OK, + MSG_WARN, + MSG_ERR } TaglineStatus; -TaglineStatus tagline_status = TAGLINE_OK; +TaglineStatus msg_status = MSG_OK; -void tagline_set(const char *fmt, ...) { +void msg_set(const char *fmt, ...) { va_list ap; va_start(ap, fmt); - vsnprintf(tagline, TAGLINE_MAX - 1, fmt, ap); + vsnprintf(msg, MSG_MAX - 1, fmt, ap); va_end(ap); - tagline_status = TAGLINE_OK; + msg_status = MSG_OK; } void log_warn(const char *fmt, ...) { @@ -179,9 +195,9 @@ void log_warn(const char *fmt, ...) { va_start(ap, fmt); beep(); flash(); - vsnprintf(tagline, TAGLINE_MAX - 1, fmt, ap); + vsnprintf(msg, MSG_MAX - 1, fmt, ap); va_end(ap); - tagline_status = TAGLINE_WARN; + msg_status = MSG_WARN; } void log_err(const char *fmt, ...) { @@ -189,11 +205,11 @@ void log_err(const char *fmt, ...) { flash(); va_list ap; va_start(ap, fmt); - vsnprintf(tagline, TAGLINE_MAX - 1, fmt, ap); - size_t n = strlen(tagline); - snprintf(tagline + n, TAGLINE_MAX - n - 1, ": %s", strerror(errno)); + vsnprintf(msg, MSG_MAX - 1, fmt, ap); + size_t n = strlen(msg); + snprintf(msg + n, MSG_MAX - n - 1, ": %s", strerror(errno)); va_end(ap); - tagline_status = TAGLINE_ERR; + msg_status = MSG_ERR; } /* string conversion */ @@ -820,13 +836,14 @@ void init_curses(void) { setlocale(LC_ALL, ""); initscr(); start_color(); - init_color(COLOR_BLACK, 0, 0, 0); + init_color(COLOR_BG, 0, 0, 0); cbreak(); noecho(); intrflush(stdscr, FALSE); keypad(stdscr, TRUE); curs_set(0); + if (opt.default_colors) use_default_colors(); CPAIR_LIST(CPAIR_INIT_X) } @@ -835,6 +852,11 @@ void fini_curses(void) { endwin(); } +void load_config(void) { + CPAIR_LIST(CPAIR_OPT_X) + /* TODO: load cbinkrc */ +} + /* main */ int main(void) { @@ -856,6 +878,7 @@ int main(void) { "([ \t\n]+|^)[@~]?%s([:;,.!? \t\n]|$)", getlogin()), REG_EXTENDED | REG_ICASE | REG_NOSUB); + load_config(); init_curses(); posts_refresh(&posts, &post_arena); @@ -868,13 +891,13 @@ int main(void) { arena_reset(&temp_arena); gfx_draw(&gfx, cur, &temp_arena); - switch (tagline_status) { - case TAGLINE_OK: color_set(CPAIR_TAGLINE_OK, 0); break; - case TAGLINE_WARN: color_set(CPAIR_TAGLINE_WARN, 0); break; - case TAGLINE_ERR: color_set(CPAIR_TAGLINE_ERR, 0); break; + switch (msg_status) { + case MSG_OK: color_set(CPAIR_MSG_OK, 0); break; + case MSG_WARN: color_set(CPAIR_MSG_WARN, 0); break; + case MSG_ERR: color_set(CPAIR_MSG_ERR, 0); break; } - mvaddstr(getmaxy(stdscr) - 1, getmaxx(stdscr) - strlen(tagline), tagline); - tagline[0] = '\0'; + mvaddstr(getmaxy(stdscr) - 1, getmaxx(stdscr) - strlen(msg), msg); + msg[0] = '\0'; int ch = getch(); if (ch == 'q') break; @@ -932,7 +955,7 @@ int main(void) { refresh: arena_reset(&post_arena); posts_refresh(&posts, &post_arena); - tagline_set("%zu users, %zu posts, %zums", post_stats.user_count, post_stats.post_count, + msg_set("%zu users, %zu posts, %zums", post_stats.user_count, post_stats.post_count, post_stats.gather_ns / 1000000); goto resize; case '\t': @@ -0,0 +1,86 @@ +#ifndef OPT_H +#define OPT_H + +#define OPT_ARG 1 +#define OPT_AT_END 0 +#define OPT_ERR_NO_PARAM -1 +#define OPT_ERR_BAD_OPT -2 + +#define OPTF_MID_SHORT 1 +#define OPTF_IGNORE 2 +#define OPTF_NO_PRINT_ERR 4 + +/* fmt is a set of short option chars, preceded by : if they accept an + * argument, followed by [foo] for a corresponding long option name. */ + +int opt_next(int *optf, int *argc, const char ***argv, const char *fmt); + +#ifdef OPT_IMPL + +#include <stdio.h> +#include <string.h> +#include <assert.h> + +int opt_next(int *optf, int *argc, const char ***argv, const char *fmt) { + if (~*optf & OPTF_MID_SHORT) { + *argv += 1, *argc -= 1; + if (*argc < 1) return OPT_AT_END; + } + if (*optf & OPTF_IGNORE) return OPT_ARG; + + int is_long = 0; + if (~*optf & OPTF_MID_SHORT) { + if ((**argv)[0] != '-') return OPT_ARG; + is_long = (**argv)[1] == '-'; + if (is_long && !(**argv)[2]) { + *optf |= OPTF_IGNORE; + return opt_next(optf, argc, argv, fmt); + } + } + + const char *opt = **argv + is_long + !(*optf & OPTF_MID_SHORT); + const char *opt_end = is_long ? strchr(opt, '=') : opt + 1; + if (!opt_end) opt_end = opt + strlen(opt); + unsigned opt_len = opt_end - opt; + + int opt_arg = 0, match = 0; + char opt_char = '\0'; + while (*fmt && !match) { + opt_arg = (*fmt == ':'); + if (opt_arg) fmt++; + opt_char = *fmt++; + assert(opt_char); + match = !is_long && *opt == opt_char; + if (*fmt == '[') { + const char *rt = strchr(++fmt, ']'); + assert(rt); + match |= is_long && rt-fmt == opt_len && !memcmp(opt, fmt, opt_len); + fmt = rt + 1; + } + } + + *optf &= ~OPTF_MID_SHORT; + if (match && opt_arg) { + if (*opt_end) { + **argv = opt_end + is_long; + } else { + *argv += 1, *argc -= 1; + if (*argc > 0) return opt_char; + if (~*optf & OPTF_NO_PRINT_ERR) { + fprintf(stderr, "option '%.*s' expected parameter, but none given\n", opt_len, opt); + } + return OPT_ERR_NO_PARAM; + } + } else if (!is_long && *opt_end) { + *optf |= OPTF_MID_SHORT; + **argv = opt_end; + } + + if (!match && ~*optf & OPTF_NO_PRINT_ERR) { + fprintf(stderr, "unrecognized option '%.*s'\n", opt_len, opt); + } + return match ? opt_char : OPT_ERR_BAD_OPT; +} + +#endif +#endif |