diff options
-rw-r--r-- | cmd-if-shell.c | 1 | ||||
-rw-r--r-- | cmd-queue.c | 56 | ||||
-rw-r--r-- | cmd-source-file.c | 1 | ||||
-rw-r--r-- | format.c | 5 | ||||
-rw-r--r-- | tmux.1 | 33 |
5 files changed, 86 insertions, 10 deletions
diff --git a/cmd-if-shell.c b/cmd-if-shell.c index 3e2a5251..2f47a0d7 100644 --- a/cmd-if-shell.c +++ b/cmd-if-shell.c @@ -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; diff --git a/cmd-queue.c b/cmd-queue.c index 1c80c59d..c35d0c62 100644 --- a/cmd-queue.c +++ b/cmd-queue.c @@ -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) { diff --git a/cmd-source-file.c b/cmd-source-file.c index 9d2d6d68..d5f5209a 100644 --- a/cmd-source-file.c +++ b/cmd-source-file.c @@ -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; @@ -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); } @@ -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" |