From 7e044fb8d9fa9d0ae8835849f123535ae859017f Mon Sep 17 00:00:00 2001 From: wrmr Date: Sat, 18 Oct 2025 14:32:38 -0400 Subject: yep --- main.c | 43 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 6 deletions(-) (limited to 'main.c') diff --git a/main.c b/main.c index a94c446..c803a95 100644 --- a/main.c +++ b/main.c @@ -73,6 +73,7 @@ X(CPAIR_DEFAULT , COLOR_FG , COLOR_BG, A_NORMAL , "default")\ X(CPAIR_TEXT , COLOR_FG , COLOR_BG, A_NORMAL , "text")\ X(CPAIR_MENTION , COLOR_FG , COLOR_BG, A_REVERSE, "mention")\ + X(CPAIR_HELP , COLOR_FG , COLOR_BG, A_REVERSE, "help")\ X(CPAIR_USER , COLOR_YELLOW , COLOR_BG, A_NORMAL , "user")\ X(CPAIR_PRONOUNS , COLOR_CYAN , COLOR_BG, A_NORMAL , "pronouns")\ X(CPAIR_DATE , COLOR_BLUE , COLOR_BG, A_NORMAL , "date")\ @@ -680,12 +681,48 @@ void gfx_draw_post(GfxPost *post, int y, int x, int width, Arena *scratch) { } } +void gfx_draw_msg(void) { + switch (msg_status) { + case MSG_OK: use_color(CPAIR_MSG_OK); break; + case MSG_WARN: use_color(CPAIR_MSG_WARN); break; + case MSG_ERR: use_color(CPAIR_MSG_ERR); break; + } + mvaddstr(getmaxy(stdscr) - 1, getmaxx(stdscr) - strlen(msg), msg); +} + +void gfx_draw_help(Arena *scratch) { + use_color(CPAIR_HELP); + //const char *help_src = "[c]reate [r]efresh [q]uit [?]help | scrolling: arrows, j/k, (ctrl-)d/u, space, page up/down"; + /*const char *help_src = "[c]reate [r]efresh [q]uit [?]help" + " [up/k]prev [down/j]next" + " [space]pagedown [b]pageup" + " [u]halfup [d]halfdown" + ;*/ + const char *help_src = "[c]reate [e]dit [r]efresh [q]uit" + " | scrolling: arrows, j/k, b/space, page up/down, (ctrl-)d/u"; + Str wrapped = { 0 }; + str_cat_wrap(&wrapped, str_from_cstr(help_src), getmaxx(stdscr), scratch); + int line_count = 0; + for (Str src = wrapped, line = { 0 }; next_line(&src, &line);) line_count++; + int y = getmaxy(stdscr) - line_count; + for (Str src = wrapped, line = { 0 }; next_line(&src, &line);) { + mvaddnstr(y++, 0, line.s, line.n); + for (int i = getmaxx(stdscr); i > line.n; i--) { + addch(' '); + } + } +} + void gfx_draw(Gfx *gfx, int cur, Arena *scratch) { erase(); for (int i = cur, y = opt.margin.top; i < gfx->len && y < getmaxy(stdscr) - opt.margin.bottom; i++) { gfx_draw_post(&gfx->posts[i], y, post_left_margin(gfx->posts[i].src), gfx_post_width(gfx->posts[i].src), scratch); y += gfx_post_height(&gfx->posts[i]) + GFX_POST_SPACING; } + if (opt.cbink.help) { + gfx_draw_help(scratch); + } + gfx_draw_msg(); } /* maybe should write an ui layer to not have to deal with all the manual layout stuff */ @@ -1178,12 +1215,6 @@ int main(void) { arena_reset(&temp_arena); gfx_draw(&gfx, cur, &temp_arena); - switch (msg_status) { - case MSG_OK: use_color(CPAIR_MSG_OK); break; - case MSG_WARN: use_color(CPAIR_MSG_WARN); break; - case MSG_ERR: use_color(CPAIR_MSG_ERR); break; - } - mvaddstr(getmaxy(stdscr) - 1, getmaxx(stdscr) - strlen(msg), msg); msg[0] = '\0'; int ch = getch(); -- cgit v1.2.3 From 0910ec32835a3dfa6d9266ae7330a1b7864492d2 Mon Sep 17 00:00:00 2001 From: wrmr Date: Sun, 19 Oct 2025 15:54:45 -0400 Subject: add long help message --- main.c | 127 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 114 insertions(+), 13 deletions(-) (limited to 'main.c') diff --git a/main.c b/main.c index c803a95..6b5e229 100644 --- a/main.c +++ b/main.c @@ -690,18 +690,108 @@ void gfx_draw_msg(void) { mvaddstr(getmaxy(stdscr) - 1, getmaxx(stdscr) - strlen(msg), msg); } -void gfx_draw_help(Arena *scratch) { +void init_curses(void); +void fini_curses(void); + +const char *help_long = + "KEY BINDINGS\n" + "\n" + " c create post\n" + " e edit post\n" + " r refresh posts list\n" + " i view info of post author\n" + " p edit your profile picture\n" + " v view post in external pager\n" + " q quit cbink\n" + " ? open this help\n" + " Tab toggle profile pictures\n" + " g scroll to top\n" + " G scroll to bottom\n" + " j/Down next post\n" + " k/Up prev post\n" + " PageDown/Space next page\n" + " PageUp/b prev page\n" + " u/Ctrl-u half-page up\n" + " d/Ctrl-d half-page down\n" + "\n" + "CONFIGURATION\n" + "\n" + "~/.cbinkrc is an INI-style config file, with [sections], #comments, and key=value pairs.\n" + "\n" + "The sections are as follows:\n" + "\n" + " [cbink]\n" + "\n" + " help = 1 | 0 enable or disable the short help banner\n" + " pfp = 1 | 0 enable or disable profile pictures\n" + " pronouns = 1 | 0 enable or disable user pronouns in posts\n" + " date = 1 | 0 enable or disable post timestamps\n" + " datefmt = ... configure the timestamp format; see date(1) or strftime(1)\n" + "\n" + " [margin]\n" + "\n" + " left = N margin at left of screen\n" + " right = N margin at right of screen\n" + " top = N margin at top of screen\n" + " bottom = N margin at bottom of screen\n" + " text.x = N horizontal margin around post text\n" + " text.y = N vertical margin around post text\n" + " pfp = N margin between profile picture and post\n" + "\n" + " [color]\n" + "\n" + " All values in the color section have the same format ([ATTR1,...]FG[:BG]) --- a\n" + " foreground color, optionally followed by a colon and a background color, optionally\n" + " with comma-separated attributes.\n" + "\n" + " Foreground and background colors can be default, black, red, green, yellow, blue,\n" + " magenta, cyan, white, and hexadecimal RGB (#RRGGBB) if the terminal supports it.\n" + "\n" + " Attributes can be standout (highlighted), underline, blink, dim, bold, and italic.\n" + "\n" + " Color keys:\n" + "\n" + " default configure what 'default' means in foreground/background\n" + " text normal post text\n" + " mention text in a post that mentions you\n" + " help short help banner at bottom of screen\n" + " user post author username\n" + " pronouns post author pronouns\n" + " date post timestamp\n" + " pfp pfp of other users\n" + " pfp.self your own pfp\n" + " banner banner in user profile\n" + " border border around posts\n" + " msg.ok successful\n" + " msg.warn unsuccessful but correct\n" + " msg.err error occurred\n" + "\n" + "FILES\n" + "\n" + " ~/.cbinkrc\n" + " configuration and styling\n" + "\n" + " ~/.binkbanner\n" + " user profile banner image\n" + "\n" + " ~/.binkpfp\n" + " user profile picture\n" + "\n" + " ~/.pronouns\n" + " user pronouns\n" + "\n" + " ~/.bink\n" + " directory of posts\n" + "\n" + ; + +const char *help_short = "[c]reate [e]dit [r]efresh [q]uit [?]help" + " | scrolling: arrows, j/k, b/space, page up/down, (ctrl-)d/u"; + +void gfx_draw_help_banner(Arena *scratch) { use_color(CPAIR_HELP); - //const char *help_src = "[c]reate [r]efresh [q]uit [?]help | scrolling: arrows, j/k, (ctrl-)d/u, space, page up/down"; - /*const char *help_src = "[c]reate [r]efresh [q]uit [?]help" - " [up/k]prev [down/j]next" - " [space]pagedown [b]pageup" - " [u]halfup [d]halfdown" - ;*/ - const char *help_src = "[c]reate [e]dit [r]efresh [q]uit" - " | scrolling: arrows, j/k, b/space, page up/down, (ctrl-)d/u"; Str wrapped = { 0 }; - str_cat_wrap(&wrapped, str_from_cstr(help_src), getmaxx(stdscr), scratch); + str_cat_wrap(&wrapped, str_from_cstr(help_short), getmaxx(stdscr), scratch); int line_count = 0; for (Str src = wrapped, line = { 0 }; next_line(&src, &line);) line_count++; int y = getmaxy(stdscr) - line_count; @@ -720,7 +810,7 @@ void gfx_draw(Gfx *gfx, int cur, Arena *scratch) { y += gfx_post_height(&gfx->posts[i]) + GFX_POST_SPACING; } if (opt.cbink.help) { - gfx_draw_help(scratch); + gfx_draw_help_banner(scratch); } gfx_draw_msg(); } @@ -840,8 +930,6 @@ char *get_editor(void) { return editor; } -void init_curses(void); -void fini_curses(void); int edit_file(const char *path, Arena *temp) { fini_curses(); int r = system(cstr_fmt(temp, "%s %s", get_editor(), path)); @@ -1182,6 +1270,16 @@ int load_config(Arena *perm, Arena *temp) { /* main */ +void view_long_help(void) { + fini_curses(); + FILE *f = popen("less", "w"); + if (f) { + fputs(help_long, f); + pclose(f); + } + init_curses(); +} + int main(void) { /* init */ @@ -1294,6 +1392,9 @@ resize: gfx_draw_user(posts.data[cur].user, &temp_arena); (void)getch(); break; + case '?': + view_long_help(); + break; } } -- cgit v1.2.3 From 363b31c57d7f0f2f9667162305a0b9aee97ae745 Mon Sep 17 00:00:00 2001 From: wrmr Date: Sun, 19 Oct 2025 15:55:30 -0400 Subject: remove redundant return --- main.c | 1 - 1 file changed, 1 deletion(-) (limited to 'main.c') diff --git a/main.c b/main.c index 6b5e229..fb35759 100644 --- a/main.c +++ b/main.c @@ -1101,7 +1101,6 @@ int sect_cbink(Str k, Str v, Arena *perm) { PROP_BOOL("pronouns", &opt.cbink.pronouns); PROP_BOOL("date", &opt.cbink.date); return -1; - return -1; } int sect_margin(Str k, Str v, Arena *perm) { -- cgit v1.2.3 From a8914fc5064cbb94c257dfbca5d04e4013e67184 Mon Sep 17 00:00:00 2001 From: wrmr Date: Sun, 19 Oct 2025 15:57:45 -0400 Subject: typo --- main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'main.c') diff --git a/main.c b/main.c index fb35759..7e94c56 100644 --- a/main.c +++ b/main.c @@ -698,7 +698,7 @@ const char *help_long = "\n" " c create post\n" " e edit post\n" - " r refresh posts list\n" + " r refresh post list\n" " i view info of post author\n" " p edit your profile picture\n" " v view post in external pager\n" -- cgit v1.2.3 From 6630b94145dfdd01b4fdbb8791b219d7325d9b1e Mon Sep 17 00:00:00 2001 From: wrmr Date: Sun, 19 Oct 2025 16:10:00 -0400 Subject: combine both uses of less(1) into page_string(Str) --- main.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'main.c') diff --git a/main.c b/main.c index 7e94c56..eae3605 100644 --- a/main.c +++ b/main.c @@ -1269,12 +1269,15 @@ int load_config(Arena *perm, Arena *temp) { /* main */ -void view_long_help(void) { +void page_string(Str txt) { fini_curses(); - FILE *f = popen("less", "w"); + /* -c to prevent screen-not-fully-cleared weirdness */ + FILE *f = popen("less -c", "w"); if (f) { - fputs(help_long, f); + fwrite(txt.s, 1, txt.n, f); pclose(f); + } else { + log_err("failed to open less"); } init_curses(); } @@ -1383,16 +1386,14 @@ resize: gfx_load(&gfx, &posts, &gfx_arena); break; case 'v': - fini_curses(); - system(cstr_fmt(&temp_arena, "less %s", posts.data[cur].path)); - init_curses(); + page_string(posts.data[cur].text); break; case 'i': gfx_draw_user(posts.data[cur].user, &temp_arena); (void)getch(); break; case '?': - view_long_help(); + page_string(str_from_cstr(help_long)); break; } } -- cgit v1.2.3 From 8319b3054d87575cce28c539d45315695853e7f6 Mon Sep 17 00:00:00 2001 From: wrmr Date: Sun, 19 Oct 2025 17:10:00 -0400 Subject: remove some articles from help_long --- main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'main.c') diff --git a/main.c b/main.c index eae3605..2e3eb4a 100644 --- a/main.c +++ b/main.c @@ -722,11 +722,11 @@ const char *help_long = "\n" " [cbink]\n" "\n" - " help = 1 | 0 enable or disable the short help banner\n" + " help = 1 | 0 enable or disable short help banner\n" " pfp = 1 | 0 enable or disable profile pictures\n" " pronouns = 1 | 0 enable or disable user pronouns in posts\n" " date = 1 | 0 enable or disable post timestamps\n" - " datefmt = ... configure the timestamp format; see date(1) or strftime(1)\n" + " datefmt = ... configure timestamp format; see date(1) or strftime(1)\n" "\n" " [margin]\n" "\n" -- cgit v1.2.3 From f5fe1e20391c2631e8823578ec14500443a0de31 Mon Sep 17 00:00:00 2001 From: wrmr Date: Sun, 19 Oct 2025 17:13:28 -0400 Subject: tweak keybind help --- main.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'main.c') diff --git a/main.c b/main.c index 2e3eb4a..150e453 100644 --- a/main.c +++ b/main.c @@ -696,23 +696,23 @@ void fini_curses(void); const char *help_long = "KEY BINDINGS\n" "\n" - " c create post\n" - " e edit post\n" - " r refresh post list\n" - " i view info of post author\n" - " p edit your profile picture\n" - " v view post in external pager\n" - " q quit cbink\n" - " ? open this help\n" - " Tab toggle profile pictures\n" - " g scroll to top\n" - " G scroll to bottom\n" - " j/Down next post\n" - " k/Up prev post\n" - " PageDown/Space next page\n" - " PageUp/b prev page\n" - " u/Ctrl-u half-page up\n" - " d/Ctrl-d half-page down\n" + " c create post\n" + " e edit post\n" + " r refresh post list\n" + " i view info of post author\n" + " p edit your profile picture\n" + " v view post in external pager\n" + " q quit cbink\n" + " ? open this help\n" + " Tab toggle profile pictures\n" + " g scroll to top\n" + " G scroll to bottom\n" + " j/Down post down\n" + " k/Up post up\n" + " PgDn/Space page down\n" + " PgUp/b page up\n" + " d/Ctrl-d half-page down\n" + " u/Ctrl-u half-page up\n" "\n" "CONFIGURATION\n" "\n" -- cgit v1.2.3 From be75e7e2363cf7d26a86efde1bf64983c70c8262 Mon Sep 17 00:00:00 2001 From: wrmr Date: Sun, 19 Oct 2025 19:40:06 -0400 Subject: help tweak --- main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'main.c') diff --git a/main.c b/main.c index 150e453..41071fe 100644 --- a/main.c +++ b/main.c @@ -749,7 +749,7 @@ const char *help_long = "\n" " Attributes can be standout (highlighted), underline, blink, dim, bold, and italic.\n" "\n" - " Color keys:\n" + " Keys in this section:\n" "\n" " default configure what 'default' means in foreground/background\n" " text normal post text\n" -- cgit v1.2.3 From d6348a4ba833f99b049766574628c23943a60e97 Mon Sep 17 00:00:00 2001 From: wrmr Date: Sun, 19 Oct 2025 20:06:04 -0400 Subject: print newline at program end to scroll down --- main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'main.c') diff --git a/main.c b/main.c index 41071fe..9276093 100644 --- a/main.c +++ b/main.c @@ -1407,6 +1407,7 @@ resize: arena_free(&temp_arena); fini_curses(); + puts(""); return 0; } -- cgit v1.2.3 From 468d82256a4e7172ef305923167853452a248554 Mon Sep 17 00:00:00 2001 From: wrmr Date: Sun, 19 Oct 2025 20:44:58 -0400 Subject: support both # and ; comments in cbinkrc --- main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'main.c') diff --git a/main.c b/main.c index 9276093..dc4069e 100644 --- a/main.c +++ b/main.c @@ -1248,9 +1248,9 @@ int load_config(Arena *perm, Arena *temp) { continue; } if (!fn) continue; - line = str_trim(line); + line = str_trim(str_cut(line, '#').head); + line = str_trim(str_cut(line, ';').head); if (!line.n) continue; - if (line.s[0] == '#') continue; Cut c = str_cut(line, '='); c.head = str_trim(c.head); c.tail = str_trim(c.tail); -- cgit v1.2.3 From f343df5e72712d83722485f770a0e6cb7f651717 Mon Sep 17 00:00:00 2001 From: wrmr Date: Mon, 20 Oct 2025 22:17:15 -0400 Subject: pop pronouns off todo (done a while ago) --- main.c | 1 - 1 file changed, 1 deletion(-) (limited to 'main.c') diff --git a/main.c b/main.c index dc4069e..25c086b 100644 --- a/main.c +++ b/main.c @@ -5,7 +5,6 @@ /* TODO: * - * - read ~user/.pronouns and put next to name * - add keybind to view info about a user, like .plan, .project etc * - maybe remove ncurses dependency * - consider setting up a proper log file for log_warn / log_err stuff -- cgit v1.2.3 From 0148fc9cf70e836348c48a75c8da5103ad11aa4a Mon Sep 17 00:00:00 2001 From: wrmr Date: Tue, 21 Oct 2025 15:28:58 -0400 Subject: add -c/--config option --- main.c | 51 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 44 insertions(+), 7 deletions(-) (limited to 'main.c') diff --git a/main.c b/main.c index 25c086b..b31a0af 100644 --- a/main.c +++ b/main.c @@ -153,6 +153,9 @@ typedef struct { } ColorOpt; typedef struct { + struct { + const char *cbinkrc; + } cmdline; struct { int help; int pfp, pronouns, date; @@ -692,7 +695,19 @@ void gfx_draw_msg(void) { void init_curses(void); void fini_curses(void); +#define USAGE "cbink [-c CONFIG]" + const char *help_long = + + "USAGE\n" + "\n" + " " USAGE "\n" + "\n" + "OPTIONS\n" + "\n" + " -c --config config file to use instead of default, or NONE\n" + "\n" + "KEY BINDINGS\n" "\n" " c create post\n" @@ -768,6 +783,7 @@ const char *help_long = "FILES\n" "\n" " ~/.cbinkrc\n" + " ~/.config/cbink/cbinkrc\n" " configuration and styling\n" "\n" " ~/.binkbanner\n" @@ -1051,13 +1067,20 @@ void fini_curses(void) { /* configuration */ FILE *open_config_file(Arena *a) { - const char *s = cstr_fmt(a, "/home/%s/.cbinkrc", getlogin()); - FILE *f = fopen(s, "r/o"); - if (f) return f; - s = cstr_fmt(a, "/home/%s/.config/cbink/cbinkrc", getlogin()); + FILE *f; + const char *s = opt.cmdline.cbinkrc; + if (s) { + if (!strcmp(s, "NONE")) { + return NULL; + } + } else { + s = cstr_fmt(a, "/home/%s/.cbinkrc", getlogin()); + f = fopen(s, "r/o"); + if (f) return f; + s = cstr_fmt(a, "/home/%s/.config/cbink/cbinkrc", getlogin()); + } f = fopen(s, "r/o"); - if (f) return f; - return NULL; + return f; } typedef struct { @@ -1281,7 +1304,7 @@ void page_string(Str txt) { init_curses(); } -int main(void) { +int main(int argc, const char **argv) { /* init */ Arena cfg_arena = { 0 }; @@ -1292,6 +1315,20 @@ int main(void) { arena_reserve(&post_arena, 128 << 10L); arena_reserve(&gfx_arena, 128 << 10L); + int optf = 0; + for (;;) { + int o = opt_next(&optf, &argc, &argv, ":c[config]"); + if (!o) break; + switch (o) { + case 'c': + opt.cmdline.cbinkrc = *argv; + break; + default: + fprintf(stderr, "Usage: " USAGE "\n"); + return 1; + } + } + ensure_dotbink_exists(&temp_arena); PostList posts = { 0 }; -- cgit v1.2.3