summaryrefslogtreecommitdiff
path: root/usr.bin/tmux
diff options
context:
space:
mode:
authorNicholas Marriott <nicm@cvs.openbsd.org>2019-04-26 11:38:52 +0000
committerNicholas Marriott <nicm@cvs.openbsd.org>2019-04-26 11:38:52 +0000
commit584b0b820080b312119c4f3889b3c3190195dc75 (patch)
treea7814fc11e7a8161308a43c4462562af1889073f /usr.bin/tmux
parente36c521bc8fb42ec39a478a61b68f80803204339 (diff)
Merge hooks into options and make each one an array option. This allows
multiple commands to be easily bound to one hook. set-hook and show-hooks remain but they are now variants of set-option and show-options. show-options now has a -H flag to show hooks (by default they are not shown).
Diffstat (limited to 'usr.bin/tmux')
-rw-r--r--usr.bin/tmux/Makefile4
-rw-r--r--usr.bin/tmux/cmd-new-session.c4
-rw-r--r--usr.bin/tmux/cmd-new-window.c4
-rw-r--r--usr.bin/tmux/cmd-queue.c58
-rw-r--r--usr.bin/tmux/cmd-select-pane.c4
-rw-r--r--usr.bin/tmux/cmd-select-window.c6
-rw-r--r--usr.bin/tmux/cmd-set-hook.c133
-rw-r--r--usr.bin/tmux/cmd-set-option.c41
-rw-r--r--usr.bin/tmux/cmd-show-options.c54
-rw-r--r--usr.bin/tmux/cmd-split-window.c4
-rw-r--r--usr.bin/tmux/cmd-string.c7
-rw-r--r--usr.bin/tmux/hooks.c173
-rw-r--r--usr.bin/tmux/notify.c76
-rw-r--r--usr.bin/tmux/options-table.c76
-rw-r--r--usr.bin/tmux/options.c75
-rw-r--r--usr.bin/tmux/session.c5
-rw-r--r--usr.bin/tmux/status.c4
-rw-r--r--usr.bin/tmux/tmux.134
-rw-r--r--usr.bin/tmux/tmux.c5
-rw-r--r--usr.bin/tmux/tmux.h41
20 files changed, 375 insertions, 433 deletions
diff --git a/usr.bin/tmux/Makefile b/usr.bin/tmux/Makefile
index b0e5708dcf8..e107e9ab099 100644
--- a/usr.bin/tmux/Makefile
+++ b/usr.bin/tmux/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.94 2019/04/17 14:37:48 nicm Exp $
+# $OpenBSD: Makefile,v 1.95 2019/04/26 11:38:51 nicm Exp $
PROG= tmux
SRCS= alerts.c \
@@ -56,7 +56,6 @@ SRCS= alerts.c \
cmd-send-keys.c \
cmd-set-buffer.c \
cmd-set-environment.c \
- cmd-set-hook.c \
cmd-set-option.c \
cmd-show-environment.c \
cmd-show-messages.c \
@@ -78,7 +77,6 @@ SRCS= alerts.c \
format-draw.c \
grid-view.c \
grid.c \
- hooks.c \
input-keys.c \
input.c \
job.c \
diff --git a/usr.bin/tmux/cmd-new-session.c b/usr.bin/tmux/cmd-new-session.c
index d5c63e40bd0..f19faaec305 100644
--- a/usr.bin/tmux/cmd-new-session.c
+++ b/usr.bin/tmux/cmd-new-session.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-new-session.c,v 1.116 2019/04/17 14:37:48 nicm Exp $ */
+/* $OpenBSD: cmd-new-session.c,v 1.117 2019/04/26 11:38:51 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -329,7 +329,7 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
}
cmd_find_from_session(&fs, s, 0);
- hooks_insert(s->hooks, item, &fs, "after-new-session");
+ cmdq_insert_hook(s, item, &fs, "after-new-session");
free(cwd);
free(newname);
diff --git a/usr.bin/tmux/cmd-new-window.c b/usr.bin/tmux/cmd-new-window.c
index 0383b53b444..e096f340391 100644
--- a/usr.bin/tmux/cmd-new-window.c
+++ b/usr.bin/tmux/cmd-new-window.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-new-window.c,v 1.77 2019/04/17 14:37:48 nicm Exp $ */
+/* $OpenBSD: cmd-new-window.c,v 1.78 2019/04/26 11:38:51 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -105,7 +105,7 @@ cmd_new_window_exec(struct cmd *self, struct cmdq_item *item)
}
cmd_find_from_winlink(&fs, new_wl, 0);
- hooks_insert(s->hooks, item, &fs, "after-new-window");
+ cmdq_insert_hook(s, item, &fs, "after-new-window");
return (CMD_RETURN_NORMAL);
}
diff --git a/usr.bin/tmux/cmd-queue.c b/usr.bin/tmux/cmd-queue.c
index 95b78ef3402..3109cdb8cf8 100644
--- a/usr.bin/tmux/cmd-queue.c
+++ b/usr.bin/tmux/cmd-queue.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-queue.c,v 1.62 2019/04/17 14:37:48 nicm Exp $ */
+/* $OpenBSD: cmd-queue.c,v 1.63 2019/04/26 11:38:51 nicm Exp $ */
/*
* Copyright (c) 2013 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -98,6 +98,60 @@ cmdq_insert_after(struct cmdq_item *after, struct cmdq_item *item)
} while (item != NULL);
}
+
+/* Insert a hook. */
+void
+cmdq_insert_hook(struct session *s, struct cmdq_item *item,
+ struct cmd_find_state *fs, const char *fmt, ...)
+{
+ struct options *oo;
+ va_list ap;
+ char *name;
+ struct cmdq_item *new_item;
+ struct options_entry *o;
+ struct options_array_item *a;
+ struct cmd_list *cmdlist;
+
+ if (item->flags & CMDQ_NOHOOKS)
+ return;
+ if (s == NULL)
+ oo = global_s_options;
+ else
+ oo = s->options;
+
+ va_start(ap, fmt);
+ xvasprintf(&name, fmt, ap);
+ va_end(ap);
+
+ o = options_get(oo, name);
+ if (o == NULL) {
+ free(name);
+ return;
+ }
+ log_debug("running hook %s (parent %p)", name, item);
+
+ a = options_array_first(o);
+ while (a != NULL) {
+ cmdlist = options_array_item_value(a)->cmdlist;
+ if (cmdlist == NULL) {
+ a = options_array_next(a);
+ continue;
+ }
+
+ new_item = cmdq_get_command(cmdlist, fs, NULL, CMDQ_NOHOOKS);
+ cmdq_format(new_item, "hook", "%s", name);
+ if (item != NULL) {
+ cmdq_insert_after(item, new_item);
+ item = new_item;
+ } else
+ cmdq_append(NULL, new_item);
+
+ a = options_array_next(a);
+ }
+
+ free(name);
+}
+
/* Remove an item. */
static void
cmdq_remove(struct cmdq_item *item)
@@ -245,7 +299,7 @@ cmdq_fire_command(struct cmdq_item *item)
fsp = &fs;
else
goto out;
- hooks_insert(fsp->s->hooks, item, fsp, "after-%s", entry->name);
+ cmdq_insert_hook(fsp->s, item, fsp, "after-%s", entry->name);
}
out:
diff --git a/usr.bin/tmux/cmd-select-pane.c b/usr.bin/tmux/cmd-select-pane.c
index 9fce50d4fcf..ba8fc931639 100644
--- a/usr.bin/tmux/cmd-select-pane.c
+++ b/usr.bin/tmux/cmd-select-pane.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-select-pane.c,v 1.48 2019/04/17 14:37:48 nicm Exp $ */
+/* $OpenBSD: cmd-select-pane.c,v 1.49 2019/04/26 11:38:51 nicm Exp $ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -196,7 +196,7 @@ cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item)
window_redraw_active_switch(w, wp);
if (window_set_active_pane(w, wp, 1)) {
cmd_find_from_winlink_pane(current, wl, wp, 0);
- hooks_insert(s->hooks, item, current, "after-select-pane");
+ cmdq_insert_hook(s, item, current, "after-select-pane");
cmd_select_pane_redraw(w);
}
diff --git a/usr.bin/tmux/cmd-select-window.c b/usr.bin/tmux/cmd-select-window.c
index 2e08f3abd54..7ad78262567 100644
--- a/usr.bin/tmux/cmd-select-window.c
+++ b/usr.bin/tmux/cmd-select-window.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-select-window.c,v 1.22 2017/08/30 10:33:57 nicm Exp $ */
+/* $OpenBSD: cmd-select-window.c,v 1.23 2019/04/26 11:38:51 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -119,7 +119,7 @@ cmd_select_window_exec(struct cmd *self, struct cmdq_item *item)
}
cmd_find_from_session(current, s, 0);
server_redraw_session(s);
- hooks_insert(s->hooks, item, current, "after-select-window");
+ cmdq_insert_hook(s, item, current, "after-select-window");
} else {
/*
* If -T and select-window is invoked on same window as
@@ -137,7 +137,7 @@ cmd_select_window_exec(struct cmd *self, struct cmdq_item *item)
cmd_find_from_session(current, s, 0);
server_redraw_session(s);
}
- hooks_insert(s->hooks, item, current, "after-select-window");
+ cmdq_insert_hook(s, item, current, "after-select-window");
}
recalculate_sizes();
diff --git a/usr.bin/tmux/cmd-set-hook.c b/usr.bin/tmux/cmd-set-hook.c
deleted file mode 100644
index 20c72173f3c..00000000000
--- a/usr.bin/tmux/cmd-set-hook.c
+++ /dev/null
@@ -1,133 +0,0 @@
-/* $OpenBSD: cmd-set-hook.c,v 1.12 2018/07/04 12:30:52 nicm Exp $ */
-
-/*
- * Copyright (c) 2012 Thomas Adam <thomas@xteddy.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
- * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
- * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <sys/types.h>
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "tmux.h"
-
-/*
- * Set or show global or session hooks.
- */
-
-static enum cmd_retval cmd_set_hook_exec(struct cmd *, struct cmdq_item *);
-
-const struct cmd_entry cmd_set_hook_entry = {
- .name = "set-hook",
- .alias = NULL,
-
- .args = { "gRt:u", 1, 2 },
- .usage = "[-gRu] " CMD_TARGET_SESSION_USAGE " hook-name [command]",
-
- .target = { 't', CMD_FIND_SESSION, CMD_FIND_CANFAIL },
-
- .flags = CMD_AFTERHOOK,
- .exec = cmd_set_hook_exec
-};
-
-const struct cmd_entry cmd_show_hooks_entry = {
- .name = "show-hooks",
- .alias = NULL,
-
- .args = { "gt:", 0, 1 },
- .usage = "[-g] " CMD_TARGET_SESSION_USAGE,
-
- .target = { 't', CMD_FIND_SESSION, 0 },
-
- .flags = CMD_AFTERHOOK,
- .exec = cmd_set_hook_exec
-};
-
-static enum cmd_retval
-cmd_set_hook_exec(struct cmd *self, struct cmdq_item *item)
-{
- struct args *args = self->args;
- struct cmd_list *cmdlist;
- struct hooks *hooks;
- struct hook *hook;
- char *cause, *tmp;
- const char *name, *cmd, *target;
-
- if (args_has(args, 'g'))
- hooks = global_hooks;
- else {
- if (item->target.s == NULL) {
- target = args_get(args, 't');
- if (target != NULL)
- cmdq_error(item, "no such session: %s", target);
- else
- cmdq_error(item, "no current session");
- return (CMD_RETURN_ERROR);
- }
- hooks = item->target.s->hooks;
- }
-
- if (self->entry == &cmd_show_hooks_entry) {
- hook = hooks_first(hooks);
- while (hook != NULL) {
- tmp = cmd_list_print(hook->cmdlist);
- cmdq_print(item, "%s -> %s", hook->name, tmp);
- free(tmp);
-
- hook = hooks_next(hook);
- }
- return (CMD_RETURN_NORMAL);
- }
-
- name = args->argv[0];
- if (*name == '\0') {
- cmdq_error(item, "invalid hook name");
- return (CMD_RETURN_ERROR);
- }
- if (args->argc < 2)
- cmd = NULL;
- else
- cmd = args->argv[1];
-
- if (cmd != NULL && (args_has(args, 'R') || args_has(args, 'u'))) {
- cmdq_error(item, "no command allowed");
- return (CMD_RETURN_ERROR);
- }
- if (args_has(args, 'R')) {
- notify_hook(item, name);
- return (CMD_RETURN_NORMAL);
- }
- if (args_has(args, 'u')) {
- hooks_remove(hooks, name);
- return (CMD_RETURN_NORMAL);
- }
-
- if (cmd == NULL) {
- cmdq_error(item, "no command given");
- return (CMD_RETURN_ERROR);
- }
- cmdlist = cmd_string_parse(cmd, NULL, 0, &cause);
- if (cmdlist == NULL) {
- if (cause != NULL) {
- cmdq_error(item, "%s", cause);
- free(cause);
- }
- return (CMD_RETURN_ERROR);
- }
- hooks_add(hooks, name, cmdlist);
- cmd_list_free(cmdlist);
-
- return (CMD_RETURN_NORMAL);
-}
diff --git a/usr.bin/tmux/cmd-set-option.c b/usr.bin/tmux/cmd-set-option.c
index 5976dab3ce7..2357bfeb61e 100644
--- a/usr.bin/tmux/cmd-set-option.c
+++ b/usr.bin/tmux/cmd-set-option.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-set-option.c,v 1.124 2019/04/23 20:36:55 nicm Exp $ */
+/* $OpenBSD: cmd-set-option.c,v 1.125 2019/04/26 11:38:51 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -65,6 +65,19 @@ const struct cmd_entry cmd_set_window_option_entry = {
.exec = cmd_set_option_exec
};
+const struct cmd_entry cmd_set_hook_entry = {
+ .name = "set-hook",
+ .alias = NULL,
+
+ .args = { "agRt:u", 1, 2 },
+ .usage = "[-agRu] " CMD_TARGET_SESSION_USAGE " hook [command]",
+
+ .target = { 't', CMD_FIND_SESSION, CMD_FIND_CANFAIL },
+
+ .flags = CMD_AFTERHOOK,
+ .exec = cmd_set_option_exec
+};
+
static enum cmd_retval
cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
{
@@ -87,6 +100,11 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
c = cmd_find_client(item, NULL, 1);
argument = format_single(item, args->argv[0], c, s, wl, NULL);
+ if (self->entry == &cmd_set_hook_entry && args_has(args, 'R')) {
+ notify_hook(item, argument);
+ return (CMD_RETURN_NORMAL);
+ }
+
/* Parse option name and index. */
name = options_match(argument, &idx, &ambiguous);
if (name == NULL) {
@@ -200,8 +218,11 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
options_default(oo, options_table_entry(o));
else
options_remove(o);
- } else
- options_array_set(o, idx, NULL, 0);
+ } else if (options_array_set(o, idx, NULL, 0, &cause) != 0) {
+ cmdq_error(item, "%s", cause);
+ free(cause);
+ goto fail;
+ }
} else if (*name == '@') {
if (value == NULL) {
cmdq_error(item, "empty value");
@@ -222,9 +243,15 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
if (idx == -1) {
if (!append)
options_array_clear(o);
- options_array_assign(o, value);
- } else if (options_array_set(o, idx, value, append) != 0) {
- cmdq_error(item, "invalid index: %s", argument);
+ if (options_array_assign(o, value, &cause) != 0) {
+ cmdq_error(item, "%s", cause);
+ free(cause);
+ goto fail;
+ }
+ } else if (options_array_set(o, idx, value, append,
+ &cause) != 0) {
+ cmdq_error(item, "%s", cause);
+ free(cause);
goto fail;
}
}
@@ -366,6 +393,8 @@ cmd_set_option_set(struct cmd *self, struct cmdq_item *item, struct options *oo,
return (-1);
}
return (0);
+ case OPTIONS_TABLE_COMMAND:
+ break;
}
return (-1);
}
diff --git a/usr.bin/tmux/cmd-show-options.c b/usr.bin/tmux/cmd-show-options.c
index 5d161991977..a4daac6cb02 100644
--- a/usr.bin/tmux/cmd-show-options.c
+++ b/usr.bin/tmux/cmd-show-options.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-show-options.c,v 1.47 2019/04/25 18:18:55 nicm Exp $ */
+/* $OpenBSD: cmd-show-options.c,v 1.48 2019/04/26 11:38:51 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -39,8 +39,8 @@ const struct cmd_entry cmd_show_options_entry = {
.name = "show-options",
.alias = "show",
- .args = { "gqst:vw", 0, 1 },
- .usage = "[-gqsvw] [-t target-session|target-window] [option]",
+ .args = { "gHqst:vw", 0, 1 },
+ .usage = "[-gHqsvw] [-t target-session|target-window] [option]",
.target = { 't', CMD_FIND_WINDOW, CMD_FIND_CANFAIL },
@@ -61,6 +61,19 @@ const struct cmd_entry cmd_show_window_options_entry = {
.exec = cmd_show_options_exec
};
+const struct cmd_entry cmd_show_hooks_entry = {
+ .name = "show-hooks",
+ .alias = NULL,
+
+ .args = { "gt:", 0, 1 },
+ .usage = "[-g] " CMD_TARGET_SESSION_USAGE,
+
+ .target = { 't', CMD_FIND_SESSION, 0 },
+
+ .flags = CMD_AFTERHOOK,
+ .exec = cmd_show_options_exec
+};
+
static enum cmd_retval
cmd_show_options_exec(struct cmd *self, struct cmdq_item *item)
{
@@ -162,15 +175,20 @@ cmd_show_options_print(struct cmd *self, struct cmdq_item *item,
struct options_entry *o, int idx)
{
struct options_array_item *a;
- const char *name;
- char *value, *tmp, *escaped;
+ const char *name = options_name(o);
+ char *value, *tmp = NULL, *escaped;
if (idx != -1) {
- xasprintf(&tmp, "%s[%d]", options_name(o), idx);
+ xasprintf(&tmp, "%s[%d]", name, idx);
name = tmp;
} else {
if (options_isarray(o)) {
a = options_array_first(o);
+ if (a == NULL) {
+ if (!args_has(self->args, 'v'))
+ cmdq_print(item, "%s", name);
+ return;
+ }
while (a != NULL) {
idx = options_array_item_index(a);
cmd_show_options_print(self, item, o, idx);
@@ -178,8 +196,6 @@ cmd_show_options_print(struct cmd *self, struct cmdq_item *item,
}
return;
}
- tmp = NULL;
- name = options_name(o);
}
value = options_tostring(o, idx, 0);
@@ -200,16 +216,28 @@ static enum cmd_retval
cmd_show_options_all(struct cmd *self, struct cmdq_item *item,
struct options *oo)
{
- struct options_entry *o;
- struct options_array_item *a;
- u_int idx;
+ struct options_entry *o;
+ struct options_array_item *a;
+ u_int idx;
+ int flags;
o = options_first(oo);
while (o != NULL) {
+ flags = options_table_entry(o)->flags;
+ if ((self->entry != &cmd_show_hooks_entry &&
+ !args_has(self->args, 'H') &&
+ (flags & OPTIONS_TABLE_IS_HOOK)) ||
+ (self->entry == &cmd_show_hooks_entry &&
+ (~flags & OPTIONS_TABLE_IS_HOOK))) {
+ o = options_next(o);
+ continue;
+ }
if (!options_isarray(o))
cmd_show_options_print(self, item, o, -1);
- else {
- a = options_array_first(o);
+ else if ((a = options_array_first(o)) == NULL) {
+ if (!args_has(self->args, 'v'))
+ cmdq_print(item, "%s", options_name(o));
+ } else {
while (a != NULL) {
idx = options_array_item_index(a);
cmd_show_options_print(self, item, o, idx);
diff --git a/usr.bin/tmux/cmd-split-window.c b/usr.bin/tmux/cmd-split-window.c
index 8010ca46bbf..65473c36446 100644
--- a/usr.bin/tmux/cmd-split-window.c
+++ b/usr.bin/tmux/cmd-split-window.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-split-window.c,v 1.92 2019/04/17 14:37:48 nicm Exp $ */
+/* $OpenBSD: cmd-split-window.c,v 1.93 2019/04/26 11:38:51 nicm Exp $ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -144,7 +144,7 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
}
cmd_find_from_winlink_pane(&fs, wl, new_wp, 0);
- hooks_insert(s->hooks, item, &fs, "after-split-window");
+ cmdq_insert_hook(s, item, &fs, "after-split-window");
return (CMD_RETURN_NORMAL);
}
diff --git a/usr.bin/tmux/cmd-string.c b/usr.bin/tmux/cmd-string.c
index 33e62ab9036..bab4679d67e 100644
--- a/usr.bin/tmux/cmd-string.c
+++ b/usr.bin/tmux/cmd-string.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-string.c,v 1.30 2018/08/19 19:03:46 nicm Exp $ */
+/* $OpenBSD: cmd-string.c,v 1.31 2019/04/26 11:38:51 nicm Exp $ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -174,7 +174,10 @@ cmd_string_parse(const char *s, const char *file, u_int line, char **cause)
int argc;
char **argv;
- *cause = NULL;
+ if (cause != NULL)
+ *cause = NULL;
+ log_debug ("%s: %s", __func__, s);
+
if (cmd_string_split(s, &argc, &argv) != 0) {
xasprintf(cause, "invalid or unknown command: %s", s);
return (NULL);
diff --git a/usr.bin/tmux/hooks.c b/usr.bin/tmux/hooks.c
deleted file mode 100644
index 79fd1bbd976..00000000000
--- a/usr.bin/tmux/hooks.c
+++ /dev/null
@@ -1,173 +0,0 @@
-/* $OpenBSD: hooks.c,v 1.10 2018/01/18 07:10:53 nicm Exp $ */
-
-/*
- * Copyright (c) 2012 Thomas Adam <thomas@xteddy.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
- * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
- * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <sys/types.h>
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "tmux.h"
-
-struct hooks {
- RB_HEAD(hooks_tree, hook) tree;
- struct hooks *parent;
-};
-
-static int hooks_cmp(struct hook *, struct hook *);
-RB_GENERATE_STATIC(hooks_tree, hook, entry, hooks_cmp);
-
-static struct hook *hooks_find1(struct hooks *, const char *);
-static void hooks_free1(struct hooks *, struct hook *);
-
-static int
-hooks_cmp(struct hook *hook1, struct hook *hook2)
-{
- return (strcmp(hook1->name, hook2->name));
-}
-
-struct hooks *
-hooks_get(struct session *s)
-{
- if (s != NULL)
- return (s->hooks);
- return (global_hooks);
-}
-
-struct hooks *
-hooks_create(struct hooks *parent)
-{
- struct hooks *hooks;
-
- hooks = xcalloc(1, sizeof *hooks);
- RB_INIT(&hooks->tree);
- hooks->parent = parent;
- return (hooks);
-}
-
-static void
-hooks_free1(struct hooks *hooks, struct hook *hook)
-{
- RB_REMOVE(hooks_tree, &hooks->tree, hook);
- cmd_list_free(hook->cmdlist);
- free((char *)hook->name);
- free(hook);
-}
-
-void
-hooks_free(struct hooks *hooks)
-{
- struct hook *hook, *hook1;
-
- RB_FOREACH_SAFE(hook, hooks_tree, &hooks->tree, hook1)
- hooks_free1(hooks, hook);
- free(hooks);
-}
-
-struct hook *
-hooks_first(struct hooks *hooks)
-{
- return (RB_MIN(hooks_tree, &hooks->tree));
-}
-
-struct hook *
-hooks_next(struct hook *hook)
-{
- return (RB_NEXT(hooks_tree, &hooks->tree, hook));
-}
-
-void
-hooks_add(struct hooks *hooks, const char *name, struct cmd_list *cmdlist)
-{
- struct hook *hook;
-
- if ((hook = hooks_find1(hooks, name)) != NULL)
- hooks_free1(hooks, hook);
-
- hook = xcalloc(1, sizeof *hook);
- hook->name = xstrdup(name);
- hook->cmdlist = cmdlist;
- hook->cmdlist->references++;
- RB_INSERT(hooks_tree, &hooks->tree, hook);
-}
-
-void
-hooks_remove(struct hooks *hooks, const char *name)
-{
- struct hook *hook;
-
- if ((hook = hooks_find1(hooks, name)) != NULL)
- hooks_free1(hooks, hook);
-}
-
-static struct hook *
-hooks_find1(struct hooks *hooks, const char *name)
-{
- struct hook hook;
-
- hook.name = name;
- return (RB_FIND(hooks_tree, &hooks->tree, &hook));
-}
-
-struct hook *
-hooks_find(struct hooks *hooks, const char *name)
-{
- struct hook hook0, *hook;
-
- hook0.name = name;
- hook = RB_FIND(hooks_tree, &hooks->tree, &hook0);
- while (hook == NULL) {
- hooks = hooks->parent;
- if (hooks == NULL)
- break;
- hook = RB_FIND(hooks_tree, &hooks->tree, &hook0);
- }
- return (hook);
-}
-
-void
-hooks_insert(struct hooks *hooks, struct cmdq_item *item,
- struct cmd_find_state *fs, const char *fmt, ...)
-{
- struct hook *hook;
- va_list ap;
- char *name;
- struct cmdq_item *new_item;
-
- if (item->flags & CMDQ_NOHOOKS)
- return;
-
- va_start(ap, fmt);
- xvasprintf(&name, fmt, ap);
- va_end(ap);
-
- hook = hooks_find(hooks, name);
- if (hook == NULL) {
- free(name);
- return;
- }
- log_debug("running hook %s (parent %p)", name, item);
-
- new_item = cmdq_get_command(hook->cmdlist, fs, NULL, CMDQ_NOHOOKS);
- cmdq_format(new_item, "hook", "%s", name);
- if (item != NULL)
- cmdq_insert_after(item, new_item);
- else
- cmdq_append(NULL, new_item);
-
- free(name);
-}
diff --git a/usr.bin/tmux/notify.c b/usr.bin/tmux/notify.c
index 947b6b10e7a..ec246516f59 100644
--- a/usr.bin/tmux/notify.c
+++ b/usr.bin/tmux/notify.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: notify.c,v 1.26 2018/07/04 12:30:52 nicm Exp $ */
+/* $OpenBSD: notify.c,v 1.27 2019/04/26 11:38:51 nicm Exp $ */
/*
* Copyright (c) 2012 George Nachman <tmux@georgester.com>
@@ -36,13 +36,34 @@ struct notify_entry {
};
static void
-notify_hook1(struct cmdq_item *item, struct notify_entry *ne)
+notify_hook_formats(struct cmdq_item *item, struct session *s, struct window *w,
+ int pane)
{
- struct cmd_find_state fs;
- struct hook *hook;
- struct cmdq_item *new_item;
- struct session *s = ne->session;
- struct window *w = ne->window;
+ if (s != NULL) {
+ cmdq_format(item, "hook_session", "$%u", s->id);
+ cmdq_format(item, "hook_session_name", "%s", s->name);
+ }
+ if (w != NULL) {
+ cmdq_format(item, "hook_window", "@%u", w->id);
+ cmdq_format(item, "hook_window_name", "%s", w->name);
+ }
+ if (pane != -1)
+ cmdq_format(item, "hook_pane", "%%%d", pane);
+}
+
+static void
+notify_insert_hook(struct cmdq_item *item, struct notify_entry *ne)
+{
+ struct cmd_find_state fs;
+ struct options *oo;
+ struct cmdq_item *new_item;
+ struct session *s = ne->session;
+ struct window *w = ne->window;
+ struct options_entry *o;
+ struct options_array_item *a;
+ struct cmd_list *cmdlist;
+
+ log_debug("%s: %s", __func__, ne->name);
cmd_find_clear_state(&fs, 0);
if (cmd_find_empty_state(&ne->fs) || !cmd_find_valid_state(&ne->fs))
@@ -50,26 +71,31 @@ notify_hook1(struct cmdq_item *item, struct notify_entry *ne)
else
cmd_find_copy_state(&fs, &ne->fs);
- hook = hooks_find(hooks_get(fs.s), ne->name);
- if (hook == NULL)
+ if (fs.s == NULL)
+ oo = global_s_options;
+ else
+ oo = fs.s->options;
+ o = options_get(oo, ne->name);
+ if (o == NULL)
return;
- log_debug("notify hook %s", ne->name);
- new_item = cmdq_get_command(hook->cmdlist, &fs, NULL, CMDQ_NOHOOKS);
- cmdq_format(new_item, "hook", "%s", ne->name);
+ a = options_array_first(o);
+ while (a != NULL) {
+ cmdlist = options_array_item_value(a)->cmdlist;
+ if (cmdlist == NULL) {
+ a = options_array_next(a);
+ continue;
+ }
- if (s != NULL) {
- cmdq_format(new_item, "hook_session", "$%u", s->id);
- cmdq_format(new_item, "hook_session_name", "%s", s->name);
- }
- if (w != NULL) {
- cmdq_format(new_item, "hook_window", "@%u", w->id);
- cmdq_format(new_item, "hook_window_name", "%s", w->name);
- }
- if (ne->pane != -1)
- cmdq_format(new_item, "hook_pane", "%%%d", ne->pane);
+ new_item = cmdq_get_command(cmdlist, &fs, NULL, CMDQ_NOHOOKS);
+ cmdq_format(new_item, "hook", "%s", ne->name);
+ notify_hook_formats(new_item, s, w, ne->pane);
- cmdq_insert_after(item, new_item);
+ cmdq_insert_after(item, new_item);
+ item = new_item;
+
+ a = options_array_next(a);
+ }
}
static enum cmd_retval
@@ -102,7 +128,7 @@ notify_callback(struct cmdq_item *item, void *data)
if (strcmp(ne->name, "session-window-changed") == 0)
control_notify_session_window_changed(ne->session);
- notify_hook1(item, ne);
+ notify_insert_hook(item, ne);
if (ne->client != NULL)
server_client_unref(ne->client);
@@ -169,7 +195,7 @@ notify_hook(struct cmdq_item *item, const char *name)
ne.window = item->target.w;
ne.pane = item->target.wp->id;
- notify_hook1(item, &ne);
+ notify_insert_hook(item, &ne);
}
void
diff --git a/usr.bin/tmux/options-table.c b/usr.bin/tmux/options-table.c
index 14cd41c8110..85cd09a7f25 100644
--- a/usr.bin/tmux/options-table.c
+++ b/usr.bin/tmux/options-table.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: options-table.c,v 1.104 2019/04/23 20:36:55 nicm Exp $ */
+/* $OpenBSD: options-table.c,v 1.105 2019/04/26 11:38:51 nicm Exp $ */
/*
* Copyright (c) 2011 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -130,8 +130,19 @@ static const char *options_table_status_format_default[] = {
OPTIONS_TABLE_STATUS_FORMAT1, OPTIONS_TABLE_STATUS_FORMAT2, NULL
};
+/* Helper for hook options. */
+#define OPTIONS_TABLE_HOOK(hook_name, default_value) \
+ { .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 = "" \
+ }
+
/* Top-level options. */
const struct options_table_entry options_table[] = {
+ /* Server options. */
{ .name = "buffer-limit",
.type = OPTIONS_TABLE_NUMBER,
.scope = OPTIONS_TABLE_SERVER,
@@ -224,6 +235,7 @@ const struct options_table_entry options_table[] = {
.separator = ","
},
+ /* Session options. */
{ .name = "activity-action",
.type = OPTIONS_TABLE_CHOICE,
.scope = OPTIONS_TABLE_SESSION,
@@ -542,6 +554,7 @@ const struct options_table_entry options_table[] = {
.default_str = " -_@"
},
+ /* Window options. */
{ .name = "aggressive-resize",
.type = OPTIONS_TABLE_FLAG,
.scope = OPTIONS_TABLE_WINDOW,
@@ -776,5 +789,66 @@ const struct options_table_entry options_table[] = {
.default_num = 1
},
+ /* 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-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-attached", ""),
+ OPTIONS_TABLE_HOOK("client-detached", ""),
+ OPTIONS_TABLE_HOOK("client-resized", ""),
+ OPTIONS_TABLE_HOOK("client-session-changed", ""),
+ OPTIONS_TABLE_HOOK("pane-died", ""),
+ OPTIONS_TABLE_HOOK("pane-exited", ""),
+ OPTIONS_TABLE_HOOK("pane-focus-in", ""),
+ OPTIONS_TABLE_HOOK("pane-focus-out", ""),
+ OPTIONS_TABLE_HOOK("pane-mode-changed", ""),
+ OPTIONS_TABLE_HOOK("pane-set-clipboard", ""),
+ OPTIONS_TABLE_HOOK("session-closed", ""),
+ OPTIONS_TABLE_HOOK("session-created", ""),
+ OPTIONS_TABLE_HOOK("session-renamed", ""),
+ OPTIONS_TABLE_HOOK("session-window-changed", ""),
+ OPTIONS_TABLE_HOOK("window-layout-changed", ""),
+ OPTIONS_TABLE_HOOK("window-linked", ""),
+ OPTIONS_TABLE_HOOK("window-pane-changed", ""),
+ OPTIONS_TABLE_HOOK("window-renamed", ""),
+ OPTIONS_TABLE_HOOK("window-unlinked", ""),
+
{ .name = NULL }
};
diff --git a/usr.bin/tmux/options.c b/usr.bin/tmux/options.c
index c7bd422aeb9..003f1547b6a 100644
--- a/usr.bin/tmux/options.c
+++ b/usr.bin/tmux/options.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: options.c,v 1.42 2019/04/25 18:18:55 nicm Exp $ */
+/* $OpenBSD: options.c,v 1.43 2019/04/26 11:38:51 nicm Exp $ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -76,6 +76,9 @@ static struct options_entry *options_add(struct options *, const char *);
#define OPTIONS_IS_STYLE(o) \
((o)->tableentry != NULL && \
(o)->tableentry->type == OPTIONS_TABLE_STYLE)
+#define OPTIONS_IS_COMMAND(o) \
+ ((o)->tableentry != NULL && \
+ (o)->tableentry->type == OPTIONS_TABLE_COMMAND)
#define OPTIONS_IS_ARRAY(o) \
((o)->tableentry != NULL && \
@@ -108,6 +111,8 @@ options_value_free(struct options_entry *o, union options_value *ov)
{
if (OPTIONS_IS_STRING(o))
free(ov->string);
+ if (OPTIONS_IS_COMMAND(o) && ov->cmdlist != NULL)
+ cmd_list_free(ov->cmdlist);
}
static char *
@@ -116,6 +121,8 @@ options_value_tostring(struct options_entry *o, union options_value *ov,
{
char *s;
+ if (OPTIONS_IS_COMMAND(o))
+ return (cmd_list_print(ov->cmdlist));
if (OPTIONS_IS_STYLE(o))
return (xstrdup(style_tostring(&ov->style)));
if (OPTIONS_IS_NUMBER(o)) {
@@ -140,6 +147,7 @@ options_value_tostring(struct options_entry *o, union options_value *ov,
break;
case OPTIONS_TABLE_STRING:
case OPTIONS_TABLE_STYLE:
+ case OPTIONS_TABLE_COMMAND:
fatalx("not a number option type");
}
return (s);
@@ -231,11 +239,12 @@ options_default(struct options *oo, const struct options_table_entry *oe)
ov = &o->value;
if (oe->flags & OPTIONS_TABLE_IS_ARRAY) {
- if (oe->default_arr != NULL) {
- for (i = 0; oe->default_arr[i] != NULL; i++)
- options_array_set(o, i, oe->default_arr[i], 0);
- } else
- options_array_assign(o, oe->default_str);
+ if (oe->default_arr == NULL) {
+ options_array_assign(o, oe->default_str, NULL);
+ return (o);
+ }
+ for (i = 0; oe->default_arr[i] != NULL; i++)
+ options_array_set(o, i, oe->default_arr[i], 0, NULL);
return (o);
}
@@ -340,13 +349,22 @@ options_array_get(struct options_entry *o, u_int idx)
int
options_array_set(struct options_entry *o, u_int idx, const char *value,
- int append)
+ int append, char **cause)
{
struct options_array_item *a;
char *new;
+ struct cmd_list *cmdlist;
- if (!OPTIONS_IS_ARRAY(o))
+ if (!OPTIONS_IS_ARRAY(o)) {
+ *cause = xstrdup("not an array");
return (-1);
+ }
+
+ if (OPTIONS_IS_COMMAND(o)) {
+ cmdlist = cmd_string_parse(value, NULL, 0, cause);
+ if (cmdlist == NULL && *cause != NULL)
+ return (-1);
+ }
a = options_array_item(o, idx);
if (value == NULL) {
@@ -355,25 +373,29 @@ options_array_set(struct options_entry *o, u_int idx, const char *value,
return (0);
}
- if (a == NULL) {
- a = xcalloc(1, sizeof *a);
- a->index = idx;
- a->value.string = xstrdup(value);
- RB_INSERT(options_array, &o->value.array, a);
- } else {
- options_value_free(o, &a->value);
+ if (OPTIONS_IS_STRING(o)) {
if (a != NULL && append)
xasprintf(&new, "%s%s", a->value.string, value);
else
new = xstrdup(value);
- a->value.string = new;
}
+ if (a == NULL) {
+ a = xcalloc(1, sizeof *a);
+ a->index = idx;
+ RB_INSERT(options_array, &o->value.array, a);
+ } else
+ options_value_free(o, &a->value);
+
+ if (OPTIONS_IS_STRING(o))
+ a->value.string = new;
+ else if (OPTIONS_IS_COMMAND(o))
+ a->value.cmdlist = cmdlist;
return (0);
}
-void
-options_array_assign(struct options_entry *o, const char *s)
+int
+options_array_assign(struct options_entry *o, const char *s, char **cause)
{
const char *separator;
char *copy, *next, *string;
@@ -382,7 +404,18 @@ options_array_assign(struct options_entry *o, const char *s)
separator = o->tableentry->separator;
if (separator == NULL)
separator = " ,";
+ if (*separator == '\0') {
+ if (*s == '\0')
+ return (0);
+ for (i = 0; i < UINT_MAX; i++) {
+ if (options_array_item(o, i) == NULL)
+ break;
+ }
+ return (options_array_set(o, i, s, 0, cause));
+ }
+ if (*s == '\0')
+ return (0);
copy = string = xstrdup(s);
while ((next = strsep(&string, separator)) != NULL) {
if (*next == '\0')
@@ -393,9 +426,13 @@ options_array_assign(struct options_entry *o, const char *s)
}
if (i == UINT_MAX)
break;
- options_array_set(o, i, next, 0);
+ if (options_array_set(o, i, next, 0, cause) != 0) {
+ free(copy);
+ return (-1);
+ }
}
free(copy);
+ return (0);
}
struct options_array_item *
diff --git a/usr.bin/tmux/session.c b/usr.bin/tmux/session.c
index 347f91b6699..dad169c9264 100644
--- a/usr.bin/tmux/session.c
+++ b/usr.bin/tmux/session.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: session.c,v 1.84 2019/04/17 14:37:48 nicm Exp $ */
+/* $OpenBSD: session.c,v 1.85 2019/04/26 11:38:51 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -129,7 +129,6 @@ session_create(const char *prefix, const char *name, const char *cwd,
s->environ = env;
s->options = oo;
- s->hooks = hooks_create(global_hooks);
status_update_cache(s);
@@ -193,9 +192,7 @@ session_free(__unused int fd, __unused short events, void *arg)
if (s->references == 0) {
environ_free(s->environ);
-
options_free(s->options);
- hooks_free(s->hooks);
free(s->name);
free(s);
diff --git a/usr.bin/tmux/status.c b/usr.bin/tmux/status.c
index ae18fa630f1..6b131791a66 100644
--- a/usr.bin/tmux/status.c
+++ b/usr.bin/tmux/status.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: status.c,v 1.195 2019/04/25 19:36:59 nicm Exp $ */
+/* $OpenBSD: status.c,v 1.196 2019/04/26 11:38:51 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -1323,7 +1323,7 @@ status_prompt_complete_list(u_int *size, const char *s)
while (a != NULL) {
value = options_array_item_value(a)->string;
if ((cp = strchr(value, '=')) == NULL)
- goto next;
+ goto next;
valuelen = cp - value;
if (slen > valuelen || strncmp(value, s, slen) != 0)
goto next;
diff --git a/usr.bin/tmux/tmux.1 b/usr.bin/tmux/tmux.1
index e0ea6f38ece..6659f45a157 100644
--- a/usr.bin/tmux/tmux.1
+++ b/usr.bin/tmux/tmux.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: tmux.1,v 1.639 2019/04/25 15:35:07 nicm Exp $
+.\" $OpenBSD: tmux.1,v 1.640 2019/04/26 11:38:51 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: April 25 2019 $
+.Dd $Mdocdate: April 26 2019 $
.Dt TMUX 1
.Os
.Sh NAME
@@ -3383,7 +3383,7 @@ function key sequences; these have a number included to indicate modifiers such
as Shift, Alt or Ctrl.
.El
.It Xo Ic show-options
-.Op Fl gqsvw
+.Op Fl gHqsvw
.Op Fl t Ar target-session | Ar target-window
.Op Ar option
.Xc
@@ -3415,6 +3415,8 @@ If
is set, no error will be returned if
.Ar option
is unset.
+.Fl H
+includes hooks (omitted by default).
.It Xo Ic show-window-options
.Op Fl gv
.Op Fl t Ar target-window
@@ -3439,6 +3441,26 @@ commands have an
.Em after
hook and there are a number of hooks not associated with commands.
.Pp
+Hooks are stored as array options, members of the array are executed in
+order when the hook is triggered.
+Hooks may be configured with the
+.Ic set-hook
+or
+.Ic set-option
+commands and displayed with
+.Ic show-hooks
+or
+.Ic show-options
+.Fl H .
+The following two commands are equivalent:
+.Bd -literal -offset indent.
+set-hook -g pane-mode-changed[42] 'set -g status-left-style bg=red'
+set-option -g pane-mode-changed[42] 'set -g status-left-style bg=red'
+.Ed
+.Pp
+Setting a hook without specifying an array index clears the hook and sets the
+first member of the array.
+.Pp
A command's after
hook is run after it completes, except when the command is run as part of a hook
itself.
@@ -3449,7 +3471,7 @@ For example, the following command adds a hook to select the even-vertical
layout after every
.Ic split-window :
.Bd -literal -offset indent
-set-hook after-split-window "selectl even-vertical"
+set-hook -g after-split-window "selectl even-vertical"
.Ed
.Pp
All the notifications listed in the
@@ -3513,7 +3535,7 @@ Run when a window is unlinked from a session.
Hooks are managed with these commands:
.Bl -tag -width Ds
.It Xo Ic set-hook
-.Op Fl gRu
+.Op Fl agRu
.Op Fl t Ar target-session
.Ar hook-name
.Ar command
@@ -3535,6 +3557,8 @@ hooks (for
.Ar target-session
with
.Fl t ) .
+.Fl a
+appends to a hook.
Like options, session hooks inherit from the global ones.
.Pp
With
diff --git a/usr.bin/tmux/tmux.c b/usr.bin/tmux/tmux.c
index b12fda88cd6..e837961022b 100644
--- a/usr.bin/tmux/tmux.c
+++ b/usr.bin/tmux/tmux.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tmux.c,v 1.187 2018/11/22 10:36:40 nicm Exp $ */
+/* $OpenBSD: tmux.c,v 1.188 2019/04/26 11:38:51 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -39,7 +39,6 @@ struct options *global_options; /* server options */
struct options *global_s_options; /* session options */
struct options *global_w_options; /* window options */
struct environ *global_environ;
-struct hooks *global_hooks;
struct timeval start_time;
const char *socket_path;
@@ -312,8 +311,6 @@ main(int argc, char **argv)
flags |= CLIENT_UTF8;
}
- global_hooks = hooks_create(NULL);
-
global_environ = environ_create();
for (var = environ; *var != NULL; var++)
environ_put(global_environ, *var);
diff --git a/usr.bin/tmux/tmux.h b/usr.bin/tmux/tmux.h
index b973655ff69..39e20e0df28 100644
--- a/usr.bin/tmux/tmux.h
+++ b/usr.bin/tmux/tmux.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: tmux.h,v 1.882 2019/04/25 18:18:55 nicm Exp $ */
+/* $OpenBSD: tmux.h,v 1.883 2019/04/26 11:38:51 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -683,15 +683,6 @@ struct style {
u_int range_argument;
};
-/* Hook data structures. */
-struct hook {
- const char *name;
-
- struct cmd_list *cmdlist;
-
- RB_ENTRY(hook) entry;
-};
-
/* Virtual screen. */
struct screen_sel;
struct screen_titles;
@@ -995,7 +986,6 @@ struct session {
int statusat;
u_int statuslines;
- struct hooks *hooks;
struct options *options;
#define SESSION_PASTING 0x1
@@ -1521,6 +1511,7 @@ union options_value {
long long number;
struct style style;
struct options_array array;
+ struct cmd_list *cmdlist;
};
/* Option table entries. */
@@ -1531,17 +1522,19 @@ enum options_table_type {
OPTIONS_TABLE_COLOUR,
OPTIONS_TABLE_FLAG,
OPTIONS_TABLE_CHOICE,
- OPTIONS_TABLE_STYLE
+ OPTIONS_TABLE_STYLE,
+ OPTIONS_TABLE_COMMAND
};
enum options_table_scope {
OPTIONS_TABLE_NONE,
OPTIONS_TABLE_SERVER,
OPTIONS_TABLE_SESSION,
- OPTIONS_TABLE_WINDOW,
+ OPTIONS_TABLE_WINDOW
};
#define OPTIONS_TABLE_IS_ARRAY 0x1
+#define OPTIONS_TABLE_IS_HOOK 0x2
struct options_table_entry {
const char *name;
@@ -1599,7 +1592,6 @@ struct spawn_context {
};
/* tmux.c */
-extern struct hooks *global_hooks;
extern struct options *global_options;
extern struct options *global_s_options;
extern struct options *global_w_options;
@@ -1693,20 +1685,6 @@ u_int format_width(const char *);
char *format_trim_left(const char *, u_int);
char *format_trim_right(const char *, u_int);
-/* hooks.c */
-struct hook;
-struct hooks *hooks_get(struct session *);
-struct hooks *hooks_create(struct hooks *);
-void hooks_free(struct hooks *);
-struct hook *hooks_first(struct hooks *);
-struct hook *hooks_next(struct hook *);
-void hooks_add(struct hooks *, const char *, struct cmd_list *);
-void hooks_copy(struct hooks *, struct hooks *);
-void hooks_remove(struct hooks *, const char *);
-struct hook *hooks_find(struct hooks *, const char *);
-void printflike(4, 5) hooks_insert(struct hooks *, struct cmdq_item *,
- struct cmd_find_state *, const char *, ...);
-
/* notify.c */
void notify_hook(struct cmdq_item *, const char *);
void notify_input(struct window_pane *, struct evbuffer *);
@@ -1734,8 +1712,9 @@ void options_remove(struct options_entry *);
void options_array_clear(struct options_entry *);
union options_value *options_array_get(struct options_entry *, u_int);
int options_array_set(struct options_entry *, u_int, const char *,
- int);
-void options_array_assign(struct options_entry *, const char *);
+ int, char **);
+int options_array_assign(struct options_entry *, const char *,
+ char **);
struct options_array_item *options_array_first(struct options_entry *);
struct options_array_item *options_array_next(struct options_array_item *);
u_int options_array_item_index(struct options_array_item *);
@@ -1956,6 +1935,8 @@ struct cmdq_item *cmdq_get_command(struct cmd_list *, struct cmd_find_state *,
struct cmdq_item *cmdq_get_callback1(const char *, cmdq_cb, void *);
void cmdq_insert_after(struct cmdq_item *, struct cmdq_item *);
void cmdq_append(struct client *, struct cmdq_item *);
+void cmdq_insert_hook(struct session *, struct cmdq_item *,
+ struct cmd_find_state *, const char *, ...);
void printflike(3, 4) cmdq_format(struct cmdq_item *, const char *,
const char *, ...);
u_int cmdq_next(struct client *);