Final parts of command hooks, add before- and after- hooks to each command.

This commit is contained in:
nicm 2016-04-29 14:05:24 +00:00
parent c5443da2d3
commit 0d84fdd953
5 changed files with 86 additions and 10 deletions

View File

@ -157,6 +157,7 @@ cmd_if_shell_callback(struct job *job)
}
cmdq1 = cmdq_new(cmdq->client);
cmdq1->flags |= cmdq->flags & CMD_Q_NOHOOKS;
cmdq1->emptyfn = cmd_if_shell_done;
cmdq1->data = cdata;

View File

@ -186,6 +186,9 @@ static enum cmd_retval
cmdq_continue_one(struct cmd_q *cmdq)
{
struct cmd *cmd = cmdq->cmd;
const char *name = cmd->entry->name;
struct session *s;
struct hooks *hooks;
enum cmd_retval retval;
char *tmp;
int flags = !!(cmd->flags & CMD_CONTROL);
@ -197,19 +200,51 @@ cmdq_continue_one(struct cmd_q *cmdq)
cmdq->time = time(NULL);
cmdq->number++;
cmdq_guard(cmdq, "begin", flags);
if (~cmdq->flags & CMD_Q_REENTRY)
cmdq_guard(cmdq, "begin", flags);
if (cmd_prepare_state(cmd, cmdq, NULL) != 0)
if (cmd_prepare_state(cmd, cmdq, cmdq->parent) != 0)
goto error;
if (~cmdq->flags & CMD_Q_NOHOOKS) {
s = NULL;
if (cmdq->state.tflag.s != NULL)
s = cmdq->state.tflag.s;
else if (cmdq->state.sflag.s != NULL)
s = cmdq->state.sflag.s;
else if (cmdq->state.c != NULL)
s = cmdq->state.c->session;
if (s != NULL)
hooks = s->hooks;
else
hooks = global_hooks;
if (~cmdq->flags & CMD_Q_REENTRY) {
cmdq->flags |= CMD_Q_REENTRY;
if (hooks_wait(hooks, cmdq, NULL,
"before-%s", name) == 0)
return (CMD_RETURN_WAIT);
if (cmd_prepare_state(cmd, cmdq, cmdq->parent) != 0)
goto error;
}
} else
hooks = NULL;
cmdq->flags &= ~CMD_Q_REENTRY;
retval = cmd->entry->exec(cmd, cmdq);
if (retval == CMD_RETURN_ERROR)
goto error;
if (hooks != NULL && hooks_wait(hooks, cmdq, NULL,
"after-%s", name) == 0)
retval = CMD_RETURN_WAIT;
cmdq_guard(cmdq, "end", flags);
return (retval);
error:
cmdq_guard(cmdq, "error", flags);
cmdq->flags &= ~CMD_Q_REENTRY;
return (CMD_RETURN_ERROR);
}
@ -232,11 +267,18 @@ cmdq_continue(struct cmd_q *cmdq)
if (empty)
goto empty;
if (cmdq->item == NULL) {
cmdq->item = TAILQ_FIRST(&cmdq->queue);
cmdq->cmd = TAILQ_FIRST(&cmdq->item->cmdlist->list);
} else
cmdq->cmd = TAILQ_NEXT(cmdq->cmd, qentry);
/*
* If the command isn't in the middle of running hooks (due to
* CMD_RETURN_WAIT), move onto the next command; otherwise, leave the
* state of the queue as it is.
*/
if (~cmdq->flags & CMD_Q_REENTRY) {
if (cmdq->item == NULL) {
cmdq->item = TAILQ_FIRST(&cmdq->queue);
cmdq->cmd = TAILQ_FIRST(&cmdq->item->cmdlist->list);
} else
cmdq->cmd = TAILQ_NEXT(cmdq->cmd, qentry);
}
do {
while (cmdq->cmd != NULL) {

View File

@ -49,6 +49,7 @@ cmd_source_file_exec(struct cmd *self, struct cmd_q *cmdq)
char *cause;
cmdq1 = cmdq_new(cmdq->client);
cmdq1->flags |= cmdq->flags & CMD_Q_NOHOOKS;
cmdq1->emptyfn = cmd_source_file_done;
cmdq1->data = cmdq;

View File

@ -468,6 +468,7 @@ struct format_tree *
format_create(struct cmd_q *cmdq, int flags)
{
struct format_tree *ft;
struct cmd *cmd;
if (!event_initialized(&format_job_event)) {
evtimer_set(&format_job_event, format_job_timer, NULL);
@ -486,6 +487,10 @@ format_create(struct cmd_q *cmdq, int flags)
if (cmdq != NULL && cmdq->cmd != NULL)
format_add(ft, "command_name", "%s", cmdq->cmd->entry->name);
if (cmdq != NULL && cmdq->parent != NULL) {
cmd = cmdq->parent->cmd;
format_add(ft, "command_hooked", "%s", cmd->entry->name);
}
return (ft);
}

33
tmux.1
View File

@ -3221,9 +3221,35 @@ shows only the option value, not the name.
.Nm
allows commands to run on various triggers, called
.Em hooks .
Each hook has a
.Em name .
The following hooks are available:
Each
.Nm
command has a
.Em before
hook and an
.Em after
hook and there are a number of hooks not associated with commands.
.Pp
A command's before hook is run before the command is executed and its after
hook is run afterwards, except when the command is run as part of a hook
itself.
Before hooks are named using the
.Ql before-
prefix and after hooks the
.Ql after-
prefix.
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"
.Ed
.Pp
Or to write when each new window is created to a file:
.Bd -literal -offset indent
set-hook before-new-window 'run "date >>/tmp/log"'
.Ed
.Pp
In addition, the following hooks are available:
.Bl -tag -width "XXXXXXXXXXXXXXXX"
.It alert-activity
Run when a window has activity.
@ -3450,6 +3476,7 @@ The following variables are available, where appropriate:
.It Li "client_tty" Ta "" Ta "Pseudo terminal of client"
.It Li "client_utf8" Ta "" Ta "1 if client supports utf8"
.It Li "client_width" Ta "" Ta "Width of client"
.It Li "command_hooked" Ta "" Ta "Name of command hooked, if any"
.It Li "command_name" Ta "" Ta "Name of command in use, if any"
.It Li "cursor_flag" Ta "" Ta "Pane cursor flag"
.It Li "cursor_x" Ta "" Ta "Cursor X position in pane"