Store count of how many times a hook is fired and the last time.

This commit is contained in:
nicm
2026-07-27 19:15:58 +00:00
committed by tmux update bot
parent f751d3f2c1
commit 27ab96b284
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>
@@ -191,6 +191,9 @@ cmd_show_options_print(struct cmd *self, struct cmdq_item *item,
const char *name = options_name(o);
const char *template = args_get(args, 'F');
char *value, *line;
struct timeval tv = { 0 };
u_int fire_count;
time_t fire_time;
int is_hook = 0, is_user = 0;
int has_value = 1;
const struct options_table_entry *oe = options_table_entry(o);
@@ -233,6 +236,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_user", "%d", is_user);
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) {
format_add(ft, "option_array_key", "%s", array_key);
format_add(ft, "option_has_array_key", "1");
@@ -257,6 +270,9 @@ cmd_show_hooks_print_monitor(struct cmd *self, struct cmdq_item *item,
enum monitor_type type;
const char *template = args_get(args, 'F'), *format;
char *value, *target, *line;
struct timeval tv = { 0 };
u_int fire_count;
time_t fire_time;
int id;
value = hooks_monitor_to_string(o);
@@ -299,8 +315,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_array_key", "%s", "");
format_add(ft, "option_has_array_key", "0");
format_add(ft, "hook_monitor_target", "%s", target);
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);
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>
@@ -25,7 +25,7 @@
#include "tmux.h"
/* Hook monitor state owned by an option entry. */
struct hook_monitor {
struct hooks_monitor {
struct options *oo;
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);
return;
}
options_hook_fired(o);
if (item == NULL)
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;
if (event_payload_get_pointer(ep, "_hook_monitor") != NULL)
if (event_payload_get_pointer(ep, "_hooks_monitor") != NULL)
return;
item = event_payload_get_pointer(ep, "_cmdq_item");
@@ -324,7 +325,7 @@ hooks_run(struct cmdq_item *item, const char *name)
void
hooks_monitor_free(void *data)
{
struct hook_monitor *hm = data;
struct hooks_monitor *hm = data;
events_remove_sink(hm->sink);
monitor_destroy(hm->set);
@@ -337,7 +338,7 @@ void
hooks_monitor_remove(struct options *oo, const char *name)
{
struct options_entry *o;
struct hook_monitor *hm;
struct hooks_monitor *hm;
o = options_get_only(oo, name);
if (o == NULL)
@@ -355,9 +356,9 @@ static void
hooks_monitor_hook_cb(const char *name, struct event_payload *ep,
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);
}
@@ -365,14 +366,14 @@ hooks_monitor_hook_cb(const char *name, struct event_payload *ep,
static void
hooks_monitor_cb(struct monitor_change *change, void *data)
{
struct hook_monitor *hm = data;
struct hooks_monitor *hm = data;
struct event_payload *ep;
struct winlink *wl = change->wl;
struct window_pane *wp = change->wp;
struct cmd_find_state fs;
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);
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);
if (wl != NULL) {
if (change->s == NULL)
event_payload_set_session(ep, "session",
wl->session);
event_payload_set_session(ep, "session", wl->session);
event_payload_set_window(ep, "window", wl->window);
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)
{
struct options_entry *o;
struct hook_monitor *hm;
struct hooks_monitor *hm;
hooks_monitor_remove(oo, name);
o = options_get_only(oo, name);
@@ -446,7 +446,7 @@ hooks_monitor_add(__unused struct cmdq_item *item, struct options *oo,
char *
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);
char *s;
@@ -478,7 +478,7 @@ int
hooks_monitor_get(struct options_entry *o, enum monitor_type *type, int *id,
const char **format)
{
struct hook_monitor *hm = options_get_monitor_data(o);
struct hooks_monitor *hm = options_get_monitor_data(o);
if (hm == NULL)
return (0);
@@ -487,3 +487,25 @@ hooks_monitor_get(struct options_entry *o, enum monitor_type *type, int *id,
*format = hm->format;
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>
@@ -59,6 +59,9 @@ struct monitor_item {
struct monitor_panes panes;
struct monitor_windows windows;
u_int fire_count;
time_t fire_time;
RB_ENTRY(monitor_item) entry;
};
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);
me->fire_count++;
me->fire_time = current_time;
change.name = me->name;
change.value = value;
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))
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>
@@ -107,7 +107,10 @@ struct options_entry {
int cached;
struct style style;
void *monitor_data;
u_int fire_count;
time_t fire_time;
RB_ENTRY(options_entry) entry;
};
@@ -440,6 +443,25 @@ options_set_monitor_data(struct options_entry *o, void *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 *
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>
.\"
@@ -14,7 +14,7 @@
.\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
.\" 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
.Os
.Sh NAME
@@ -7283,6 +7283,8 @@ The following variables are available, where appropriate:
.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_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_monitor_format" Ta "" Ta "Format 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>
@@ -2745,6 +2745,8 @@ void hooks_monitor_free(void *);
char *hooks_monitor_to_string(struct options_entry *);
int hooks_monitor_get(struct options_entry *, enum monitor_type *, int *,
const char **);
u_int hooks_monitor_get_fire_count(struct options_entry *);
time_t hooks_monitor_get_fire_time(struct options_entry *);
/* options.c */
struct options *options_create(struct options *);
@@ -2762,6 +2764,9 @@ const char *options_name(struct options_entry *);
struct options *options_owner(struct options_entry *);
void *options_get_monitor_data(struct options_entry *);
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 *);
struct options_entry *options_get_only(struct options *, const char *);
struct options_entry *options_get(struct options *, const char *);
@@ -3957,6 +3962,8 @@ int monitor_parse(const char *, char **, enum monitor_type *, int *,
void monitor_add(struct monitor_set *, const char *, enum monitor_type, int,
const char *, int);
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 */
void control_discard(struct client *);