summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.am2
-rw-r--r--cmd-new-session.c2
-rw-r--r--cmd-new-window.c2
-rw-r--r--cmd-queue.c56
-rw-r--r--cmd-select-pane.c2
-rw-r--r--cmd-select-window.c4
-rw-r--r--cmd-set-hook.c133
-rw-r--r--cmd-set-option.c39
-rw-r--r--cmd-show-options.c52
-rw-r--r--cmd-split-window.c2
-rw-r--r--cmd-string.c5
-rw-r--r--hooks.c173
-rw-r--r--notify.c74
-rw-r--r--options-table.c74
-rw-r--r--options.c73
-rw-r--r--session.c3
-rw-r--r--status.c2
-rw-r--r--tmux.130
-rw-r--r--tmux.c3
-rw-r--r--tmux.h39
20 files changed, 356 insertions, 414 deletions
diff --git a/Makefile.am b/Makefile.am
index 942a9e28..4f267a23 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -112,7 +112,6 @@ dist_tmux_SOURCES = \
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 \
@@ -135,7 +134,6 @@ dist_tmux_SOURCES = \
format-draw.c \
grid-view.c \
grid.c \
- hooks.c \
input-keys.c \
input.c \
job.c \
diff --git a/cmd-new-session.c b/cmd-new-session.c
index f0a353d8..6818ce9c 100644
--- a/cmd-new-session.c
+++ b/cmd-new-session.c
@@ -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/cmd-new-window.c b/cmd-new-window.c
index e3bacff8..1007c597 100644
--- a/cmd-new-window.c
+++ b/cmd-new-window.c
@@ -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/cmd-queue.c b/cmd-queue.c
index 03fd5f10..9ce25f5f 100644
--- a/cmd-queue.c
+++ b/cmd-queue.c
@@ -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/cmd-select-pane.c b/cmd-select-pane.c
index af0f033b..89c6fb20 100644
--- a/cmd-select-pane.c
+++ b/cmd-select-pane.c
@@ -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/cmd-select-window.c b/cmd-select-window.c
index f35b8202..54965e89 100644
--- a/cmd-select-window.c
+++ b/cmd-select-window.c
@@ -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/cmd-set-hook.c b/cmd-set-hook.c
deleted file mode 100644
index b04e6335..00000000
--- a/cmd-set-hook.c
+++ /dev/null
@@ -1,133 +0,0 @@
-/* $OpenBSD$ */
-
-/*
- * 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/cmd-set-option.c b/cmd-set-option.c
index edeb8385..7be561f2 100644
--- a/cmd-set-option.c
+++ b/cmd-set-option.c
@@ -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/cmd-show-options.c b/cmd-show-options.c
index 642b3f89..4948ff79 100644
--- a/cmd-show-options.c
+++ b/cmd-show-options.c
@@ -38,8 +38,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 },
@@ -60,6 +60,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)
{
@@ -161,15 +174,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);
@@ -177,8 +195,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);
@@ -199,16 +215,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/cmd-split-window.c b/cmd-split-window.c
index e64e9247..e9da1f3e 100644
--- a/cmd-split-window.c
+++ b/cmd-split-window.c
@@ -143,7 +143,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/cmd-string.c b/cmd-string.c
index 440a0231..058f997c 100644
--- a/cmd-string.c
+++ b/cmd-string.c
@@ -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/hooks.c b/hooks.c
deleted file mode 100644
index 361f3522..00000000
--- a/hooks.c
+++ /dev/null
@@ -1,173 +0,0 @@
-/* $OpenBSD$ */
-
-/*
- * 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/notify.c b/notify.c
index adef3d4e..163aa1a9 100644
--- a/notify.c
+++ b/notify.c
@@ -35,13 +35,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))
@@ -49,26 +70,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
@@ -101,7 +127,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);
@@ -168,7 +194,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/options-table.c b/options-table.c
index a8beea06..19cf39f4 100644
--- a/options-table.c
+++ b/options-table.c
@@ -129,8 +129,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,
@@ -223,6 +234,7 @@ const struct options_table_entry options_table[] = {
.separator = ","
},
+ /* Session options. */
{ .name = "activity-action",
.type = OPTIONS_TABLE_CHOICE,
.scope = OPTIONS_TABLE_SESSION,
@@ -541,6 +553,7 @@ const struct options_table_entry options_table[] = {
.default_str = " -_@"
},
+ /* Window options. */
{ .name = "aggressive-resize",
.type = OPTIONS_TABLE_FLAG,
.scope = OPTIONS_TABLE_WINDOW,
@@ -775,5 +788,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/options.c b/options.c
index fb271d5e..c5a776e5 100644
--- a/options.c
+++ b/options.c
@@ -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;
+ e