From fba5083b5896a8ec209e188017914a5850770113 Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 13 Jul 2026 19:32:28 +0000 Subject: [PATCH 1/2] Add hooks to customize mode. --- options-table.c | 255 ++++++++++++++++++++++++++++----------------- window-customize.c | 123 ++++++++++++++++++---- 2 files changed, 263 insertions(+), 115 deletions(-) diff --git a/options-table.c b/options-table.c index a36901dcb..ddbb9404d 100644 --- a/options-table.c +++ b/options-table.c @@ -1,4 +1,4 @@ -/* $OpenBSD: options-table.c,v 1.235 2026/07/13 15:03:03 nicm Exp $ */ +/* $OpenBSD: options-table.c,v 1.236 2026/07/13 19:32:28 nicm Exp $ */ /* * Copyright (c) 2011 Nicholas Marriott @@ -240,33 +240,40 @@ static const char *options_table_status_format_default[] = { }; /* Helpers for hook options. */ -#define OPTIONS_TABLE_HOOK(hook_name, default_value) \ +#define OPTIONS_TABLE_HOOK(hook_name, default_value, hook_text) \ { .name = hook_name, \ .type = OPTIONS_TABLE_COMMAND, \ .scope = OPTIONS_TABLE_SESSION, \ .flags = OPTIONS_TABLE_IS_ARRAY|OPTIONS_TABLE_IS_HOOK, \ .default_str = default_value, \ - .separator = "" \ + .separator = "", \ + .text = hook_text \ } -#define OPTIONS_TABLE_PANE_HOOK(hook_name, default_value) \ +#define OPTIONS_TABLE_PANE_HOOK(hook_name, default_value, hook_text) \ { .name = hook_name, \ .type = OPTIONS_TABLE_COMMAND, \ .scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE, \ .flags = OPTIONS_TABLE_IS_ARRAY|OPTIONS_TABLE_IS_HOOK, \ .default_str = default_value, \ - .separator = "" \ + .separator = "", \ + .text = hook_text \ } -#define OPTIONS_TABLE_WINDOW_HOOK(hook_name, default_value) \ +#define OPTIONS_TABLE_WINDOW_HOOK(hook_name, default_value, hook_text) \ { .name = hook_name, \ .type = OPTIONS_TABLE_COMMAND, \ .scope = OPTIONS_TABLE_WINDOW, \ .flags = OPTIONS_TABLE_IS_ARRAY|OPTIONS_TABLE_IS_HOOK, \ .default_str = default_value, \ - .separator = "" \ + .separator = "", \ + .text = hook_text \ } +#define OPTIONS_TABLE_AFTER_HOOK(command_name) \ + OPTIONS_TABLE_HOOK("after-" command_name, "", \ + "Run after the " command_name " command completes.") + /* Map of name conversions. */ const struct options_name_map options_other_names[] = { { "display-panes-color", "display-panes-colour" }, @@ -1882,95 +1889,151 @@ const struct options_table_entry options_table[] = { }, /* Hook options. */ - OPTIONS_TABLE_HOOK("after-bind-key", ""), - OPTIONS_TABLE_HOOK("after-capture-pane", ""), - OPTIONS_TABLE_HOOK("after-copy-mode", ""), - OPTIONS_TABLE_HOOK("after-display-message", ""), - OPTIONS_TABLE_HOOK("after-display-panes", ""), - OPTIONS_TABLE_HOOK("after-kill-pane", ""), - OPTIONS_TABLE_HOOK("after-list-buffers", ""), - OPTIONS_TABLE_HOOK("after-list-clients", ""), - OPTIONS_TABLE_HOOK("after-list-keys", ""), - OPTIONS_TABLE_HOOK("after-list-panes", ""), - OPTIONS_TABLE_HOOK("after-list-sessions", ""), - OPTIONS_TABLE_HOOK("after-list-windows", ""), - OPTIONS_TABLE_HOOK("after-load-buffer", ""), - OPTIONS_TABLE_HOOK("after-lock-server", ""), - OPTIONS_TABLE_HOOK("after-new-session", ""), - OPTIONS_TABLE_HOOK("after-new-window", ""), - OPTIONS_TABLE_HOOK("after-paste-buffer", ""), - OPTIONS_TABLE_HOOK("after-pipe-pane", ""), - OPTIONS_TABLE_HOOK("after-queue", ""), - OPTIONS_TABLE_HOOK("after-refresh-client", ""), - OPTIONS_TABLE_HOOK("after-rename-session", ""), - OPTIONS_TABLE_HOOK("after-rename-window", ""), - OPTIONS_TABLE_HOOK("after-resize-pane", ""), - OPTIONS_TABLE_HOOK("after-resize-window", ""), - OPTIONS_TABLE_HOOK("after-save-buffer", ""), - OPTIONS_TABLE_HOOK("after-select-layout", ""), - OPTIONS_TABLE_HOOK("after-select-pane", ""), - OPTIONS_TABLE_HOOK("after-select-window", ""), - OPTIONS_TABLE_HOOK("after-send-keys", ""), - OPTIONS_TABLE_HOOK("after-set-buffer", ""), - OPTIONS_TABLE_HOOK("after-set-environment", ""), - OPTIONS_TABLE_HOOK("after-set-hook", ""), - OPTIONS_TABLE_HOOK("after-set-option", ""), - OPTIONS_TABLE_HOOK("after-show-environment", ""), - OPTIONS_TABLE_HOOK("after-show-messages", ""), - OPTIONS_TABLE_HOOK("after-show-options", ""), - OPTIONS_TABLE_HOOK("after-split-window", ""), - OPTIONS_TABLE_HOOK("after-unbind-key", ""), - OPTIONS_TABLE_HOOK("alert-activity", ""), - OPTIONS_TABLE_HOOK("alert-bell", ""), - OPTIONS_TABLE_HOOK("alert-silence", ""), - OPTIONS_TABLE_HOOK("client-active", ""), - OPTIONS_TABLE_HOOK("client-attached", ""), - OPTIONS_TABLE_HOOK("client-created", ""), - OPTIONS_TABLE_HOOK("client-closed", ""), - OPTIONS_TABLE_HOOK("client-detached", ""), - OPTIONS_TABLE_HOOK("client-focus-in", ""), - OPTIONS_TABLE_HOOK("client-focus-out", ""), - OPTIONS_TABLE_HOOK("client-resized", ""), - OPTIONS_TABLE_HOOK("client-session-changed", ""), - OPTIONS_TABLE_HOOK("client-light-theme", ""), - OPTIONS_TABLE_HOOK("client-dark-theme", ""), - OPTIONS_TABLE_HOOK("command-error", ""), - OPTIONS_TABLE_HOOK("marked-pane-changed", ""), - OPTIONS_TABLE_PANE_HOOK("pane-activity", ""), - OPTIONS_TABLE_PANE_HOOK("pane-bell", ""), - OPTIONS_TABLE_PANE_HOOK("pane-command-finished", ""), - OPTIONS_TABLE_PANE_HOOK("pane-command-started", ""), - OPTIONS_TABLE_PANE_HOOK("pane-created", ""), - OPTIONS_TABLE_PANE_HOOK("pane-died", ""), - OPTIONS_TABLE_PANE_HOOK("pane-exited", ""), - OPTIONS_TABLE_PANE_HOOK("pane-focus-in", ""), - OPTIONS_TABLE_PANE_HOOK("pane-focus-out", ""), - OPTIONS_TABLE_PANE_HOOK("pane-mode-changed", ""), - OPTIONS_TABLE_PANE_HOOK("pane-mode-entered", ""), - OPTIONS_TABLE_PANE_HOOK("pane-mode-exited", ""), - OPTIONS_TABLE_PANE_HOOK("pane-moved", ""), - OPTIONS_TABLE_PANE_HOOK("pane-prompt-closed", ""), - OPTIONS_TABLE_PANE_HOOK("pane-prompt-opened", ""), - OPTIONS_TABLE_PANE_HOOK("pane-resized", ""), - OPTIONS_TABLE_PANE_HOOK("pane-set-clipboard", ""), - OPTIONS_TABLE_PANE_HOOK("pane-shell-prompt", ""), - OPTIONS_TABLE_PANE_HOOK("pane-title-changed", ""), - OPTIONS_TABLE_HOOK("session-closed", ""), - OPTIONS_TABLE_HOOK("session-created", ""), - OPTIONS_TABLE_HOOK("session-added-to-group", ""), - OPTIONS_TABLE_HOOK("session-renamed", ""), - OPTIONS_TABLE_HOOK("session-removed-from-group", ""), - OPTIONS_TABLE_HOOK("session-window-changed", ""), - OPTIONS_TABLE_WINDOW_HOOK("window-created", ""), - OPTIONS_TABLE_WINDOW_HOOK("window-closed", ""), - OPTIONS_TABLE_WINDOW_HOOK("window-layout-changed", ""), - OPTIONS_TABLE_HOOK("window-linked", ""), - OPTIONS_TABLE_WINDOW_HOOK("window-pane-changed", ""), - OPTIONS_TABLE_WINDOW_HOOK("window-renamed", ""), - OPTIONS_TABLE_WINDOW_HOOK("window-resized", ""), - OPTIONS_TABLE_WINDOW_HOOK("window-unzoomed", ""), - OPTIONS_TABLE_WINDOW_HOOK("window-zoomed", ""), - OPTIONS_TABLE_HOOK("window-unlinked", ""), + OPTIONS_TABLE_AFTER_HOOK("bind-key"), + OPTIONS_TABLE_AFTER_HOOK("capture-pane"), + OPTIONS_TABLE_AFTER_HOOK("copy-mode"), + OPTIONS_TABLE_AFTER_HOOK("display-message"), + OPTIONS_TABLE_AFTER_HOOK("display-panes"), + OPTIONS_TABLE_AFTER_HOOK("kill-pane"), + OPTIONS_TABLE_AFTER_HOOK("list-buffers"), + OPTIONS_TABLE_AFTER_HOOK("list-clients"), + OPTIONS_TABLE_AFTER_HOOK("list-keys"), + OPTIONS_TABLE_AFTER_HOOK("list-panes"), + OPTIONS_TABLE_AFTER_HOOK("list-sessions"), + OPTIONS_TABLE_AFTER_HOOK("list-windows"), + OPTIONS_TABLE_AFTER_HOOK("load-buffer"), + OPTIONS_TABLE_AFTER_HOOK("lock-server"), + OPTIONS_TABLE_AFTER_HOOK("new-session"), + OPTIONS_TABLE_AFTER_HOOK("new-window"), + OPTIONS_TABLE_AFTER_HOOK("paste-buffer"), + OPTIONS_TABLE_AFTER_HOOK("pipe-pane"), + OPTIONS_TABLE_AFTER_HOOK("refresh-client"), + OPTIONS_TABLE_AFTER_HOOK("rename-session"), + OPTIONS_TABLE_AFTER_HOOK("rename-window"), + OPTIONS_TABLE_AFTER_HOOK("resize-pane"), + OPTIONS_TABLE_AFTER_HOOK("resize-window"), + OPTIONS_TABLE_AFTER_HOOK("save-buffer"), + OPTIONS_TABLE_AFTER_HOOK("select-layout"), + OPTIONS_TABLE_AFTER_HOOK("select-pane"), + OPTIONS_TABLE_AFTER_HOOK("select-window"), + OPTIONS_TABLE_AFTER_HOOK("send-keys"), + OPTIONS_TABLE_AFTER_HOOK("set-buffer"), + OPTIONS_TABLE_AFTER_HOOK("set-environment"), + OPTIONS_TABLE_AFTER_HOOK("set-hook"), + OPTIONS_TABLE_AFTER_HOOK("set-option"), + OPTIONS_TABLE_AFTER_HOOK("show-environment"), + OPTIONS_TABLE_AFTER_HOOK("show-messages"), + OPTIONS_TABLE_AFTER_HOOK("show-options"), + OPTIONS_TABLE_AFTER_HOOK("split-window"), + OPTIONS_TABLE_AFTER_HOOK("unbind-key"), + OPTIONS_TABLE_HOOK("alert-activity", "", + "Run when a window has activity."), + OPTIONS_TABLE_HOOK("alert-bell", "", + "Run when a window has received a bell."), + OPTIONS_TABLE_HOOK("alert-silence", "", + "Run when a window has been silent."), + OPTIONS_TABLE_HOOK("client-active", "", + "Run when a client becomes the latest active client of its " + "session."), + OPTIONS_TABLE_HOOK("client-attached", "", + "Run when a client is attached."), + OPTIONS_TABLE_HOOK("client-created", "", + "Run when a client is created."), + OPTIONS_TABLE_HOOK("client-closed", "", + "Run when a client is closed."), + OPTIONS_TABLE_HOOK("client-detached", "", + "Run when a client is detached."), + OPTIONS_TABLE_HOOK("client-focus-in", "", + "Run when focus enters a client."), + OPTIONS_TABLE_HOOK("client-focus-out", "", + "Run when focus exits a client."), + OPTIONS_TABLE_HOOK("client-resized", "", + "Run when a client is resized."), + OPTIONS_TABLE_HOOK("client-session-changed", "", + "Run when a client's attached session is changed."), + OPTIONS_TABLE_HOOK("client-light-theme", "", + "Run when a client switches to a light theme."), + OPTIONS_TABLE_HOOK("client-dark-theme", "", + "Run when a client switches to a dark theme."), + OPTIONS_TABLE_HOOK("command-error", "", + "Run when a command fails."), + OPTIONS_TABLE_HOOK("marked-pane-changed", "", + "Run when the marked pane is set or cleared."), + OPTIONS_TABLE_PANE_HOOK("pane-activity", "", + "Run when there is new output in a pane."), + OPTIONS_TABLE_PANE_HOOK("pane-bell", "", + "Run when a pane receives a bell."), + OPTIONS_TABLE_PANE_HOOK("pane-command-finished", "", + "Run when an OSC 133 command finishes in a pane."), + OPTIONS_TABLE_PANE_HOOK("pane-command-started", "", + "Run when an OSC 133 command starts in a pane."), + OPTIONS_TABLE_PANE_HOOK("pane-created", "", + "Run when a pane is created or respawned."), + OPTIONS_TABLE_PANE_HOOK("pane-died", "", + "Run when the program running in a pane exits, but remain-on-exit " + "is on so the pane has not closed."), + OPTIONS_TABLE_PANE_HOOK("pane-exited", "", + "Run when the program running in a pane exits."), + OPTIONS_TABLE_PANE_HOOK("pane-focus-in", "", + "Run when the focus enters a pane, if the focus-events option is " + "on."), + OPTIONS_TABLE_PANE_HOOK("pane-focus-out", "", + "Run when the focus exits a pane, if the focus-events option is " + "on."), + OPTIONS_TABLE_PANE_HOOK("pane-mode-changed", "", + "Run when a pane changes mode."), + OPTIONS_TABLE_PANE_HOOK("pane-mode-entered", "", + "Run when a pane enters a mode."), + OPTIONS_TABLE_PANE_HOOK("pane-mode-exited", "", + "Run when a pane exits a mode."), + OPTIONS_TABLE_PANE_HOOK("pane-moved", "", + "Run when a pane is moved to another window."), + OPTIONS_TABLE_PANE_HOOK("pane-prompt-closed", "", + "Run when a prompt in a pane is closed."), + OPTIONS_TABLE_PANE_HOOK("pane-prompt-opened", "", + "Run when a prompt is opened in a pane."), + OPTIONS_TABLE_PANE_HOOK("pane-resized", "", + "Run when a pane is resized."), + OPTIONS_TABLE_PANE_HOOK("pane-set-clipboard", "", + "Run when the terminal clipboard is set using the xterm escape " + "sequence."), + OPTIONS_TABLE_PANE_HOOK("pane-shell-prompt", "", + "Run when an OSC 133 shell prompt starts in a pane."), + OPTIONS_TABLE_PANE_HOOK("pane-title-changed", "", + "Run when a pane title is changed."), + OPTIONS_TABLE_HOOK("session-closed", "", + "Run when a session is closed."), + OPTIONS_TABLE_HOOK("session-created", "", + "Run when a new session is created."), + OPTIONS_TABLE_HOOK("session-added-to-group", "", + "Run when a session is added to a session group."), + OPTIONS_TABLE_HOOK("session-renamed", "", + "Run when a session is renamed."), + OPTIONS_TABLE_HOOK("session-removed-from-group", "", + "Run when a session is removed from a session group."), + OPTIONS_TABLE_HOOK("session-window-changed", "", + "Run when a session changes its active window."), + OPTIONS_TABLE_WINDOW_HOOK("window-created", "", + "Run when a window is created."), + OPTIONS_TABLE_WINDOW_HOOK("window-closed", "", + "Run when a window is closed."), + OPTIONS_TABLE_WINDOW_HOOK("window-layout-changed", "", + "Run when a window layout is changed."), + OPTIONS_TABLE_HOOK("window-linked", "", + "Run when a window is linked into a session."), + OPTIONS_TABLE_WINDOW_HOOK("window-pane-changed", "", + "Run when a window changes its active pane."), + OPTIONS_TABLE_WINDOW_HOOK("window-renamed", "", + "Run when a window is renamed."), + OPTIONS_TABLE_WINDOW_HOOK("window-resized", "", + "Run when a window is resized. This may be after the " + "client-resized hook is run."), + OPTIONS_TABLE_WINDOW_HOOK("window-unzoomed", "", + "Run when a window is unzoomed."), + OPTIONS_TABLE_WINDOW_HOOK("window-zoomed", "", + "Run when a window is zoomed."), + OPTIONS_TABLE_HOOK("window-unlinked", "", + "Run when a window is unlinked from a session."), { .name = NULL } }; diff --git a/window-customize.c b/window-customize.c index 9f84540ed..4a61eed72 100644 --- a/window-customize.c +++ b/window-customize.c @@ -1,4 +1,4 @@ -/* $OpenBSD: window-customize.c,v 1.30 2026/07/06 14:40:57 nicm Exp $ */ +/* $OpenBSD: window-customize.c,v 1.31 2026/07/13 19:32:28 nicm Exp $ */ /* * Copyright (c) 2020 Nicholas Marriott @@ -81,6 +81,11 @@ enum window_customize_change { WINDOW_CUSTOMIZE_RESET, }; +enum window_customize_option_type { + WINDOW_CUSTOMIZE_OPTIONS, + WINDOW_CUSTOMIZE_HOOKS +}; + struct window_customize_itemdata { struct window_customize_modedata *data; enum window_customize_scope scope; @@ -274,7 +279,8 @@ static void window_customize_build_option(struct window_customize_modedata *data, struct mode_tree_item *top, enum window_customize_scope scope, struct options_entry *o, struct format_tree *ft, - const char *filter, struct cmd_find_state *fs) + const char *filter, struct cmd_find_state *fs, + enum window_customize_option_type type) { const struct options_table_entry *oe = options_table_entry(o); struct options *oo = options_owner(o); @@ -282,10 +288,23 @@ window_customize_build_option(struct window_customize_modedata *data, struct window_customize_itemdata *item; char *text, *expanded, *value; int global = 0, array = 0; + int is_hook = 0, is_monitor = 0; uint64_t tag; if (oe != NULL && (oe->flags & OPTIONS_TABLE_IS_HOOK)) - return; + is_hook = 1; + if (options_get_monitor_data(o) != NULL) + is_monitor = 1; + switch (type) { + case WINDOW_CUSTOMIZE_OPTIONS: + if (is_hook || is_monitor) + return; + break; + case WINDOW_CUSTOMIZE_HOOKS: + if (!is_hook && !is_monitor) + return; + break; + } if (oe != NULL && (oe->flags & OPTIONS_TABLE_IS_ARRAY)) array = 1; @@ -299,6 +318,8 @@ window_customize_build_option(struct window_customize_modedata *data, format_add(ft, "option_name", "%s", name); format_add(ft, "option_is_global", "%d", global); format_add(ft, "option_is_array", "%d", array); + format_add(ft, "option_is_hook", "%d", is_hook); + format_add(ft, "option_is_monitor", "%d", is_monitor); text = window_customize_scope_text(scope, fs); format_add(ft, "option_scope", "%s", text); @@ -309,6 +330,16 @@ window_customize_build_option(struct window_customize_modedata *data, else format_add(ft, "option_unit", "%s", ""); + if (is_monitor) { + value = hooks_monitor_to_string(o); + if (value != NULL) { + format_add(ft, "option_monitor", "%s", value); + free(value); + } else + format_add(ft, "option_monitor", "%s", ""); + } else + format_add(ft, "option_monitor", "%s", ""); + if (!array) { value = options_to_string(o, NULL, 0); format_add(ft, "option_value", "%s", value); @@ -376,7 +407,8 @@ window_customize_build_options(struct window_customize_modedata *data, enum window_customize_scope scope0, struct options *oo0, enum window_customize_scope scope1, struct options *oo1, enum window_customize_scope scope2, struct options *oo2, - struct format_tree *ft, const char *filter, struct cmd_find_state *fs) + struct format_tree *ft, const char *filter, struct cmd_find_state *fs, + enum window_customize_option_type type) { struct mode_tree_item *top; struct options_entry *o = NULL, *loop; @@ -400,6 +432,7 @@ window_customize_build_options(struct window_customize_modedata *data, window_customize_find_user_options(oo2, &list, &size); for (i = 0; i < size; i++) { + o = NULL; if (oo2 != NULL) o = options_get(oo2, list[i]); if (o == NULL && oo1 != NULL) @@ -413,7 +446,7 @@ window_customize_build_options(struct window_customize_modedata *data, else scope = scope0; window_customize_build_option(data, top, scope, o, ft, filter, - fs); + fs, type); } free(list); @@ -437,7 +470,7 @@ window_customize_build_options(struct window_customize_modedata *data, else scope = scope0; window_customize_build_option(data, top, scope, o, ft, filter, - fs); + fs, type); loop = options_next(loop); } } @@ -556,19 +589,31 @@ window_customize_build(void *modedata, WINDOW_CUSTOMIZE_SERVER, global_options, WINDOW_CUSTOMIZE_NONE, NULL, WINDOW_CUSTOMIZE_NONE, NULL, - ft, filter, &fs); + ft, filter, &fs, WINDOW_CUSTOMIZE_OPTIONS); window_customize_build_options(data, "Session Options", (3ULL << 62)|(OPTIONS_TABLE_SESSION << 1)|1, WINDOW_CUSTOMIZE_GLOBAL_SESSION, global_s_options, WINDOW_CUSTOMIZE_SESSION, fs.s->options, WINDOW_CUSTOMIZE_NONE, NULL, - ft, filter, &fs); + ft, filter, &fs, WINDOW_CUSTOMIZE_OPTIONS); window_customize_build_options(data, "Window & Pane Options", (3ULL << 62)|(OPTIONS_TABLE_WINDOW << 1)|1, WINDOW_CUSTOMIZE_GLOBAL_WINDOW, global_w_options, WINDOW_CUSTOMIZE_WINDOW, fs.w->options, WINDOW_CUSTOMIZE_PANE, fs.wp->options, - ft, filter, &fs); + ft, filter, &fs, WINDOW_CUSTOMIZE_OPTIONS); + window_customize_build_options(data, "Session Hooks", + (3ULL << 62)|(1ULL << 8)|(OPTIONS_TABLE_SESSION << 1)|1, + WINDOW_CUSTOMIZE_GLOBAL_SESSION, global_s_options, + WINDOW_CUSTOMIZE_SESSION, fs.s->options, + WINDOW_CUSTOMIZE_NONE, NULL, + ft, filter, &fs, WINDOW_CUSTOMIZE_HOOKS); + window_customize_build_options(data, "Window & Pane Hooks", + (3ULL << 62)|(1ULL << 8)|(OPTIONS_TABLE_WINDOW << 1)|1, + WINDOW_CUSTOMIZE_GLOBAL_WINDOW, global_w_options, + WINDOW_CUSTOMIZE_WINDOW, fs.w->options, + WINDOW_CUSTOMIZE_PANE, fs.wp->options, + ft, filter, &fs, WINDOW_CUSTOMIZE_HOOKS); format_free(ft); ft = format_create_from_state(NULL, NULL, &fs); @@ -662,10 +707,12 @@ window_customize_draw_option(struct window_customize_modedata *data, const char *array_key; const char *space = "", *unit = ""; char *value = NULL, *expanded; + char *monitor; char *default_value = NULL; char choices[256] = ""; struct cmd_find_state fs; struct format_tree *ft; + int is_hook, is_monitor; if (!window_customize_check_item(data, item, &fs)) return; @@ -676,6 +723,8 @@ window_customize_draw_option(struct window_customize_modedata *data, if (o == NULL) return; oe = options_table_entry(o); + is_hook = (oe != NULL && (oe->flags & OPTIONS_TABLE_IS_HOOK)); + is_monitor = (options_get_monitor_data(o) != NULL); if (oe != NULL && oe->unit != NULL) { space = " "; @@ -683,9 +732,11 @@ window_customize_draw_option(struct window_customize_modedata *data, } ft = format_create_from_state(NULL, NULL, &fs); - if (oe == NULL || oe->text == NULL) - text = "This option doesn't have a description."; - else + if (oe == NULL || oe->text == NULL) { + text = is_monitor ? + "This hook runs when a monitor changes." : + "This option doesn't have a description."; + } else text = oe->text; if (!screen_write_text(ctx, cx, sx, sy, 0, &grid_default_cell, "%s", text)) @@ -694,6 +745,12 @@ window_customize_draw_option(struct window_customize_modedata *data, if (s->cy >= cy + sy - 1) goto out; + if (is_monitor) { + if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy), 0, + &grid_default_cell, "This is a monitor hook.")) + goto out; + goto monitor; + } if (oe == NULL) text = "user"; else if ((oe->scope & (OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE)) == @@ -705,11 +762,31 @@ window_customize_draw_option(struct window_customize_modedata *data, text = "session"; else text = "server"; - if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy), 0, - &grid_default_cell, "This is a %s option.", text)) - goto out; + if (is_hook) { + if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy), 0, + &grid_default_cell, "This is a %s hook.", text)) + goto out; + } else { + if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy), 0, + &grid_default_cell, "This is a %s option.", text)) + goto out; + } + +monitor: + monitor = hooks_monitor_to_string(o); + if (monitor != NULL) { + if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy), 0, + &grid_default_cell, "Monitor: %s", monitor)) { + free(monitor); + goto out; + } + free(monitor); + } if (oe != NULL && (oe->flags & OPTIONS_TABLE_IS_ARRAY)) { - if (array_key != NULL) { + if (is_hook) { + if (array_key == NULL) + goto out; + } else if (array_key != NULL) { if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy), 0, &grid_default_cell, "This is an array option, key %s.", array_key)) @@ -734,9 +811,17 @@ window_customize_draw_option(struct window_customize_modedata *data, default_value = NULL; } } - if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy), 0, - &grid_default_cell, "Option value: %s%s%s", value, space, unit)) - goto out; + if (is_hook || is_monitor) { + if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy), 0, + &grid_default_cell, "Hook command: %s%s%s", value, space, + unit)) + goto out; + } else { + if (!screen_write_text(ctx, cx, sx, sy - (s->cy - cy), 0, + &grid_default_cell, "Option value: %s%s%s", value, space, + unit)) + goto out; + } if (oe == NULL || oe->type == OPTIONS_TABLE_STRING) { expanded = format_expand(ft, value); if (strcmp(expanded, value) != 0) { From b1c347ee0ca31031efcea9c873017d72248b23b0 Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 13 Jul 2026 19:35:22 +0000 Subject: [PATCH 2/2] Replace last use of fgetln with getline, GitHub issue 5389 from Yayo Razo. --- prompt-history.c | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/prompt-history.c b/prompt-history.c index ad1ab4047..109043aa7 100644 --- a/prompt-history.c +++ b/prompt-history.c @@ -1,4 +1,4 @@ -/* $OpenBSD: prompt-history.c,v 1.1 2026/06/25 11:39:11 nicm Exp $ */ +/* $OpenBSD: prompt-history.c,v 1.2 2026/07/13 19:35:22 nicm Exp $ */ /* * Copyright (c) 2026 Nicholas Marriott @@ -79,8 +79,9 @@ void prompt_load_history(void) { FILE *f; - char *history_file, *line, *tmp; - size_t length; + char *history_file, *line = NULL; + size_t length = 0; + ssize_t got; if ((history_file = prompt_find_history_file()) == NULL) return; @@ -94,23 +95,13 @@ prompt_load_history(void) } free(history_file); - for (;;) { - if ((line = fgetln(f, &length)) == NULL) - break; - - if (length > 0) { - if (line[length - 1] == '\n') { - line[length - 1] = '\0'; - prompt_add_typed_history(line); - } else { - tmp = xmalloc(length + 1); - memcpy(tmp, line, length); - tmp[length] = '\0'; - prompt_add_typed_history(tmp); - free(tmp); - } - } + while ((got = getline(&line, &length, f)) != -1) { + if (got > 0 && line[got - 1] == '\n') + line[got - 1] = '\0'; + if (got > 0) + prompt_add_typed_history(line); } + free(line); fclose(f); }