mirror of
https://github.com/tmux/tmux.git
synced 2025-01-05 23:38:48 +00:00
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).
This commit is contained in:
parent
f1e14f86c4
commit
dfb7bb6830
2
Makefile
2
Makefile
@ -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 \
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
56
cmd-queue.c
56
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:
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
133
cmd-set-hook.c
133
cmd-set-hook.c
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
173
hooks.c
173
hooks.c
@ -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);
|
||||
}
|
74
notify.c
74
notify.c
@ -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);
|
||||
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);
|
||||
item = new_item;
|
||||
|
||||
a = options_array_next(a);
|
||||
}
|
||||
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);
|
||||
|
||||
cmdq_insert_after(item, new_item);
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -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 }
|
||||
};
|
||||
|
73
options.c
73
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;
|
||||
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 *
|
||||
|
@ -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);
|
||||
|
2
status.c
2
status.c
@ -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;
|
||||
|
30
tmux.1
30
tmux.1
@ -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
|
||||
|
3
tmux.c
3
tmux.c
@ -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);
|
||||
|
39
tmux.h
39
tmux.h
@ -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 *);
|
||||
|
Loading…
Reference in New Issue
Block a user