Merge remote-tracking branch 'refs/remotes/tmux-openbsd/master'

* refs/remotes/tmux-openbsd/master:
  Store count of how many times a hook is fired and the last time.
This commit is contained in:
tmux update bot
2026-07-28 04:30:35 +00:00
6 changed files with 128 additions and 20 deletions

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: cmd-show-options.c,v 1.75 2026/07/22 20:12:58 nicm Exp $ */ /* $OpenBSD: cmd-show-options.c,v 1.76 2026/07/27 19:15:58 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -190,6 +190,9 @@ cmd_show_options_print(struct cmd *self, struct cmdq_item *item,
const char *name = options_name(o); const char *name = options_name(o);
const char *template = args_get(args, 'F'); const char *template = args_get(args, 'F');
char *value, *line; char *value, *line;
struct timeval tv = { 0 };
u_int fire_count;
time_t fire_time;
int is_hook = 0, is_user = 0; int is_hook = 0, is_user = 0;
int has_value = 1; int has_value = 1;
const struct options_table_entry *oe = options_table_entry(o); const struct options_table_entry *oe = options_table_entry(o);
@@ -232,6 +235,16 @@ cmd_show_options_print(struct cmd *self, struct cmdq_item *item,
format_add(ft, "option_is_hook", "%d", is_hook); format_add(ft, "option_is_hook", "%d", is_hook);
format_add(ft, "option_is_user", "%d", is_user); format_add(ft, "option_is_user", "%d", is_user);
format_add(ft, "option_has_value", "%d", has_value); format_add(ft, "option_has_value", "%d", has_value);
if (cmd_get_entry(self) == &cmd_show_hooks_entry) {
fire_count = options_get_fire_count(o);
format_add(ft, "hook_fire_count", "%u", fire_count);
fire_time = options_get_fire_time(o);
if (fire_time != 0) {
tv.tv_sec = fire_time;
format_add_tv(ft, "hook_fire_time", &tv);
}
}
if (array_key != NULL) { if (array_key != NULL) {
format_add(ft, "option_array_key", "%s", array_key); format_add(ft, "option_array_key", "%s", array_key);
format_add(ft, "option_has_array_key", "1"); format_add(ft, "option_has_array_key", "1");
@@ -256,6 +269,9 @@ cmd_show_hooks_print_monitor(struct cmd *self, struct cmdq_item *item,
enum monitor_type type; enum monitor_type type;
const char *template = args_get(args, 'F'), *format; const char *template = args_get(args, 'F'), *format;
char *value, *target, *line; char *value, *target, *line;
struct timeval tv = { 0 };
u_int fire_count;
time_t fire_time;
int id; int id;
value = hooks_monitor_to_string(o); value = hooks_monitor_to_string(o);
@@ -298,8 +314,19 @@ cmd_show_hooks_print_monitor(struct cmd *self, struct cmdq_item *item,
format_add(ft, "option_has_value", "%d", 1); format_add(ft, "option_has_value", "%d", 1);
format_add(ft, "option_array_key", "%s", ""); format_add(ft, "option_array_key", "%s", "");
format_add(ft, "option_has_array_key", "0"); format_add(ft, "option_has_array_key", "0");
format_add(ft, "hook_monitor_target", "%s", target); format_add(ft, "hook_monitor_target", "%s", target);
format_add(ft, "hook_monitor_format", "%s", format); format_add(ft, "hook_monitor_format", "%s", format);
fire_count = hooks_monitor_get_fire_count(o);
format_add(ft, "hook_fire_count", "%u", fire_count);
fire_time = hooks_monitor_get_fire_time(o);
if (fire_time != 0) {
tv.tv_sec = fire_time;
format_add_tv(ft, "hook_fire_time", &tv);
}
line = format_expand(ft, template); line = format_expand(ft, template);
format_free(ft); format_free(ft);

50
hooks.c
View File

@@ -1,4 +1,4 @@
/* $OpenBSD: hooks.c,v 1.15 2026/07/22 20:12:58 nicm Exp $ */ /* $OpenBSD: hooks.c,v 1.16 2026/07/27 19:15:58 nicm Exp $ */
/* /*
* Copyright (c) 2026 Nicholas Marriott <nicholas.marriott@gmail.com> * Copyright (c) 2026 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -25,7 +25,7 @@
#include "tmux.h" #include "tmux.h"
/* Hook monitor state owned by an option entry. */ /* Hook monitor state owned by an option entry. */
struct hook_monitor { struct hooks_monitor {
struct options *oo; struct options *oo;
struct monitor_set *set; struct monitor_set *set;
@@ -143,6 +143,7 @@ hooks_insert(struct cmdq_item *item, struct hooks_data *hd)
log_debug("%s: hook %s not found", __func__, hd->name); log_debug("%s: hook %s not found", __func__, hd->name);
return; return;
} }
options_hook_fired(o);
if (item == NULL) if (item == NULL)
state = cmdq_new_state(&fs, NULL, CMDQ_STATE_NOHOOKS); state = cmdq_new_state(&fs, NULL, CMDQ_STATE_NOHOOKS);
@@ -233,7 +234,7 @@ hooks_event_cb(const char *name, struct event_payload *ep,
{ {
struct cmdq_item *item; struct cmdq_item *item;
if (event_payload_get_pointer(ep, "_hook_monitor") != NULL) if (event_payload_get_pointer(ep, "_hooks_monitor") != NULL)
return; return;
item = event_payload_get_pointer(ep, "_cmdq_item"); item = event_payload_get_pointer(ep, "_cmdq_item");
@@ -324,7 +325,7 @@ hooks_run(struct cmdq_item *item, const char *name)
void void
hooks_monitor_free(void *data) hooks_monitor_free(void *data)
{ {
struct hook_monitor *hm = data; struct hooks_monitor *hm = data;
events_remove_sink(hm->sink); events_remove_sink(hm->sink);
monitor_destroy(hm->set); monitor_destroy(hm->set);
@@ -337,7 +338,7 @@ void
hooks_monitor_remove(struct options *oo, const char *name) hooks_monitor_remove(struct options *oo, const char *name)
{ {
struct options_entry *o; struct options_entry *o;
struct hook_monitor *hm; struct hooks_monitor *hm;
o = options_get_only(oo, name); o = options_get_only(oo, name);
if (o == NULL) if (o == NULL)
@@ -355,9 +356,9 @@ static void
hooks_monitor_hook_cb(const char *name, struct event_payload *ep, hooks_monitor_hook_cb(const char *name, struct event_payload *ep,
void *sink_data) void *sink_data)
{ {
struct hook_monitor *hm = sink_data; struct hooks_monitor *hm = sink_data;
if (event_payload_get_pointer(ep, "_hook_monitor") == hm) if (event_payload_get_pointer(ep, "_hooks_monitor") == hm)
hooks_insert_event(cmdq_running(NULL), name, ep, hm->oo, 1); hooks_insert_event(cmdq_running(NULL), name, ep, hm->oo, 1);
} }
@@ -365,14 +366,14 @@ hooks_monitor_hook_cb(const char *name, struct event_payload *ep,
static void static void
hooks_monitor_cb(struct monitor_change *change, void *data) hooks_monitor_cb(struct monitor_change *change, void *data)
{ {
struct hook_monitor *hm = data; struct hooks_monitor *hm = data;
struct event_payload *ep; struct event_payload *ep;
struct winlink *wl = change->wl; struct winlink *wl = change->wl;
struct window_pane *wp = change->wp; struct window_pane *wp = change->wp;
struct cmd_find_state fs; struct cmd_find_state fs;
ep = event_payload_create(); ep = event_payload_create();
event_payload_set_pointer(ep, "_hook_monitor", data, NULL, NULL); event_payload_set_pointer(ep, "_hooks_monitor", data, NULL, NULL);
cmd_find_clear_state(&fs, 0); cmd_find_clear_state(&fs, 0);
if (wl != NULL && wp != NULL && wp->window == wl->window) if (wl != NULL && wp != NULL && wp->window == wl->window)
@@ -402,8 +403,7 @@ hooks_monitor_cb(struct monitor_change *change, void *data)
event_payload_set_session(ep, "session", change->s); event_payload_set_session(ep, "session", change->s);
if (wl != NULL) { if (wl != NULL) {
if (change->s == NULL) if (change->s == NULL)
event_payload_set_session(ep, "session", event_payload_set_session(ep, "session", wl->session);
wl->session);
event_payload_set_window(ep, "window", wl->window); event_payload_set_window(ep, "window", wl->window);
event_payload_set_int(ep, "window_index", wl->idx); event_payload_set_int(ep, "window_index", wl->idx);
} }
@@ -423,7 +423,7 @@ hooks_monitor_add(__unused struct cmdq_item *item, struct options *oo,
int flags, struct cmd_find_state *fs, struct session *s) int flags, struct cmd_find_state *fs, struct session *s)
{ {
struct options_entry *o; struct options_entry *o;
struct hook_monitor *hm; struct hooks_monitor *hm;
hooks_monitor_remove(oo, name); hooks_monitor_remove(oo, name);
o = options_get_only(oo, name); o = options_get_only(oo, name);
@@ -446,7 +446,7 @@ hooks_monitor_add(__unused struct cmdq_item *item, struct options *oo,
char * char *
hooks_monitor_to_string(struct options_entry *o) hooks_monitor_to_string(struct options_entry *o)
{ {
struct hook_monitor *hm = options_get_monitor_data(o); struct hooks_monitor *hm = options_get_monitor_data(o);
const char *name = options_name(o); const char *name = options_name(o);
char *s; char *s;
@@ -478,7 +478,7 @@ int
hooks_monitor_get(struct options_entry *o, enum monitor_type *type, int *id, hooks_monitor_get(struct options_entry *o, enum monitor_type *type, int *id,
const char **format) const char **format)
{ {
struct hook_monitor *hm = options_get_monitor_data(o); struct hooks_monitor *hm = options_get_monitor_data(o);
if (hm == NULL) if (hm == NULL)
return (0); return (0);
@@ -487,3 +487,25 @@ hooks_monitor_get(struct options_entry *o, enum monitor_type *type, int *id,
*format = hm->format; *format = hm->format;
return (1); return (1);
} }
/* Get hook monitor firing count. */
u_int
hooks_monitor_get_fire_count(struct options_entry *o)
{
struct hooks_monitor *hm = options_get_monitor_data(o);
if (hm == NULL)
return (0);
return (monitor_get_fire_count(hm->set, options_name(o)));
}
/* Get hook monitor firing time. */
time_t
hooks_monitor_get_fire_time(struct options_entry *o)
{
struct hooks_monitor *hm = options_get_monitor_data(o);
if (hm == NULL)
return (0);
return (monitor_get_fire_time(hm->set, options_name(o)));
}

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: monitor.c,v 1.6 2026/07/10 15:20:06 nicm Exp $ */ /* $OpenBSD: monitor.c,v 1.7 2026/07/27 19:15:58 nicm Exp $ */
/* /*
* Copyright (c) 2026 Nicholas Marriott <nicholas.marriott@gmail.com> * Copyright (c) 2026 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -59,6 +59,9 @@ struct monitor_item {
struct monitor_panes panes; struct monitor_panes panes;
struct monitor_windows windows; struct monitor_windows windows;
u_int fire_count;
time_t fire_time;
RB_ENTRY(monitor_item) entry; RB_ENTRY(monitor_item) entry;
}; };
RB_HEAD(monitor_items, monitor_item); RB_HEAD(monitor_items, monitor_item);
@@ -180,6 +183,9 @@ monitor_report(struct monitor_set *ms, struct monitor_item *me,
log_debug("%s: %s changed to %s", __func__, me->name, value); log_debug("%s: %s changed to %s", __func__, me->name, value);
me->fire_count++;
me->fire_time = current_time;
change.name = me->name; change.name = me->name;
change.value = value; change.value = value;
change.last = last; change.last = last;
@@ -659,3 +665,25 @@ monitor_remove(struct monitor_set *ms, const char *name)
if (RB_EMPTY(&ms->items) && evtimer_initialized(&ms->timer)) if (RB_EMPTY(&ms->items) && evtimer_initialized(&ms->timer))
evtimer_del(&ms->timer); evtimer_del(&ms->timer);
} }
/* Get subscription firing count. */
u_int
monitor_get_fire_count(struct monitor_set *ms, const char *name)
{
struct monitor_item *me, find = { .name = (char *)name };
if ((me = RB_FIND(monitor_items, &ms->items, &find)) == NULL)
return (0);
return (me->fire_count);
}
/* Get subscription firing time. */
time_t
monitor_get_fire_time(struct monitor_set *ms, const char *name)
{
struct monitor_item *me, find = { .name = (char *)name };
if ((me = RB_FIND(monitor_items, &ms->items, &find)) == NULL)
return (0);
return (me->fire_time);
}

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: options.c,v 1.91 2026/07/23 09:38:27 nicm Exp $ */ /* $OpenBSD: options.c,v 1.92 2026/07/27 19:15:58 nicm Exp $ */
/* /*
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com> * Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -107,7 +107,10 @@ struct options_entry {
int cached; int cached;
struct style style; struct style style;
void *monitor_data; void *monitor_data;
u_int fire_count;
time_t fire_time;
RB_ENTRY(options_entry) entry; RB_ENTRY(options_entry) entry;
}; };
@@ -440,6 +443,25 @@ options_set_monitor_data(struct options_entry *o, void *data)
o->monitor_data = data; o->monitor_data = data;
} }
void
options_hook_fired(struct options_entry *o)
{
o->fire_count++;
o->fire_time = current_time;
}
u_int
options_get_fire_count(struct options_entry *o)
{
return (o->fire_count);
}
time_t
options_get_fire_time(struct options_entry *o)
{
return (o->fire_time);
}
const struct options_table_entry * const struct options_table_entry *
options_table_entry(struct options_entry *o) options_table_entry(struct options_entry *o)
{ {

6
tmux.1
View File

@@ -1,4 +1,4 @@
.\" $OpenBSD: tmux.1,v 1.1149 2026/07/23 09:38:27 nicm Exp $ .\" $OpenBSD: tmux.1,v 1.1150 2026/07/27 19:15:58 nicm Exp $
.\" .\"
.\" Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> .\" Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
.\" .\"
@@ -14,7 +14,7 @@
.\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING .\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
.\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\" .\"
.Dd $Mdocdate: July 23 2026 $ .Dd $Mdocdate: July 27 2026 $
.Dt TMUX 1 .Dt TMUX 1
.Os .Os
.Sh NAME .Sh NAME
@@ -7285,6 +7285,8 @@ The following variables are available, where appropriate:
.It Li "history_size" Ta "" Ta "Size of history in lines" .It Li "history_size" Ta "" Ta "Size of history in lines"
.It Li "hook" Ta "" Ta "Name of running hook, if any" .It Li "hook" Ta "" Ta "Name of running hook, if any"
.It Li "hook_client" Ta "" Ta "Name of client where hook was run, if any" .It Li "hook_client" Ta "" Ta "Name of client where hook was run, if any"
.It Li "hook_fire_count" Ta "" Ta "Number of times hook has fired"
.It Li "hook_fire_time" Ta "" Ta "Time hook last fired"
.It Li "hook_last" Ta "" Ta "Previous value for a monitor hook" .It Li "hook_last" Ta "" Ta "Previous value for a monitor hook"
.It Li "hook_monitor_format" Ta "" Ta "Format for a monitor hook" .It Li "hook_monitor_format" Ta "" Ta "Format for a monitor hook"
.It Li "hook_monitor_target" Ta "" Ta "Target for a monitor hook" .It Li "hook_monitor_target" Ta "" Ta "Target for a monitor hook"

9
tmux.h
View File

@@ -1,4 +1,4 @@
/* $OpenBSD: tmux.h,v 1.1415 2026/07/23 09:38:27 nicm Exp $ */ /* $OpenBSD: tmux.h,v 1.1416 2026/07/27 19:15:58 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -2786,6 +2786,8 @@ void hooks_monitor_free(void *);
char *hooks_monitor_to_string(struct options_entry *); char *hooks_monitor_to_string(struct options_entry *);
int hooks_monitor_get(struct options_entry *, enum monitor_type *, int *, int hooks_monitor_get(struct options_entry *, enum monitor_type *, int *,
const char **); const char **);
u_int hooks_monitor_get_fire_count(struct options_entry *);
time_t hooks_monitor_get_fire_time(struct options_entry *);
/* options.c */ /* options.c */
struct options *options_create(struct options *); struct options *options_create(struct options *);
@@ -2803,6 +2805,9 @@ const char *options_name(struct options_entry *);
struct options *options_owner(struct options_entry *); struct options *options_owner(struct options_entry *);
void *options_get_monitor_data(struct options_entry *); void *options_get_monitor_data(struct options_entry *);
void options_set_monitor_data(struct options_entry *, void *); void options_set_monitor_data(struct options_entry *, void *);
void options_hook_fired(struct options_entry *);
u_int options_get_fire_count(struct options_entry *);
time_t options_get_fire_time(struct options_entry *);
const struct options_table_entry *options_table_entry(struct options_entry *); const struct options_table_entry *options_table_entry(struct options_entry *);
struct options_entry *options_get_only(struct options *, const char *); struct options_entry *options_get_only(struct options *, const char *);
struct options_entry *options_get(struct options *, const char *); struct options_entry *options_get(struct options *, const char *);
@@ -4007,6 +4012,8 @@ int monitor_parse(const char *, char **, enum monitor_type *, int *,
void monitor_add(struct monitor_set *, const char *, enum monitor_type, int, void monitor_add(struct monitor_set *, const char *, enum monitor_type, int,
const char *, int); const char *, int);
void monitor_remove(struct monitor_set *, const char *); void monitor_remove(struct monitor_set *, const char *);
u_int monitor_get_fire_count(struct monitor_set *, const char *);
time_t monitor_get_fire_time(struct monitor_set *, const char *);
/* control.c */ /* control.c */
void control_discard(struct client *); void control_discard(struct client *);