The branch, hooks has been updated
  discards  dd07310fd7074d92c6db916188009fdcef995d6e (commit)
  discards  176e90bc0a6e25f2263b01b4c26c2631d0409eaf (commit)
  discards  24f81102d5f3106aa01c09c5d826de3b4a78944f (commit)
  discards  3091598cd78b124f0b3a62dec04e6a7c39243de0 (commit)
  discards  cbccf553f6d9f41f981fe1953de71b9881df42e9 (commit)
  discards  b4d577407ae5cb1f4ad9ee84e0e39ca3c625b796 (commit)
  discards  5c57048647aa9cb2e74a427fe50c160014967784 (commit)
       via  8e2cab16cbca65ccb25a79068f32e24436a7aae5 (commit)
       via  aefdd9c368013008a566257bc99d4bdde4c65f65 (commit)
       via  9178a39f431d89d8c30307f9a5843986fa743fa4 (commit)
       via  d9bec8233a3f3dd44795efb2d8a93255a0856a56 (commit)
       via  1bb3aa6f7ea481412adcde41ba228b564a245123 (commit)
       via  5c2831bcf2f265065d3e0bb18ad51f7e754e5060 (commit)
       via  2103ae2e24a53668f9ca003d2b28f6f3c1eaa02f (commit)
       via  ccbe2545d9857e03731eddb9757989b9f52dc785 (commit)
       via  54ca7b230d08aae0b2028f3f82a259963017c167 (commit)
       via  575fd1e322b15a3e9f0d1892ebb82c2e8a30ba46 (commit)
       via  e52d7912122177ddff952feccc192a3f357b9d1b (commit)
       via  c8bf8ee931e4ccfe709f5ac36fb210e938eeec50 (commit)
       via  c403bfc89488bf3867cee9d5c3b4083a3f80bee6 (commit)
       via  a3612a5472ec5ecf1ffbb1c3cdea58d6b709478d (commit)

This update added new revisions after undoing existing revisions.  That is
to say, the old revision is not a strict subset of the new revision.  This
situation occurs when you --force push a change and generate a repository
containing something like this:

 * -- * -- B -- O -- O -- O (dd07310fd7074d92c6db916188009fdcef995d6e)
            \
             N -- N -- N (8e2cab16cbca65ccb25a79068f32e24436a7aae5)

When this happens we assume that you've already had alert emails for all
of the O revisions, and so we here report only the revisions in the N
branch from the common base, B.

- Log -----------------------------------------------------------------
commit 8e2cab16cbca65ccb25a79068f32e24436a7aae5
Author: Thomas Adam <tho...@xteddy.org>
Commit: Thomas Adam <tho...@xteddy.org>

    Update HOOK-NOTES
---
 HOOK-NOTES |   56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 56 insertions(+), 0 deletions(-)

diff --git a/HOOK-NOTES b/HOOK-NOTES
index de7bbdf..1104a96 100644
--- a/HOOK-NOTES
+++ b/HOOK-NOTES
@@ -60,3 +60,59 @@
 22:37 <         NicM> | anyway it seems like it'd work
 22:48 <  thomas_adam> | I'll give that a go.
 
+Then later...
+
+            nicm | so for example
+            nicm | kill-session prepare does this {state->s =
+                 | cmd_find_session(args_get('t'),NULL)} then kill-session exec
+                 | does {s = cmd_find_session(args_get('t'),state->s)}
+            nicm | list-keys prepare does {state->s = cmd_current_session()} 
and
+                 | swapw does {s = cmd_find_session('t',state->s}
+     thomas_adam | Ugh. 
+     thomas_adam | That's just confusing.
+            nicm | well, there may be alternatives
+            nicm | but the important thing is, kill-session's prepare has to 
set
+                 | up a state suitable for ANY command
+     thomas_adam | The point of prepare() was to try and centralise these
+                 | things, not spread them about.
+            nicm | it can't assume it will only be used for kill-session
+     thomas_adam | Hmm.
+     thomas_adam | Yes.
+            nicm | well, no, the point of prepare is to allow the current
+                 | session to be replaced in hooks
+            nicm | new-session and new-window and after- hooks have a different
+                 | issue too, because there we want to default to the NEW
+                 | session
+            nicm | so they need to update the state for subsequent commands
+     thomas_adam | Interesting.  Yes.
+            nicm | i think this would work, but you will need to parse -t twice
+            nicm | - there is a state which is current {win,sess,client} - 
there
+                 | is the "actual" command being run, and the "hook" commands -
+                 | state is set up by running the "actual" command prepare 
which
+                 | looks at the actual -t etc - then the before-hooks use that
+                 | state for their current {sess,win,client} - the actual
+                 | command is then run with the state too, and updates it if
+                 | needed - the after hooks use the updated state for their
+                 | current {win,se
+     thomas_adam | Yeah.  OK.
+            nicm | command sequences are irrelevent -- new command, new state  
 
+     thomas_adam | I can see how this is needed.
+            nicm | so: "lsw\; lsk\; killw" has three states and three different
+                 | prepare()s are called
+            nicm | this only matters for the before and after hooks
+            nicm | i think you will find it works well for simple commands with
+                 | no -t or just -t
+            nicm | -t -s might be more fiddly but i don't care so much about  
+                 | that
+            nicm | well, it might be ok
+            nicm | at the moment there is only one "current session"
+            nicm | so i'd pick one or the other to be the current if you have 
-t
+                 | and -s
+            nicm | for a first iteration that'd be fine, if people start 
wanting
+                 | to write hooks that are fancy and need to know both we can 
do
+                 | something else
+     thomas_adam | OK.  This is starting to make a lot more sense in my head
+                 | now.
+     thomas_adam | Yes, I'm starting to remember these subtlties the last time 
I
+                 | looked at this.
+


commit aefdd9c368013008a566257bc99d4bdde4c65f65
Author: Thomas Adam <tho...@xteddy.org>
Commit: Thomas Adam <tho...@xteddy.org>

    Rename current -> default state
---
 cmd-queue.c |   19 ++++++++++---------
 tmux.h      |    2 +-
 2 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/cmd-queue.c b/cmd-queue.c
index 1df40fc..f16a339 100644
--- a/cmd-queue.c
+++ b/cmd-queue.c
@@ -33,16 +33,17 @@ void        cmdq_run_hook(struct hooks *, const char *, 
struct cmd *,
 void
 cmdq_set_state(struct cmd_q *cmdq)
 {
-       memset(&cmdq->current_state, 0, sizeof cmdq->current_state);
+       memset(&cmdq->default_state, 0, sizeof cmdq->default_state);
 
-       cmdq->current_state.c = cmdq->client;
+       cmdq->default_state.c = cmdq->client;
 
-       cmdq->current_state.s = cmdq->client != NULL ? cmdq->client->session : 
NULL;
-       cmdq->current_state.s2 = NULL;
+       cmdq->default_state.s = cmdq->client != NULL ?
+               cmdq->client->session : NULL;
+       cmdq->default_state.s2 = NULL;
 
-       cmdq->current_state.w = NULL;
-       cmdq->current_state.wl = NULL;
-       cmdq->current_state.wp = NULL;
+       cmdq->default_state.w = NULL;
+       cmdq->default_state.wl = NULL;
+       cmdq->default_state.wp = NULL;
 }
 
 /* Create new command queue. */
@@ -232,8 +233,8 @@ cmdq_continue(struct cmd_q *cmdq)
                         * otherwise used the intended session's hooks when
                         * running the command.
                         */
-                       if (cmdq->current_state.s != NULL)
-                               hooks = &cmdq->current_state.s->hooks;
+                       if (cmdq->default_state.s != NULL)
+                               hooks = &cmdq->default_state.s->hooks;
                        else
                                hooks = &global_hooks;
 
diff --git a/tmux.h b/tmux.h
index fc571fb..26c666d 100644
--- a/tmux.h
+++ b/tmux.h
@@ -1422,8 +1422,8 @@ struct cmd_q {
        struct cmd_q_items       queue;
        struct cmd_q_item       *item;
        struct cmd              *cmd;
-       struct cmd_state         default_state;
        struct cmd_state         current_state;
+       struct cmd_state         default_state;
 
        time_t                   time;
        u_int                    number;


commit 9178a39f431d89d8c30307f9a5843986fa743fa4
Author: Thomas Adam <tho...@xteddy.org>
Commit: Thomas Adam <tho...@xteddy.org>

    Add HOOK-NOTES
    
    Temporarily add some notes about how hooks might work whilst they're being
    worked on.
---
 HOOK-NOTES |   62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 62 insertions(+), 0 deletions(-)

diff --git a/HOOK-NOTES b/HOOK-NOTES
new file mode 100644
index 0000000..de7bbdf
--- /dev/null
+++ b/HOOK-NOTES
@@ -0,0 +1,62 @@
+22:08 < NicM> thomas_adam?
+22:08 < thomas_adam> Hi.
+22:09 < NicM> what happens if you put a command that needs prepare_session in 
the before hook of a command that doesn't?
+22:11 < thomas_adam> Hmm.
+22:11 < thomas_adam> Let's see.
+22:12 < NicM> the commands in the hooks need their own prepare to be called. 
not the prepare of the "hooked" command
+22:13 < NicM> eg if you put swapw -s x -t y in eg before-list-keys then it'll 
fail because possibly wl and definitely wl2 will not be filled in
+22:13 < NicM> or worse it'll do the wrong thing entirely
+22:13 < thomas_adam> Should fix that then.
+22:13 < NicM> either prepare needs to be called for each command separately in 
which case there is no point
+22:14 < NicM> or prepare needs to setup the default context and the command 
then overrides it with it's own -t -s or whatever
+22:14 < thomas_adam> Maybe that's better.
+22:14 < NicM> well, the problem there is that the original aim is lost
+22:15 < NicM> where if you do kill-session -t foo, the before hook should run 
with default session == foo
+22:15 < NicM> so if you set the before-hook to eg rename-session bar it 
renames foo, not the current session
+22:16 < NicM> silly and useless examples but you get the point, they need to 
work :-)
+22:16 < NicM> i have made a load of changes to the prepare diff
+22:16 < NicM> i'll send it to you anyway and if it is ok i'll commit it to the 
branch
+22:16 < thomas_adam> Then it probably can only work by always calling 
prepare(); otherwise we'll have to completely redefine contexts in some way, 
which I don't like either.
+22:16 < thomas_adam> Sure.
+22:17 < NicM> at the moment prepare can't be called multiple times or you will 
get multiple messages
+22:17 < NicM> it either needs to be side-effect free or it needs to return 
success/failure
+22:17 < NicM> either so you can call multiple prepares and defer the error for 
the command (first option)
+22:18 < NicM> or so you can do if (cmd-prepare() != success) { return; } ... 
before_hook->prepare();
+22:18 < NicM> ie don't call the second prepare if the first one fails
+22:18 < NicM> that means the prepare needs to take the NULL checking from 
exec() too
+22:18 < NicM> sent the diff anyway
+22:20 < thomas_adam> I'll take a look.
+22:20 < NicM> i think returning an error would be better maybe
+22:21 < NicM> but sure think about it and we can talk about it later
+22:24 <  thomas_adam> | Hmm.  That's a really good point.
+22:27 <         NicM> | maybe it is just being too clever trying to make the 
default session be whatever you specified for the hooked command -t
+22:27 <         NicM> | in order to make that work
+22:28 <         NicM> | you need prepare to fill in the state for the hooked 
command
+22:28 <         NicM> | then the prepare of the before/after command needs to 
use that state IF -t is not giv en for them
+22:28 <         NicM> | ie instead of calling cmd_current_session or whatever 
they need to look in cmdq->stat e.s
+22:28 <         NicM> | and fill that into THEIR state
+22:29 <  thomas_adam> | Yeah...
+22:29 <  thomas_adam> | That'd work, and be less invasive.
+22:29 <         NicM> | so basically i think the cmdq state would be the 
default state
+22:29 <         NicM> | and then you'd have a local state for each one
+22:29 <         NicM> | so you'd do this
+22:29 <         NicM> | cmd_prepare(hooked_cmd, &cmdq->state, NULL/*default 
state*/)
+22:30 <         NicM> | struct cmd_state before_state; cmd_prepare(before_cmd, 
&before_state, &cmdq->state); cmd_exec(before_cmd)
+22:30 <         NicM> | and then the same for after
+22:30 <         NicM> | er cmd_exec(before_cmd, &before_state)
+22:30 <         NicM> | or put it in the struct cmd would be better
+22:31 <         NicM> | or maybe in the cmdq, but have two members
+22:31 <         NicM> | i dunno
+22:31 <  thomas_adam> | Yeah... that ought to work.
+22:31 <         NicM> | in the cmdq would be better
+22:32 <         NicM> | ie cmdq has two members, current-command-state and 
default-command-state
+22:32 <         NicM> | cmdq would be best because it's already passed into 
prepare and exec and all the cmd.c functions
+22:33 <  thomas_adam> | That shouldn't be too hard to do.
+22:33 <  thomas_adam> | BRB...
+22:33 <         NicM> | yeh since exec is only called in two places now
+22:34 <         NicM> | basically cmdq_continue does what it does now but with 
the default state and copies that into the current state before exec
+22:36 <         NicM> | or it may be better to copy to the default state
+22:37 <         NicM> | so prepare always fills in current state then we copy 
to default so the before can use it, we call the before prepare and it 
overwrites the current, then we call before exec, then we copy default back to 
current to call the hooked command
+22:37 <         NicM> | anyway it seems like it'd work
+22:48 <  thomas_adam> | I'll give that a go.
+


commit d9bec8233a3f3dd44795efb2d8a93255a0856a56
Author: Thomas Adam <tho...@xteddy.org>
Commit: Thomas Adam <tho...@xteddy.org>

    SQUASH:  FIXUP
---
 cmd-attach-session.c |   10 +++++-----
 cmd-kill-window.c    |    4 ++--
 cmd-list-keys.c      |    2 +-
 cmd-move-window.c    |    4 ++--
 cmd-new-session.c    |    6 +++---
 cmd-paste-buffer.c   |   11 -----------
 cmd-set-hook.c       |    1 -
 cmd-show-hooks.c     |    2 --
 cmd-show-messages.c  |    6 +++---
 cmd-switch-client.c  |    7 ++++---
 tmux.h               |    3 ++-
 11 files changed, 22 insertions(+), 34 deletions(-)

diff --git a/cmd-attach-session.c b/cmd-attach-session.c
index 2f7e230..f1b5ace 100644
--- a/cmd-attach-session.c
+++ b/cmd-attach-session.c
@@ -43,7 +43,8 @@ const struct cmd_entry cmd_attach_session_entry = {
 };
 
 enum cmd_retval
-cmd_attach_session(struct cmd_q *cmdq, int dflag, int rflag, const char *cflag)
+cmd_attach_session(struct cmd_q *cmdq, const char *tflag, int dflag, int rflag,
+    const char *cflag)
 {
        struct session          *s;
        struct client           *c;
@@ -62,7 +63,6 @@ cmd_attach_session(struct cmd_q *cmdq, int dflag, int rflag, 
const char *cflag)
                return (CMD_RETURN_ERROR);
        }
 
-<<<<<<< HEAD
        if (tflag == NULL) {
                if ((s = cmd_find_session(cmdq, tflag, 1)) == NULL)
                        return (CMD_RETURN_ERROR);
@@ -79,7 +79,7 @@ cmd_attach_session(struct cmd_q *cmdq, int dflag, int rflag, 
const char *cflag)
                        wl = winlink_find_by_window(&s->windows, w);
        }
        /* TA:  Likely broken! */
-       if ((s = cmdq->state.s) == NULL)
+       if ((s = cmdq->default_state.s) == NULL)
                return (CMD_RETURN_ERROR);
 
        if (cmdq->client == NULL)
@@ -194,6 +194,6 @@ cmd_attach_session_exec(struct cmd *self, struct cmd_q 
*cmdq)
 {
        struct args     *args = self->args;
 
-       return (cmd_attach_session(cmdq, args_has(args, 'd'), args_has(args,
-           'r'), args_get(args, 'c')));
+       return (cmd_attach_session(cmdq, args_get(args, 't'),
+               args_has(args, 'd'), args_has(args, 'r'), args_get(args, 'c')));
 }
diff --git a/cmd-kill-window.c b/cmd-kill-window.c
index 0c484fc..0d55015 100644
--- a/cmd-kill-window.c
+++ b/cmd-kill-window.c
@@ -57,6 +57,7 @@ cmd_kill_window_exec(struct cmd *self, struct cmd_q *cmdq)
        if ((wl = cmdq->current_state.wl) == NULL)
                return (CMD_RETURN_ERROR);
        w = wl->window;
+       s = cmdq->current_state.s;
 
        if (self->entry == &cmd_unlink_window_entry) {
                sg = session_group_find(s);
@@ -67,8 +68,7 @@ cmd_kill_window_exec(struct cmd *self, struct cmd_q *cmdq)
                if (!args_has(self->args, 'k') && w->references == references) {
                        cmdq_error(cmdq, "window only linked to one session");
                        return (CMD_RETURN_ERROR);
-       s = cmdq->current_state.s;
-
+               }
        } else {
                if (args_has(args, 'a')) {
                        RB_FOREACH_SAFE(wl2, winlinks, &s->windows, wl3) {
diff --git a/cmd-list-keys.c b/cmd-list-keys.c
index bd18b2b..de8310e 100644
--- a/cmd-list-keys.c
+++ b/cmd-list-keys.c
@@ -45,7 +45,7 @@ const struct cmd_entry cmd_list_commands_entry = {
        "", 0, 0,
        "",
        0,
-       cmd_list_keys_exec
+       cmd_list_keys_exec,
        NULL
 };
 
diff --git a/cmd-move-window.c b/cmd-move-window.c
index a246601..34b5284 100644
--- a/cmd-move-window.c
+++ b/cmd-move-window.c
@@ -34,8 +34,8 @@ const struct cmd_entry cmd_move_window_entry = {
        "dkrs:t:", 0, 0,
        "[-dkr] " CMD_SRCDST_WINDOW_USAGE,
        0,
-<<<<<<< HEAD
-       cmd_move_window_exec
+       cmd_move_window_exec,
+       NULL
 };
 
 const struct cmd_entry cmd_link_window_entry = {
diff --git a/cmd-new-session.c b/cmd-new-session.c
index 084aa88..0a05cde 100644
--- a/cmd-new-session.c
+++ b/cmd-new-session.c
@@ -51,7 +51,7 @@ const struct cmd_entry cmd_has_session_entry = {
        "t:", 0, 0,
        CMD_TARGET_SESSION_USAGE,
        0,
-       cmd_new_session_exec
+       cmd_new_session_exec,
        NULL
 };
 
@@ -92,8 +92,8 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
                }
                if (session_find(newname) != NULL) {
                        if (args_has(args, 'A')) {
-                               return (cmd_attach_session(cmdq, args_has(args,
-                                   'D'), 0, NULL));
+                               return (cmd_attach_session(cmdq, newname,
+                                   args_has(args, 'D'), 0, NULL));
                        }
                        cmdq_error(cmdq, "duplicate session: %s", newname);
                        return (CMD_RETURN_ERROR);
diff --git a/cmd-paste-buffer.c b/cmd-paste-buffer.c
index 41568dd..cc5c090 100644
--- a/cmd-paste-buffer.c
+++ b/cmd-paste-buffer.c
@@ -58,17 +58,6 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
 
        wp = cmdq->current_state.wp;
 
-       if (!args_has(args, 'b'))
-               buffer = -1;
-       else {
-               buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
-               if (cause != NULL) {
-                       cmdq_error(cmdq, "buffer %s", cause);
-                       free(cause);
-                       return (CMD_RETURN_ERROR);
-               }
-       }
-
        if (bufname == NULL)
                pb = paste_get_top();
        else {
diff --git a/cmd-set-hook.c b/cmd-set-hook.c
index 6879d63..df27ca1 100644
--- a/cmd-set-hook.c
+++ b/cmd-set-hook.c
@@ -35,7 +35,6 @@ const struct cmd_entry cmd_set_hook_entry = {
        "gt:u", 1, 2,
        "[-gu]" CMD_TARGET_SESSION_USAGE " hook-name [command]",
        CMD_PREPARESESSION,
-       NULL,
        cmd_set_hook_exec,
        NULL
 };
diff --git a/cmd-show-hooks.c b/cmd-show-hooks.c
index b3e87bd..64c7db3 100644
--- a/cmd-show-hooks.c
+++ b/cmd-show-hooks.c
@@ -28,14 +28,12 @@
  */
 
 enum cmd_retval cmd_show_hooks_exec(struct cmd *, struct cmd_q *);
-void           cmd_show_hooks_prepare(struct cmd *, struct cmd_q *);
 
 const struct cmd_entry cmd_show_hooks_entry = {
        "show-hooks", NULL,
        "gt:", 0, 1,
        "[-g] " CMD_TARGET_SESSION_USAGE,
        CMD_PREPARESESSION,
-       NULL,
        cmd_show_hooks_exec,
        NULL
 };
diff --git a/cmd-show-messages.c b/cmd-show-messages.c
index b755351..88ec5ba 100644
--- a/cmd-show-messages.c
+++ b/cmd-show-messages.c
@@ -34,9 +34,7 @@ const struct cmd_entry cmd_show_messages_entry = {
        "show-messages", "showmsgs",
        "IJTt:", 0, 0,
        "[-IJT] " CMD_TARGET_CLIENT_USAGE,
-       CMD_TARGET_CLIENT_USAGE,
        CMD_PREPARECLIENT,
-       NULL,
        cmd_show_messages_exec,
        NULL
 };
@@ -46,7 +44,8 @@ const struct cmd_entry cmd_server_info_entry = {
        "", 0, 0,
        "",
        0,
-       cmd_show_messages_exec
+       cmd_show_messages_exec,
+       NULL
 };
 
 void   cmd_show_messages_server(struct cmd_q *);
@@ -128,6 +127,7 @@ cmd_show_messages_jobs(struct cmd_q *cmdq)
 enum cmd_retval
 cmd_show_messages_exec(unused struct cmd *self, struct cmd_q *cmdq)
 {
+       struct args             *args = self->args;
        struct client           *c;
        struct message_entry    *msg;
        char                    *tim;
diff --git a/cmd-switch-client.c b/cmd-switch-client.c
index 5a99fe5..949ec15 100644
--- a/cmd-switch-client.c
+++ b/cmd-switch-client.c
@@ -113,9 +113,10 @@ cmd_switch_client_exec(struct cmd *self, struct cmd_q 
*cmdq)
                                window_set_active_pane(wp->window, wp);
                        session_set_current(s, wl);
                }
-       } else
-               if ((s = cmdq->state.s) == NULL)
-                       return (CMD_RETURN_ERROR);
+       }
+
+       if ((s = cmdq->current_state.s) == NULL)
+               return (CMD_RETURN_ERROR);
 
        if (c->session != NULL)
                c->last_session = c->session;
diff --git a/tmux.h b/tmux.h
index 5e31452..fc571fb 100644
--- a/tmux.h
+++ b/tmux.h
@@ -1869,7 +1869,8 @@ extern const struct cmd_entry cmd_up_pane_entry;
 extern const struct cmd_entry cmd_wait_for_entry;
 
 /* cmd-attach-session.c */
-enum cmd_retval         cmd_attach_session(struct cmd_q *, int, int, const 
char *);
+enum cmd_retval         cmd_attach_session(struct cmd_q *, const char *, int, 
int,
+       const char *);
 
 /* cmd-list.c */
 struct cmd_list        *cmd_list_parse(int, char **, const char *, u_int, char 
**);


commit 1bb3aa6f7ea481412adcde41ba228b564a245123
Author: Thomas Adam <tho...@xteddy.org>
Commit: Thomas Adam <tho...@xteddy.org>

    Provide current_state and default_state for cmds
    
    So that we don't trample on different contexts when interpolating out which
    sessions, winlinks, panes to use, etc.  These will be used when deriving the
    hook's context for the given command.
    
    Currently renamed cmdq->state to cmdq->current_state; implementation for
    default_state comes later.
---
 cmd-break-pane.c       |    6 +++---
 cmd-capture-pane.c     |    2 +-
 cmd-choose-buffer.c    |    4 ++--
 cmd-choose-client.c    |    4 ++--
 cmd-choose-tree.c      |    6 +++---
 cmd-clear-history.c    |    2 +-
 cmd-clock-mode.c       |    2 +-
 cmd-command-prompt.c   |    2 +-
 cmd-confirm-before.c   |    2 +-
 cmd-copy-mode.c        |    2 +-
 cmd-detach-client.c    |    8 ++++----
 cmd-display-message.c  |   20 ++++++++++----------
 cmd-display-panes.c    |    2 +-
 cmd-find-window.c      |    4 ++--
 cmd-has-session.c      |    2 +-
 cmd-if-shell.c         |   14 +++++++-------
 cmd-join-pane.c        |   18 +++++++++---------
 cmd-kill-pane.c        |    4 ++--
 cmd-kill-session.c     |    2 +-
 cmd-kill-window.c      |    4 ++--
 cmd-list-clients.c     |    2 +-
 cmd-list-panes.c       |   10 +++++-----
 cmd-list-windows.c     |    4 ++--
 cmd-lock-server.c      |    8 ++++----
 cmd-move-window.c      |   20 ++++++++++----------
 cmd-new-window.c       |   10 +++++-----
 cmd-paste-buffer.c     |    4 ++--
 cmd-pipe-pane.c        |    4 ++--
 cmd-queue.c            |   18 +++++++++---------
 cmd-refresh-client.c   |    2 +-
 cmd-rename-session.c   |    2 +-
 cmd-rename-window.c    |    2 +-
 cmd-resize-pane.c      |    4 ++--
 cmd-respawn-pane.c     |    6 +++---
 cmd-respawn-window.c   |    4 ++--
 cmd-rotate-window.c    |    2 +-
 cmd-run-shell.c        |    8 ++++----
 cmd-select-layout.c    |    2 +-
 cmd-select-pane.c      |   12 ++++++------
 cmd-select-window.c    |   12 ++++++------
 cmd-send-keys.c        |    6 +++---
 cmd-set-environment.c  |    2 +-
 cmd-set-hook.c         |    2 +-
 cmd-show-environment.c |    2 +-
 cmd-show-hooks.c       |    2 +-
 cmd-show-messages.c    |    2 +-
 cmd-show-options.c     |    8 ++++----
 cmd-split-window.c     |    6 +++---
 cmd-swap-pane.c        |    4 ++--
 cmd-swap-window.c      |   16 ++++++++--------
 cmd-switch-client.c    |    6 +++---
 cmd.c                  |    4 ++--
 tmux.h                 |    3 ++-
 53 files changed, 155 insertions(+), 154 deletions(-)

diff --git a/cmd-break-pane.c b/cmd-break-pane.c
index 21d621e..8c17339 100644
--- a/cmd-break-pane.c
+++ b/cmd-break-pane.c
@@ -55,10 +55,10 @@ cmd_break_pane_exec(struct cmd *self, struct cmd_q *cmdq)
        const char              *template;
        char                    *cp;
 
-       if ((wl = cmdq->state.wl) == NULL)
+       if ((wl = cmdq->current_state.wl) == NULL)
                return (CMD_RETURN_ERROR);
-       wp = cmdq->state.wp;
-       s = cmdq->state.s;
+       wp = cmdq->current_state.wp;
+       s = cmdq->current_state.s;
 
        if (window_count_panes(wl->window) == 1) {
                cmdq_error(cmdq, "can't break with only one pane");
diff --git a/cmd-capture-pane.c b/cmd-capture-pane.c
index 74a2dc1..cc9c1ed 100644
--- a/cmd-capture-pane.c
+++ b/cmd-capture-pane.c
@@ -179,7 +179,7 @@ cmd_capture_pane_exec(struct cmd *self, struct cmd_q *cmdq)
        const char              *bufname;
        size_t                   len;
 
-       if ((wp = cmdq->state.wp) == NULL)
+       if ((wp = cmdq->current_state.wp) == NULL)
                return (CMD_RETURN_ERROR);
 
        len = 0;
diff --git a/cmd-choose-buffer.c b/cmd-choose-buffer.c
index 674ad82..a0f8310 100644
--- a/cmd-choose-buffer.c
+++ b/cmd-choose-buffer.c
@@ -54,7 +54,7 @@ cmd_choose_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
        u_int                            idx;
        int                              utf8flag;
 
-       if ((c = cmdq->state.c) == NULL) {
+       if ((c = cmdq->current_state.c) == NULL) {
                cmdq_error(cmdq, "no client available");
                return (CMD_RETURN_ERROR);
        }
@@ -62,7 +62,7 @@ cmd_choose_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
        if ((template = args_get(args, 'F')) == NULL)
                template = CHOOSE_BUFFER_TEMPLATE;
 
-       if ((wl = cmdq->state.wl) == NULL)
+       if ((wl = cmdq->current_state.wl) == NULL)
                return (CMD_RETURN_ERROR);
        utf8flag = options_get_number(&wl->window->options, "utf8");
 
diff --git a/cmd-choose-client.c b/cmd-choose-client.c
index f3237b2..f338d04 100644
--- a/cmd-choose-client.c
+++ b/cmd-choose-client.c
@@ -63,12 +63,12 @@ cmd_choose_client_exec(struct cmd *self, struct cmd_q *cmdq)
        char                            *action;
        u_int                            i, idx, cur;
 
-       if ((c = cmdq->state.c) == NULL) {
+       if ((c = cmdq->current_state.c) == NULL) {
                cmdq_error(cmdq, "no client available");
                return (CMD_RETURN_ERROR);
        }
 
-       if ((wl = cmdq->state.wl) == NULL)
+       if ((wl = cmdq->current_state.wl) == NULL)
                return (CMD_RETURN_ERROR);
 
        if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0)
diff --git a/cmd-choose-tree.c b/cmd-choose-tree.c
index 4be9f6c..56bfacc 100644
--- a/cmd-choose-tree.c
+++ b/cmd-choose-tree.c
@@ -90,15 +90,15 @@ cmd_choose_tree_exec(struct cmd *self, struct cmd_q *cmdq)
        ses_template = win_template = NULL;
        ses_action = win_action = NULL;
 
-       if ((c = cmdq->state.c) == NULL) {
+       if ((c = cmdq->current_state.c) == NULL) {
                cmdq_error(cmdq, "no client available");
                return (CMD_RETURN_ERROR);
        }
 
-       if ((s = cmdq->state.c->session) == NULL)
+       if ((s = cmdq->current_state.c->session) == NULL)
                return (CMD_RETURN_ERROR);
 
-       if ((wl = cmdq->state.wl) == NULL)
+       if ((wl = cmdq->current_state.wl) == NULL)
                return (CMD_RETURN_ERROR);
 
        if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0)
diff --git a/cmd-clear-history.c b/cmd-clear-history.c
index e345238..d22affd 100644
--- a/cmd-clear-history.c
+++ b/cmd-clear-history.c
@@ -42,7 +42,7 @@ cmd_clear_history_exec(unused struct cmd *self, struct cmd_q 
*cmdq)
        struct window_pane      *wp;
        struct grid             *gd;
 
-       if ((wp = cmdq->state.wp) == NULL)
+       if ((wp = cmdq->current_state.wp) == NULL)
                return (CMD_RETURN_ERROR);
        gd = wp->base.grid;
 
diff --git a/cmd-clock-mode.c b/cmd-clock-mode.c
index 32e8d47..82fb23b 100644
--- a/cmd-clock-mode.c
+++ b/cmd-clock-mode.c
@@ -40,7 +40,7 @@ cmd_clock_mode_exec(unused struct cmd *self, struct cmd_q 
*cmdq)
 {
        struct window_pane      *wp;
 
-       if ((wp = cmdq->state.wp) == NULL)
+       if ((wp = cmdq->current_state.wp) == NULL)
                return (CMD_RETURN_ERROR);
 
        window_pane_set_mode(wp, &window_clock_mode);
diff --git a/cmd-command-prompt.c b/cmd-command-prompt.c
index 7f66fc4..118d778 100644
--- a/cmd-command-prompt.c
+++ b/cmd-command-prompt.c
@@ -63,7 +63,7 @@ cmd_command_prompt_exec(struct cmd *self, struct cmd_q *cmdq)
        char                            *prompt, *ptr, *input = NULL;
        size_t                           n;
 
-       if ((c = cmdq->state.c) == NULL)
+       if ((c = cmdq->current_state.c) == NULL)
                return (CMD_RETURN_ERROR);
 
        if (c->prompt_string != NULL)
diff --git a/cmd-confirm-before.c b/cmd-confirm-before.c
index d5ecd8b..3584e70 100644
--- a/cmd-confirm-before.c
+++ b/cmd-confirm-before.c
@@ -56,7 +56,7 @@ cmd_confirm_before_exec(struct cmd *self, struct cmd_q *cmdq)
        char                            *cmd, *copy, *new_prompt, *ptr;
        const char                      *prompt;
 
-       if ((c = cmdq->state.c) == NULL)
+       if ((c = cmdq->current_state.c) == NULL)
                return (CMD_RETURN_ERROR);
 
        if ((prompt = args_get(args, 'p')) != NULL)
diff --git a/cmd-copy-mode.c b/cmd-copy-mode.c
index c06967d..2c4c4bd 100644
--- a/cmd-copy-mode.c
+++ b/cmd-copy-mode.c
@@ -40,7 +40,7 @@ cmd_copy_mode_exec(struct cmd *self, struct cmd_q *cmdq)
 {
        struct window_pane      *wp;
 
-       if ((wp = cmdq->state.wp) == NULL)
+       if ((wp = cmdq->current_state.wp) == NULL)
                return (CMD_RETURN_ERROR);
 
        if (wp->mode != &window_copy_mode) {
diff --git a/cmd-detach-client.c b/cmd-detach-client.c
index cd11542..8428182 100644
--- a/cmd-detach-client.c
+++ b/cmd-detach-client.c
@@ -53,9 +53,9 @@ cmd_detach_client_prepare(struct cmd *self, struct cmd_q 
*cmdq)
        struct args     *args = self->args;
 
        if (args_has(args, 's'))
-               cmdq->state.s = cmd_find_session(cmdq, args_get(args, 's'), 0);
+               cmdq->current_state.s = cmd_find_session(cmdq, args_get(args, 
's'), 0);
        else
-               cmdq->state.c = cmd_find_client(cmdq, args_get(args, 't'), 0);
+               cmdq->current_state.c = cmd_find_client(cmdq, args_get(args, 
't'), 0);
 }
 
 enum cmd_retval
@@ -82,7 +82,7 @@ cmd_detach_client_exec(struct cmd *self, struct cmd_q *cmdq)
                msgtype = MSG_DETACH;
 
        if (args_has(args, 's')) {
-               if ((s = cmdq->state.s) == NULL)
+               if ((s = cmdq->current_state.s) == NULL)
                        return (CMD_RETURN_ERROR);
 
                for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
@@ -93,7 +93,7 @@ cmd_detach_client_exec(struct cmd *self, struct cmd_q *cmdq)
                            strlen(c->session->name) + 1);
                }
        } else {
-               if ((c = cmdq->state.c) == NULL)
+               if ((c = cmdq->current_state.c) == NULL)
                        return (CMD_RETURN_ERROR);
 
                if (args_has(args, 'a')) {
diff --git a/cmd-display-message.c b/cmd-display-message.c
index 226d159..3c7db07 100644
--- a/cmd-display-message.c
+++ b/cmd-display-message.c
@@ -51,17 +51,17 @@ cmd_display_message_prepare(struct cmd *self, struct cmd_q 
*cmdq)
        struct args     *args = self->args;
 
        if (args_has(args, 't')) {
-               cmdq->state.wl = cmd_find_pane(cmdq, args_get(args, 't'),
-                   &cmdq->state.s, &cmdq->state.wp);
+               cmdq->current_state.wl = cmd_find_pane(cmdq, args_get(args, 
't'),
+                   &cmdq->current_state.s, &cmdq->current_state.wp);
        } else {
-               cmdq->state.wl = cmd_find_pane(cmdq, NULL, &cmdq->state.s,
-                   &cmdq->state.wp);
+               cmdq->current_state.wl = cmd_find_pane(cmdq, NULL, 
&cmdq->current_state.s,
+                   &cmdq->current_state.wp);
        }
 
        if (args_has(args, 'c'))
-               cmdq->state.c = cmd_find_client(cmdq, args_get(args, 'c'), 0);
+               cmdq->current_state.c = cmd_find_client(cmdq, args_get(args, 
'c'), 0);
        else
-               cmdq->state.c = cmd_current_client(cmdq);
+               cmdq->current_state.c = cmd_current_client(cmdq);
 }
 
 enum cmd_retval
@@ -79,18 +79,18 @@ cmd_display_message_exec(struct cmd *self, struct cmd_q 
*cmdq)
        time_t                   t;
        size_t                   len;
 
-       if ((wl = cmdq->state.wl) == NULL)
+       if ((wl = cmdq->current_state.wl) == NULL)
                return (CMD_RETURN_ERROR);
 
-       wp = cmdq->state.wp;
-       s = cmdq->state.s;
+       wp = cmdq->current_state.wp;
+       s = cmdq->current_state.s;
 
        if (args_has(args, 'F') && args->argc != 0) {
                cmdq_error(cmdq, "only one of -F or argument must be given");
                return (CMD_RETURN_ERROR);
        }
 
-       c = cmdq->state.c;
+       c = cmdq->current_state.c;
        if (args_has(args, 'c')) {
                if (c == NULL)
                        return (CMD_RETURN_ERROR);
diff --git a/cmd-display-panes.c b/cmd-display-panes.c
index 8b9cf58..4502339 100644
--- a/cmd-display-panes.c
+++ b/cmd-display-panes.c
@@ -40,7 +40,7 @@ cmd_display_panes_exec(unused struct cmd *self, struct cmd_q 
*cmdq)
 {
        struct client   *c;
 
-       if ((c = cmdq->state.c) == NULL)
+       if ((c = cmdq->current_state.c) == NULL)
                return (CMD_RETURN_ERROR);
 
        server_set_identify(c);
diff --git a/cmd-find-window.c b/cmd-find-window.c
index 7273633..9da6f46 100644
--- a/cmd-find-window.c
+++ b/cmd-find-window.c
@@ -144,13 +144,13 @@ cmd_find_window_exec(struct cmd *self, struct cmd_q *cmdq)
        const char                      *template;
        u_int                            i, match_flags;
 
-       if ((c = cmdq->state.c) == NULL) {
+       if ((c = cmdq->current_state.c) == NULL) {
                cmdq_error(cmdq, "no client available");
                return (CMD_RETURN_ERROR);
        }
        s = c->session;
 
-       if ((wl = cmdq->state.wl) == NULL)
+       if ((wl = cmdq->current_state.wl) == NULL)
                return (CMD_RETURN_ERROR);
 
        if ((template = args_get(args, 'F')) == NULL)
diff --git a/cmd-has-session.c b/cmd-has-session.c
index 78a62f7..56fd17f 100644
--- a/cmd-has-session.c
+++ b/cmd-has-session.c
@@ -38,7 +38,7 @@ const struct cmd_entry cmd_has_session_entry = {
 enum cmd_retval
 cmd_has_session_exec(unused struct cmd *self, struct cmd_q *cmdq)
 {
-       if (cmdq->state.s == NULL)
+       if (cmdq->current_state.s == NULL)
                return (CMD_RETURN_ERROR);
 
        return (CMD_RETURN_NORMAL);
diff --git a/cmd-if-shell.c b/cmd-if-shell.c
index 29783a8..980536a 100644
--- a/cmd-if-shell.c
+++ b/cmd-if-shell.c
@@ -59,10 +59,10 @@ cmd_if_shell_prepare(struct cmd *self, struct cmd_q *cmdq)
        struct args     *args = self->args;
 
        if (args_has(args, 't')) {
-               cmdq->state.wl = cmd_find_pane(cmdq, args_get(args, 't'),
-                   &cmdq->state.s, &cmdq->state.wp);
+               cmdq->current_state.wl = cmd_find_pane(cmdq, args_get(args, 
't'),
+                   &cmdq->current_state.s, &cmdq->current_state.wp);
        } else
-               cmdq->state.c = cmd_find_client(cmdq, NULL, 1);
+               cmdq->current_state.c = cmd_find_client(cmdq, NULL, 1);
 }
 
 enum cmd_retval
@@ -78,10 +78,10 @@ cmd_if_shell_exec(struct cmd *self, struct cmd_q *cmdq)
        struct window_pane              *wp = NULL;
        struct format_tree              *ft;
 
-       wl = cmdq->state.wl;
-       s = cmdq->state.s;
-       wp = cmdq->state.wp;
-       c = cmdq->state.c;
+       wl = cmdq->current_state.wl;
+       s = cmdq->current_state.s;
+       wp = cmdq->current_state.wp;
+       c = cmdq->current_state.c;
 
        if (!args_has(args, 't') && c != NULL && c->session != NULL) {
                s = c->session;
diff --git a/cmd-join-pane.c b/cmd-join-pane.c
index f6dba10..b94ed53 100644
--- a/cmd-join-pane.c
+++ b/cmd-join-pane.c
@@ -57,10 +57,10 @@ cmd_join_pane_prepare(struct cmd *self, struct cmd_q *cmdq)
 {
        struct args     *args = self->args;
 
-       cmdq->state.wl = cmd_find_pane(cmdq, args_get(args, 't'),
-           &cmdq->state.s, &cmdq->state.wp);
-       cmdq->state.wl2 = cmd_find_pane(cmdq, args_get(args, 's'), NULL,
-           &cmdq->state.wp2);
+       cmdq->current_state.wl = cmd_find_pane(cmdq, args_get(args, 't'),
+           &cmdq->current_state.s, &cmdq->current_state.wp);
+       cmdq->current_state.wl2 = cmd_find_pane(cmdq, args_get(args, 's'), NULL,
+           &cmdq->current_state.wp2);
 }
 enum cmd_retval
 cmd_join_pane_exec(struct cmd *self, struct cmd_q *cmdq)
@@ -81,17 +81,17 @@ join_pane(struct cmd *self, struct cmd_q *cmdq, int 
not_same_window)
        enum layout_type         type;
        struct layout_cell      *lc;
 
-       if ((dst_wl = cmdq->state.wl) == NULL)
+       if ((dst_wl = cmdq->current_state.wl) == NULL)
                return (CMD_RETURN_ERROR);
-       dst_s =  cmdq->state.s;
-       dst_wp = cmdq->state.wp;
+       dst_s =  cmdq->current_state.s;
+       dst_wp = cmdq->current_state.wp;
        dst_w = dst_wl->window;
        dst_idx = dst_wl->idx;
        server_unzoom_window(dst_w);
 
-       if ((src_wl = cmdq->state.wl2) == NULL)
+       if ((src_wl = cmdq->current_state.wl2) == NULL)
                return (CMD_RETURN_ERROR);
-       src_wp = cmdq->state.wp2;
+       src_wp = cmdq->current_state.wp2;
        src_w = src_wl->window;
        server_unzoom_window(src_w);
 
diff --git a/cmd-kill-pane.c b/cmd-kill-pane.c
index 26f0e0c..c78ea5f 100644
--- a/cmd-kill-pane.c
+++ b/cmd-kill-pane.c
@@ -44,9 +44,9 @@ cmd_kill_pane_exec(struct cmd *self, struct cmd_q *cmdq)
        struct winlink          *wl;
        struct window_pane      *loopwp, *tmpwp, *wp;
 
-       if ((wl = cmdq->state.wl) == NULL)
+       if ((wl = cmdq->current_state.wl) == NULL)
                return (CMD_RETURN_ERROR);
-       wp = cmdq->state.wp;
+       wp = cmdq->current_state.wp;
        server_unzoom_window(wl->window);
 
        if (window_count_panes(wl->window) == 1) {
diff --git a/cmd-kill-session.c b/cmd-kill-session.c
index 3515a67..0f5c60c 100644
--- a/cmd-kill-session.c
+++ b/cmd-kill-session.c
@@ -45,7 +45,7 @@ cmd_kill_session_exec(struct cmd *self, struct cmd_q *cmdq)
        struct args     *args = self->args;
        struct session  *s, *s2, *s3;
 
-       if ((s = cmdq->state.s) == NULL)
+       if ((s = cmdq->current_state.s) == NULL)
                return (CMD_RETURN_ERROR);
 
        if (args_has(args, 'a')) {
diff --git a/cmd-kill-window.c b/cmd-kill-window.c
index 9c30e82..0c484fc 100644
--- a/cmd-kill-window.c
+++ b/cmd-kill-window.c
@@ -54,7 +54,7 @@ cmd_kill_window_exec(struct cmd *self, struct cmd_q *cmdq)
        struct session_group    *sg;
        u_int                    references;
 
-       if ((wl = cmdq->state.wl) == NULL)
+       if ((wl = cmdq->current_state.wl) == NULL)
                return (CMD_RETURN_ERROR);
        w = wl->window;
 
@@ -67,7 +67,7 @@ cmd_kill_window_exec(struct cmd *self, struct cmd_q *cmdq)
                if (!args_has(self->args, 'k') && w->references == references) {
                        cmdq_error(cmdq, "window only linked to one session");
                        return (CMD_RETURN_ERROR);
-       s = cmdq->state.s;
+       s = cmdq->current_state.s;
 
        } else {
                if (args_has(args, 'a')) {
diff --git a/cmd-list-clients.c b/cmd-list-clients.c
index 9b51e05..f295d73 100644
--- a/cmd-list-clients.c
+++ b/cmd-list-clients.c
@@ -55,7 +55,7 @@ cmd_list_clients_exec(struct cmd *self, struct cmd_q *cmdq)
        u_int                    i;
        char                    *line;
 
-       s = cmdq->state.s;
+       s = cmdq->current_state.s;
        if (args_has(args, 't') && s == NULL)
                return (CMD_RETURN_ERROR);
 
diff --git a/cmd-list-panes.c b/cmd-list-panes.c
index caeb48e..3daa55b 100644
--- a/cmd-list-panes.c
+++ b/cmd-list-panes.c
@@ -51,10 +51,10 @@ cmd_list_panes_prepare(struct cmd *self, struct cmd_q *cmdq)
        struct args     *args = self->args;
 
        if (args_has(args, 's'))
-               cmdq->state.s = cmd_find_session(cmdq, args_get(args, 't'), 0);
+               cmdq->current_state.s = cmd_find_session(cmdq, args_get(args, 
't'), 0);
        else if (args_has(args, 't')) {
-               cmdq->state.wl = cmd_find_window(cmdq, args_get(args, 't'),
-                   &cmdq->state.s);
+               cmdq->current_state.wl = cmd_find_window(cmdq, args_get(args, 
't'),
+                   &cmdq->current_state.s);
        }
 }
 
@@ -65,7 +65,7 @@ cmd_list_panes_exec(struct cmd *self, struct cmd_q *cmdq)
        struct session  *s;
        struct winlink  *wl;
 
-       s = cmdq->state.s;
+       s = cmdq->current_state.s;
 
        if (args_has(args, 'a'))
                cmd_list_panes_server(self, cmdq);
@@ -74,7 +74,7 @@ cmd_list_panes_exec(struct cmd *self, struct cmd_q *cmdq)
                        return (CMD_RETURN_ERROR);
                cmd_list_panes_session(self, s, cmdq, 1);
        } else {
-               if ((wl = cmdq->state.wl) == NULL)
+               if ((wl = cmdq->current_state.wl) == NULL)
                        return (CMD_RETURN_ERROR);
                cmd_list_panes_window(self, s, wl, cmdq, 0);
        }
diff --git a/cmd-list-windows.c b/cmd-list-windows.c
index 3cd980c..27ea141 100644
--- a/cmd-list-windows.c
+++ b/cmd-list-windows.c
@@ -61,7 +61,7 @@ cmd_list_windows_prepare(struct cmd *self, struct cmd_q *cmdq)
        struct args     *args = self->args;
 
        if (!args_has(args, 'a'))
-               cmdq->state.s = cmd_find_session(cmdq, args_get(args, 't'), 0);
+               cmdq->current_state.s = cmd_find_session(cmdq, args_get(args, 
't'), 0);
 }
 
 enum cmd_retval
@@ -73,7 +73,7 @@ cmd_list_windows_exec(struct cmd *self, struct cmd_q *cmdq)
        if (args_has(args, 'a'))
                cmd_list_windows_server(self, cmdq);
        else {
-               if ((s = cmdq->state.s) == NULL)
+               if ((s = cmdq->current_state.s) == NULL)
                        return (CMD_RETURN_ERROR);
                cmd_list_windows_session(self, s, cmdq, 0);
        }
diff --git a/cmd-lock-server.c b/cmd-lock-server.c
index 4c4ca6e..a7f4765 100644
--- a/cmd-lock-server.c
+++ b/cmd-lock-server.c
@@ -60,9 +60,9 @@ cmd_lock_server_prepare(struct cmd *self, struct cmd_q *cmdq)
        struct args     *args = self->args;
 
        if (self->entry == &cmd_lock_session_entry)
-               cmdq->state.s = cmd_find_session(cmdq, args_get(args, 't'), 0);
+               cmdq->current_state.s = cmd_find_session(cmdq, args_get(args, 
't'), 0);
        else if (self->entry == &cmd_lock_client_entry)
-               cmdq->state.c = cmd_find_client(cmdq, args_get(args, 't'), 0);
+               cmdq->current_state.c = cmd_find_client(cmdq, args_get(args, 
't'), 0);
 }
 
 enum cmd_retval
@@ -74,11 +74,11 @@ cmd_lock_server_exec(struct cmd *self, unused struct cmd_q 
*cmdq)
        if (self->entry == &cmd_lock_server_entry)
                server_lock();
        else if (self->entry == &cmd_lock_session_entry) {
-               if ((s = cmdq->state.s) == NULL)
+               if ((s = cmdq->current_state.s) == NULL)
                        return (CMD_RETURN_ERROR);
                server_lock_session(s);
        } else {
-               if ((c = cmdq->state.c) == NULL)
+               if ((c = cmdq->current_state.c) == NULL)
                        return (CMD_RETURN_ERROR);
                server_lock_client(c);
        }
diff --git a/cmd-move-window.c b/cmd-move-window.c
index c864f14..a246601 100644
--- a/cmd-move-window.c
+++ b/cmd-move-window.c
@@ -53,12 +53,12 @@ cmd_move_window_prepare(struct cmd *self, struct cmd_q 
*cmdq)
        struct args     *args = self->args;
 
        if (args_has(args, 'r'))
-               cmdq->state.s = cmd_find_session(cmdq, args_get(args, 't'), 0);
+               cmdq->current_state.s = cmd_find_session(cmdq, args_get(args, 
't'), 0);
        else {
-               cmdq->state.wl = cmd_find_window(cmdq, args_get(args, 's'),
-                   &cmdq->state.s);
-               cmdq->state.idx = cmd_find_index(cmdq, args_get(args, 't'),
-                   &cmdq->state.s2);
+               cmdq->current_state.wl = cmd_find_window(cmdq, args_get(args, 
's'),
+                   &cmdq->current_state.s);
+               cmdq->current_state.idx = cmd_find_index(cmdq, args_get(args, 
't'),
+                   &cmdq->current_state.s2);
        }
 }
 
@@ -72,7 +72,7 @@ cmd_move_window_exec(struct cmd *self, struct cmd_q *cmdq)
        int              idx, kflag, dflag;
 
        if (args_has(args, 'r')) {
-               if ((s = cmdq->state.s) == NULL)
+               if ((s = cmdq->current_state.s) == NULL)
                        return (CMD_RETURN_ERROR);
 
                session_renumber_windows(s);
@@ -80,12 +80,12 @@ cmd_move_window_exec(struct cmd *self, struct cmd_q *cmdq)
 
                return (CMD_RETURN_NORMAL);
        }
-       src = cmdq->state.s;
-       dst = cmdq->state.s2;
+       src = cmdq->current_state.s;
+       dst = cmdq->current_state.s2;
 
-       if ((wl = cmdq->state.wl) == NULL)
+       if ((wl = cmdq->current_state.wl) == NULL)
                return (CMD_RETURN_ERROR);
-       if ((idx = cmdq->state.idx) == -2)
+       if ((idx = cmdq->current_state.idx) == -2)
                return (CMD_RETURN_ERROR);
 
        kflag = args_has(self->args, 'k');
diff --git a/cmd-new-window.c b/cmd-new-window.c
index 4e222ba..1276a9e 100644
--- a/cmd-new-window.c
+++ b/cmd-new-window.c
@@ -51,18 +51,18 @@ cmd_new_window_prepare(struct cmd *self, struct cmd_q *cmdq)
        struct args     *args = self->args;
 
        if (args_has(args, 'a')) {
-               cmdq->state.wl = cmd_find_window(cmdq, args_get(args, 't'),
-                   &cmdq->state.s);
+               cmdq->current_state.wl = cmd_find_window(cmdq, args_get(args, 
't'),
+                   &cmdq->current_state.s);
        } else
-               cmd_find_index(cmdq, args_get(args, 't'), &cmdq->state.s);
+               cmd_find_index(cmdq, args_get(args, 't'), 
&cmdq->current_state.s);
 }
 
 enum cmd_retval
 cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
 {
        struct args             *args = self->args;
-       struct session          *s = cmdq->state.s;
-       struct winlink          *wl = cmdq->state.wl;
+       struct session          *s = cmdq->current_state.s;
+       struct winlink          *wl = cmdq->current_state.wl;
        struct client           *c;
        const char              *cmd, *path, *template;
        char                   **argv, *cause, *cp;
diff --git a/cmd-paste-buffer.c b/cmd-paste-buffer.c
index c3ad875..41568dd 100644
--- a/cmd-paste-buffer.c
+++ b/cmd-paste-buffer.c
@@ -49,14 +49,14 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
        struct paste_buffer     *pb;
        const char              *sepstr, *bufname;
 
-       if (cmdq->state.wl == NULL)
+       if (cmdq->current_state.wl == NULL)
                return (CMD_RETURN_ERROR);
 
        bufname = NULL;
        if (args_has(args, 'b'))
                bufname = args_get(args, 'b');
 
-       wp = cmdq->state.wp;
+       wp = cmdq->current_state.wp;
 
        if (!args_has(args, 'b'))
                buffer = -1;
diff --git a/cmd-pipe-pane.c b/cmd-pipe-pane.c
index facab6f..930408f 100644
--- a/cmd-pipe-pane.c
+++ b/cmd-pipe-pane.c
@@ -53,9 +53,9 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmd_q *cmdq)
        char                    *command;
        int                      old_fd, pipe_fd[2], null_fd;
 
-       if (cmdq->state.wl == NULL)
+       if (cmdq->current_state.wl == NULL)
                return (CMD_RETURN_ERROR);
-       wp = cmdq->state.wp;
+       wp = cmdq->current_state.wp;
        c = cmd_find_client(cmdq, NULL, 1);
 
        /* Destroy the old pipe. */
diff --git a/cmd-queue.c b/cmd-queue.c
index 993303f..1df40fc 100644
--- a/cmd-queue.c
+++ b/cmd-queue.c
@@ -33,16 +33,16 @@ void        cmdq_run_hook(struct hooks *, const char *, 
struct cmd *,
 void
 cmdq_set_state(struct cmd_q *cmdq)
 {
-       memset(&cmdq->state, 0, sizeof cmdq->state);
+       memset(&cmdq->current_state, 0, sizeof cmdq->current_state);
 
-       cmdq->state.c = cmdq->client;
+       cmdq->current_state.c = cmdq->client;
 
-       cmdq->state.s = cmdq->client != NULL ? cmdq->client->session : NULL;
-       cmdq->state.s2 = NULL;
+       cmdq->current_state.s = cmdq->client != NULL ? cmdq->client->session : 
NULL;
+       cmdq->current_state.s2 = NULL;
 
-       cmdq->state.w = NULL;
-       cmdq->state.wl = NULL;
-       cmdq->state.wp = NULL;
+       cmdq->current_state.w = NULL;
+       cmdq->current_state.wl = NULL;
+       cmdq->current_state.wp = NULL;
 }
 
 /* Create new command queue. */
@@ -232,8 +232,8 @@ cmdq_continue(struct cmd_q *cmdq)
                         * otherwise used the intended session's hooks when
                         * running the command.
                         */
-                       if (cmdq->state.s != NULL)
-                               hooks = &cmdq->state.s->hooks;
+                       if (cmdq->current_state.s != NULL)
+                               hooks = &cmdq->current_state.s->hooks;
                        else
                                hooks = &global_hooks;
 
diff --git a/cmd-refresh-client.c b/cmd-refresh-client.c
index 969605b..fd20911 100644
--- a/cmd-refresh-client.c
+++ b/cmd-refresh-client.c
@@ -43,7 +43,7 @@ cmd_refresh_client_exec(struct cmd *self, struct cmd_q *cmdq)
        const char      *size;
        u_int            w, h;
 
-       if ((c = cmdq->state.c) == NULL)
+       if ((c = cmdq->current_state.c) == NULL)
                return (CMD_RETURN_ERROR);
 
        if (args_has(args, 'C')) {
diff --git a/cmd-rename-session.c b/cmd-rename-session.c
index e44c45b..203334f 100644
--- a/cmd-rename-session.c
+++ b/cmd-rename-session.c
@@ -55,7 +55,7 @@ cmd_rename_session_exec(struct cmd *self, struct cmd_q *cmdq)
                return (CMD_RETURN_ERROR);
        }
 
-       if ((s = cmdq->state.s) == NULL)
+       if ((s = cmdq->current_state.s) == NULL)
                return (CMD_RETURN_ERROR);
 
        RB_REMOVE(sessions, &sessions, s);
diff --git a/cmd-rename-window.c b/cmd-rename-window.c
index aeee5b9..b5d7000 100644
--- a/cmd-rename-window.c
+++ b/cmd-rename-window.c
@@ -44,7 +44,7 @@ cmd_rename_window_exec(struct cmd *self, struct cmd_q *cmdq)
        struct args     *args = self->args;
        struct winlink  *wl;
 
-       if ((wl = cmdq->state.wl) == NULL)
+       if ((wl = cmdq->current_state.wl) == NULL)
                return (CMD_RETURN_ERROR);
 
        window_set_name(wl->window, args->argv[0]);
diff --git a/cmd-resize-pane.c b/cmd-resize-pane.c
index b55b2c3..bf1afab 100644
--- a/cmd-resize-pane.c
+++ b/cmd-resize-pane.c
@@ -49,10 +49,10 @@ cmd_resize_pane_exec(struct cmd *self, struct cmd_q *cmdq)
        u_int                    adjust;
        int                      x, y;
 
-       if ((wl = cmdq->state.wl) == NULL)
+       if ((wl = cmdq->current_state.wl) == NULL)
                return (CMD_RETURN_ERROR);
        w = wl->window;
-       wp = cmdq->state.wp;
+       wp = cmdq->current_state.wp;
 
        if (args_has(args, 'Z')) {
                if (w->flags & WINDOW_ZOOMED)
diff --git a/cmd-respawn-pane.c b/cmd-respawn-pane.c
index 2aaee6b..b5e20c4 100644
--- a/cmd-respawn-pane.c
+++ b/cmd-respawn-pane.c
@@ -53,11 +53,11 @@ cmd_respawn_pane_exec(struct cmd *self, struct cmd_q *cmdq)
        u_int                    idx;
        struct environ_entry    *envent;
 
-       if ((wl = cmdq->state.wl) == NULL)
+       if ((wl = cmdq->current_state.wl) == NULL)
                return (CMD_RETURN_ERROR);
        w = wl->window;
-       s = cmdq->state.s;
-       wp = cmdq->state.wp;
+       s = cmdq->current_state.s;
+       wp = cmdq->current_state.wp;
 
        if (!args_has(self->args, 'k') && wp->fd != -1) {
                if (window_pane_index(wp, &idx) != 0)
diff --git a/cmd-respawn-window.c b/cmd-respawn-window.c
index af21f2f..6815ca7 100644
--- a/cmd-respawn-window.c
+++ b/cmd-respawn-window.c
@@ -51,10 +51,10 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_q 
*cmdq)
        char                    *cause;
        struct environ_entry    *envent;
 
-       if ((wl = cmdq->state.wl) == NULL)
+       if ((wl = cmdq->current_state.wl) == NULL)
                return (CMD_RETURN_ERROR);
        w = wl->window;
-       s = cmdq->state.s;
+       s = cmdq->current_state.s;
 
        if (!args_has(self->args, 'k')) {
                TAILQ_FOREACH(wp, &w->panes, entry) {
diff --git a/cmd-rotate-window.c b/cmd-rotate-window.c
index 310268c..a4f49bc 100644
--- a/cmd-rotate-window.c
+++ b/cmd-rotate-window.c
@@ -44,7 +44,7 @@ cmd_rotate_window_exec(struct cmd *self, struct cmd_q *cmdq)
        struct layout_cell      *lc;
        u_int                    sx, sy, xoff, yoff;
 
-       if ((wl = cmdq->state.wl) == NULL)
+       if ((wl = cmdq->current_state.wl) == NULL)
                return (CMD_RETURN_ERROR);
        w = wl->window;
 
diff --git a/cmd-run-shell.c b/cmd-run-shell.c
index cae8068..1ca9da3 100644
--- a/cmd-run-shell.c
+++ b/cmd-run-shell.c
@@ -83,7 +83,7 @@ cmd_run_shell_exec(struct cmd *self, struct cmd_q *cmdq)
        struct format_tree              *ft;
 
        if (args_has(args, 't'))
-               wl = cmdq->state.wl;
+               wl = cmdq->current_state.wl;
        else {
                c = cmd_find_client(cmdq, NULL, 1);
                if (c != NULL && c->session != NULL) {
@@ -92,9 +92,9 @@ cmd_run_shell_exec(struct cmd *self, struct cmd_q *cmdq)
                        wp = wl->window->active;
                }
        }
-       s = cmdq->state.s;
-       wl = cmdq->state.wl;
-       wp = cmdq->state.wp;
+       s = cmdq->current_state.s;
+       wl = cmdq->current_state.wl;
+       wp = cmdq->current_state.wp;
 
        ft = format_create();
        if (s != NULL)
diff --git a/cmd-select-layout.c b/cmd-select-layout.c
index 4eb3719..cda2b9b 100644
--- a/cmd-select-layout.c
+++ b/cmd-select-layout.c
@@ -61,7 +61,7 @@ cmd_select_layout_exec(struct cmd *self, struct cmd_q *cmdq)
        const char      *layoutname;
        int              next, previous, layout;
 
-       if ((wl = cmdq->state.wl) == NULL)
+       if ((wl = cmdq->current_state.wl) == NULL)
                return (CMD_RETURN_ERROR);
        server_unzoom_window(wl->window);
 
diff --git a/cmd-select-pane.c b/cmd-select-pane.c
index e4bebc5..7f195d6 100644
--- a/cmd-select-pane.c
+++ b/cmd-select-pane.c
@@ -51,11 +51,11 @@ cmd_select_pane_prepare(struct cmd *self, struct cmd_q 
*cmdq)
        struct args     *args = self->args;
 
        if (self->entry == &cmd_last_pane_entry || args_has(args, 'l')) {
-               cmdq->state.wl = cmd_find_window(cmdq, args_get(args, 't'),
+               cmdq->current_state.wl = cmd_find_window(cmdq, args_get(args, 
't'),
                    NULL);
        } else {
-               cmdq->state.wl = cmd_find_pane(cmdq, args_get(args, 't'), NULL,
-                   &cmdq->state.wp);
+               cmdq->current_state.wl = cmd_find_pane(cmdq, args_get(args, 
't'), NULL,
+                   &cmdq->current_state.wp);
        }
 }
 enum cmd_retval
@@ -66,7 +66,7 @@ cmd_select_pane_exec(struct cmd *self, struct cmd_q *cmdq)
        struct window_pane      *wp;
 
        if (self->entry == &cmd_last_pane_entry || args_has(args, 'l')) {
-               if ((wl = cmdq->state.wl) == NULL)
+               if ((wl = cmdq->current_state.wl) == NULL)
                        return (CMD_RETURN_ERROR);
 
                if (wl->window->last == NULL) {
@@ -88,10 +88,10 @@ cmd_select_pane_exec(struct cmd *self, struct cmd_q *cmdq)
                return (CMD_RETURN_NORMAL);
        }
 
-       if ((wl = cmdq->state.wl) == NULL)
+       if ((wl = cmdq->current_state.wl) == NULL)
                return (CMD_RETURN_ERROR);
 
-       wp = cmdq->state.wp;
+       wp = cmdq->current_state.wp;
 
        server_unzoom_window(wp->window);
        if (!window_pane_visible(wp)) {
diff --git a/cmd-select-window.c b/cmd-select-window.c
index bbd7f71..611cf20 100644
--- a/cmd-select-window.c
+++ b/cmd-select-window.c
@@ -82,10 +82,10 @@ cmd_select_window_prepare(struct cmd *self, struct cmd_q 
*cmdq)
                last = 1;
 
        if (next || previous || last)
-               cmdq->state.s = cmd_find_session(cmdq, args_get(args, 't'), 0);
+               cmdq->current_state.s = cmd_find_session(cmdq, args_get(args, 
't'), 0);
        else {
-               cmdq->state.wl = cmd_find_window(cmdq, args_get(args, 't'),
-                   &cmdq->state.s);
+               cmdq->current_state.wl = cmd_find_window(cmdq, args_get(args, 
't'),
+                   &cmdq->current_state.s);
        }
 }
 enum cmd_retval
@@ -106,7 +106,7 @@ cmd_select_window_exec(struct cmd *self, struct cmd_q *cmdq)
                last = 1;
 
        if (next || previous || last) {
-               if ((s = cmdq->state.s) == NULL)
+               if ((s = cmdq->current_state.s) == NULL)
                        return (CMD_RETURN_ERROR);
 
                activity = args_has(self->args, 'a');
@@ -129,9 +129,9 @@ cmd_select_window_exec(struct cmd *self, struct cmd_q *cmdq)
 
                server_redraw_session(s);
        } else {
-               if ((wl = cmdq->state.wl) == NULL)
+               if ((wl = cmdq->current_state.wl) == NULL)
                        return (CMD_RETURN_ERROR);
-               s = cmdq->state.s;
+               s = cmdq->current_state.s;
 
                /*
                 * If -T and select-window is invoked on same window as
diff --git a/cmd-send-keys.c b/cmd-send-keys.c
index fb38d00..9daa079 100644
--- a/cmd-send-keys.c
+++ b/cmd-send-keys.c
@@ -58,10 +58,10 @@ cmd_send_keys_exec(struct cmd *self, struct cmd_q *cmdq)
        const u_char            *str;
        int                      i, key;
 
-       if (cmdq->state.wl == NULL)
+       if (cmdq->current_state.wl == NULL)
                return (CMD_RETURN_ERROR);
-       s = cmdq->state.s;
-       wp = cmdq->state.wp;
+       s = cmdq->current_state.s;
+       wp = cmdq->current_state.wp;
 
        if (self->entry == &cmd_send_prefix_entry) {
                if (args_has(args, '2'))
diff --git a/cmd-set-environment.c b/cmd-set-environment.c
index bf65a3f..4d43304 100644
--- a/cmd-set-environment.c
+++ b/cmd-set-environment.c
@@ -65,7 +65,7 @@ cmd_set_environment_exec(struct cmd *self, struct cmd_q *cmdq)
        if (args_has(self->args, 'g'))
                env = &global_environ;
        else {
-               if ((s = cmdq->state.s) == NULL)
+               if ((s = cmdq->current_state.s) == NULL)
                        return (CMD_RETURN_ERROR);
                env = &s->environ;
        }
diff --git a/cmd-set-hook.c b/cmd-set-hook.c
index bdf4540..6879d63 100644
--- a/cmd-set-hook.c
+++ b/cmd-set-hook.c
@@ -51,7 +51,7 @@ cmd_set_hook_exec(struct cmd *self, struct cmd_q *cmdq)
        char            *cause;
        const char      *name, *cmd;
 
-       if ((s = cmdq->state.s) == NULL)
+       if ((s = cmdq->current_state.s) == NULL)
                return (CMD_RETURN_ERROR);
        hooks = args_has(args, 'g') ? &global_hooks : &s->hooks;
 
diff --git a/cmd-show-environment.c b/cmd-show-environment.c
index e5bacd6..5ba7bbd 100644
--- a/cmd-show-environment.c
+++ b/cmd-show-environment.c
@@ -50,7 +50,7 @@ cmd_show_environment_exec(struct cmd *self, struct cmd_q 
*cmdq)
        if (args_has(self->args, 'g'))
                env = &global_environ;
        else {
-               if ((s = cmdq->state.s) == NULL)
+               if ((s = cmdq->current_state.s) == NULL)
                        return (CMD_RETURN_ERROR);
                env = &s->environ;
        }
diff --git a/cmd-show-hooks.c b/cmd-show-hooks.c
index ea14631..b3e87bd 100644
--- a/cmd-show-hooks.c
+++ b/cmd-show-hooks.c
@@ -50,7 +50,7 @@ cmd_show_hooks_exec(struct cmd *self, struct cmd_q *cmdq)
        char             tmp[BUFSIZ];
        size_t           used;
 
-       if ((s = cmdq->state.s) == NULL)
+       if ((s = cmdq->current_state.s) == NULL)
                return (CMD_RETURN_ERROR);
        hooks = args_has(args, 'g') ? &global_hooks : &s->hooks;
 
diff --git a/cmd-show-messages.c b/cmd-show-messages.c
index b2a669d..b755351 100644
--- a/cmd-show-messages.c
+++ b/cmd-show-messages.c
@@ -154,7 +154,7 @@ cmd_show_messages_exec(unused struct cmd *self, struct 
cmd_q *cmdq)
        if (done)
                return (CMD_RETURN_NORMAL);
 
-       if ((c = cmdq->state.c) == NULL)
+       if ((c = cmdq->current_state.c) == NULL)
                return (CMD_RETURN_ERROR);
 
        for (i = 0; i < ARRAY_LENGTH(&c->message_log); i++) {
diff --git a/cmd-show-options.c b/cmd-show-options.c
index dc596ca..55d58aa 100644
--- a/cmd-show-options.c
+++ b/cmd-show-options.c
@@ -60,10 +60,10 @@ cmd_show_options_prepare(struct cmd *self, struct cmd_q 
*cmdq)
 
        if (args_has(args, 'g') && args_has(args, 'w') &&
            self->entry == &cmd_show_window_options_entry) {
-               cmdq->state.wl = cmd_find_window(cmdq, args_get(args, 't'),
+               cmdq->current_state.wl = cmd_find_window(cmdq, args_get(args, 
't'),
                    NULL);
        } else
-               cmdq->state.s = cmd_find_session(cmdq, args_get(args, 't'), 0);
+               cmdq->current_state.s = cmd_find_session(cmdq, args_get(args, 
't'), 0);
 }
 
 enum cmd_retval
@@ -85,7 +85,7 @@ cmd_show_options_exec(struct cmd *self, struct cmd_q *cmdq)
                if (args_has(self->args, 'g'))
                        oo = &global_w_options;
                else {
-                       if ((wl = cmdq->state.wl) == NULL)
+                       if ((wl = cmdq->current_state.wl) == NULL)
                                return (CMD_RETURN_ERROR);
                        oo = &wl->window->options;
                }
@@ -94,7 +94,7 @@ cmd_show_options_exec(struct cmd *self, struct cmd_q *cmdq)
                if (args_has(self->args, 'g'))
                        oo = &global_s_options;
                else {
-                       if ((s = cmdq->state.s) == NULL)
+                       if ((s = cmdq->current_state.s) == NULL)
                                return (CMD_RETURN_ERROR);
                        oo = &s->options;
                }
diff --git a/cmd-split-window.c b/cmd-split-window.c
index d8ae7af..db12492 100644
--- a/cmd-split-window.c
+++ b/cmd-split-window.c
@@ -63,11 +63,11 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
        struct format_tree      *ft;
        struct environ_entry    *envent;
 
-       if ((wl = cmdq->state.wl) == NULL)
+       if ((wl = cmdq->current_state.wl) == NULL)
                return (CMD_RETURN_ERROR);
        w = wl->window;
-       s = cmdq->state.s;
-       wp = cmdq->state.wp;
+       s = cmdq->current_state.s;
+       wp = cmdq->current_state.wp;
        server_unzoom_window(w);
 
        environ_init(&env);
diff --git a/cmd-swap-pane.c b/cmd-swap-pane.c
index 75094cb..af16ce1 100644
--- a/cmd-swap-pane.c
+++ b/cmd-swap-pane.c
@@ -47,10 +47,10 @@ cmd_swap_pane_exec(struct cmd *self, struct cmd_q *cmdq)
        struct layout_cell      *src_lc, *dst_lc;
        u_int                    sx, sy, xoff, yoff;
 
-       if ((dst_wl = cmdq->state.wl) == NULL)
+       if ((dst_wl = cmdq->current_state.wl) == NULL)
                return (CMD_RETURN_ERROR);
        dst_w = dst_wl->window;
-       dst_wp = cmdq->state.wp;
+       dst_wp = cmdq->current_state.wp;
        server_unzoom_window(dst_w);
 
        if (!args_has(args, 's')) {
diff --git a/cmd-swap-window.c b/cmd-swap-window.c
index 745b2bf..d281a0d 100644
--- a/cmd-swap-window.c
+++ b/cmd-swap-window.c
@@ -43,10 +43,10 @@ cmd_swap_window_prepare(struct cmd *self, struct cmd_q 
*cmdq)
 {
        struct args     *args = self->args;
 
-       cmdq->state.wl = cmd_find_window(cmdq, args_get(args, 's'),
-           &cmdq->state.s);
-       cmdq->state.wl2 = cmd_find_window(cmdq, args_get(args, 't'),
-           &cmdq->state.s2);
+       cmdq->current_state.wl = cmd_find_window(cmdq, args_get(args, 's'),
+           &cmdq->current_state.s);
+       cmdq->current_state.wl2 = cmd_find_window(cmdq, args_get(args, 't'),
+           &cmdq->current_state.s2);
 }
 
 enum cmd_retval
@@ -57,12 +57,12 @@ cmd_swap_window_exec(struct cmd *self, struct cmd_q *cmdq)
        struct winlink          *wl_src, *wl_dst;
        struct window           *w;
 
-       if ((wl_src = cmdq->state.wl) == NULL)
+       if ((wl_src = cmdq->current_state.wl) == NULL)
                return (CMD_RETURN_ERROR);
-       src = cmdq->state.s;
-       if ((wl_dst = cmdq->state.wl2) == NULL)
+       src = cmdq->current_state.s;
+       if ((wl_dst = cmdq->current_state.wl2) == NULL)
                return (CMD_RETURN_ERROR);
-       dst = cmdq->state.s2;
+       dst = cmdq->current_state.s2;
 
        sg_src = session_group_find(src);
        sg_dst = session_group_find(dst);
diff --git a/cmd-switch-client.c b/cmd-switch-client.c
index c81b386..5a99fe5 100644
--- a/cmd-switch-client.c
+++ b/cmd-switch-client.c
@@ -44,8 +44,8 @@ cmd_switch_client_prepare(struct cmd *self, struct cmd_q 
*cmdq)
 {
        struct args     *args = self->args;
 
-       cmdq->state.c = cmd_find_client(cmdq, args_get(args, 'c'), 0);
-       cmdq->state.s = cmd_find_session(cmdq, args_get(args, 't'), 0);
+       cmdq->current_state.c = cmd_find_client(cmdq, args_get(args, 'c'), 0);
+       cmdq->current_state.s = cmd_find_session(cmdq, args_get(args, 't'), 0);
 }
 
 enum cmd_retval
@@ -59,7 +59,7 @@ cmd_switch_client_exec(struct cmd *self, struct cmd_q *cmdq)
        struct window_pane      *wp = NULL;
        const char              *tflag;
 
-       if ((c = cmdq->state.c) == NULL)
+       if ((c = cmdq->current_state.c) == NULL)
                return (CMD_RETURN_ERROR);
 
        if (args_has(args, 'r')) {
diff --git a/cmd.c b/cmd.c
index 54d0e8f..b8c6b42 100644
--- a/cmd.c
+++ b/cmd.c
@@ -321,9 +321,9 @@ cmd_prepare(struct cmd *cmd, struct cmd_q *cmdq)
 {
        struct args             *args = cmd->args;
        const char              *tflag = args_get(args, 't');
-       struct cmd_state        *state = &cmdq->state;
+       struct cmd_state        *state = &cmdq->current_state;
 
-       cmdq->state.c = cmd_current_client(cmdq);
+       cmdq->current_state.c = cmd_current_client(cmdq);
 
        if (cmd->entry->flags & CMD_PREPARESESSION)
                state->s = cmd_find_session(cmdq, tflag, 1);
diff --git a/tmux.h b/tmux.h
index 79216fc..5e31452 100644
--- a/tmux.h
+++ b/tmux.h
@@ -1422,7 +1422,8 @@ struct cmd_q {
        struct cmd_q_items       queue;
        struct cmd_q_item       *item;
        struct cmd              *cmd;
-       struct cmd_state         state;
+       struct cmd_state         default_state;
+       struct cmd_state         current_state;
 
        time_t                   time;
        u_int                    number;


commit 5c2831bcf2f265065d3e0bb18ad51f7e754e5060
Author: Nicholas Marriott <nicholas.marri...@gmail.com>
Commit: Thomas Adam <tho...@xteddy.org>

    Add prepare function to all commands.
---
 cmd-attach-session.c   |   17 ++++++++----
 cmd-bind-key.c         |    3 +-
 cmd-break-pane.c       |    9 ++++--
 cmd-capture-pane.c     |    7 +++--
 cmd-choose-buffer.c    |    9 ++++---
 cmd-choose-client.c    |   10 ++++---
 cmd-choose-tree.c      |   22 +++++++++++------
 cmd-clear-history.c    |   11 ++++----
 cmd-clock-mode.c       |   10 ++++----
 cmd-command-prompt.c   |    7 +++--
 cmd-confirm-before.c   |    7 +++--
 cmd-copy-mode.c        |    8 +++---
 cmd-delete-buffer.c    |    3 +-
 cmd-detach-client.c    |   28 +++++++++++++++------
 cmd-display-message.c  |   42 ++++++++++++++++++++++----------
 cmd-display-panes.c    |   10 ++++----
 cmd-find-window.c      |    9 ++++---
 cmd-has-session.c      |   11 ++++----
 cmd-if-shell.c         |   34 +++++++++++++++++++--------
 cmd-join-pane.c        |   31 ++++++++++++++++++------
 cmd-kill-pane.c        |   10 ++++---
 cmd-kill-server.c      |    6 +++-
 cmd-kill-session.c     |    8 ++++--
 cmd-kill-window.c      |   14 ++++++----
 cmd-list-buffers.c     |    3 +-
 cmd-list-clients.c     |   14 ++++------
 cmd-list-keys.c        |    4 ++-
 cmd-list-panes.c       |   25 +++++++++++++++----
 cmd-list-sessions.c    |    3 +-
 cmd-list-windows.c     |   18 +++++++++++---
 cmd-load-buffer.c      |    3 +-
 cmd-lock-server.c      |   28 +++++++++++++++------
 cmd-move-window.c      |   31 +++++++++++++++++++----
 cmd-new-session.c      |    8 ++++--
 cmd-new-window.c       |   25 +++++++++++++++----
 cmd-paste-buffer.c     |   21 +++++++++++++---
 cmd-pipe-pane.c        |    8 ++++--
 cmd-queue.c            |   61 ++++++++++++++++++++++++++++++++++++++++++++++++
 cmd-refresh-client.c   |    7 +++--
 cmd-rename-session.c   |    8 ++++--
 cmd-rename-window.c    |    9 ++++---
 cmd-resize-pane.c      |    8 ++++--
 cmd-respawn-pane.c     |    9 ++++--
 cmd-respawn-window.c   |    8 ++++--
 cmd-rotate-window.c    |    8 +++---
 cmd-run-shell.c        |   10 +++++--
 cmd-save-buffer.c      |    6 +++-
 cmd-select-layout.c    |   17 ++++++++-----
 cmd-select-pane.c      |   31 +++++++++++++++++++-----
 cmd-select-window.c    |   52 ++++++++++++++++++++++++++++++----------
 cmd-send-keys.c        |   15 ++++++++----
 cmd-set-buffer.c       |    3 +-
 cmd-set-environment.c  |    8 ++++--
 cmd-set-hook.c         |    5 ++-
 cmd-set-option.c       |    6 +++-
 cmd-show-environment.c |    8 ++++--
 cmd-show-hooks.c       |    7 +++--
 cmd-show-messages.c    |   12 +++++----
 cmd-show-options.c     |   28 ++++++++++++++++-----
 cmd-source-file.c      |    3 +-
 cmd-split-window.c     |    9 ++++--
 cmd-swap-pane.c        |    9 ++++---
 cmd-swap-window.c      |   27 +++++++++++++++------
 cmd-switch-client.c    |   21 +++++++++++++---
 cmd-unbind-key.c       |    3 +-
 cmd-wait-for.c         |    3 +-
 cmd.c                  |   24 +++++++++++++++++++
 tmux.h                 |   29 +++++++++++++++++++++-
 68 files changed, 691 insertions(+), 280 deletions(-)

diff --git a/cmd-attach-session.c b/cmd-attach-session.c
index 160f2a8..2f7e230 100644
--- a/cmd-attach-session.c
+++ b/cmd-attach-session.c
@@ -31,18 +31,19 @@
  */
 
 enum cmd_retval        cmd_attach_session_exec(struct cmd *, struct cmd_q *);
+void           cmd_attach_session_prepare(struct cmd *, struct cmd_q *);
 
 const struct cmd_entry cmd_attach_session_entry = {
        "attach-session", "attach",
        "c:drt:", 0, 0,
        "[-dr] [-c working-directory] " CMD_TARGET_SESSION_USAGE,
-       CMD_CANTNEST|CMD_STARTSERVER,
-       cmd_attach_session_exec
+       CMD_CANTNEST|CMD_STARTSERVER|CMD_PREPARESESSION,
+       cmd_attach_session_exec,
+       NULL
 };
 
 enum cmd_retval
-cmd_attach_session(struct cmd_q *cmdq, const char *tflag, int dflag, int rflag,
-    const char *cflag)
+cmd_attach_session(struct cmd_q *cmdq, int dflag, int rflag, const char *cflag)
 {
        struct session          *s;
        struct client           *c;
@@ -61,6 +62,7 @@ cmd_attach_session(struct cmd_q *cmdq, const char *tflag, int 
dflag, int rflag,
                return (CMD_RETURN_ERROR);
        }
 
+<<<<<<< HEAD
        if (tflag == NULL) {
                if ((s = cmd_find_session(cmdq, tflag, 1)) == NULL)
                        return (CMD_RETURN_ERROR);
@@ -76,6 +78,9 @@ cmd_attach_session(struct cmd_q *cmdq, const char *tflag, int 
dflag, int rflag,
                if (w != NULL)
                        wl = winlink_find_by_window(&s->windows, w);
        }
+       /* TA:  Likely broken! */
+       if ((s = cmdq->state.s) == NULL)
+               return (CMD_RETURN_ERROR);
 
        if (cmdq->client == NULL)
                return (CMD_RETURN_NORMAL);
@@ -189,6 +194,6 @@ cmd_attach_session_exec(struct cmd *self, struct cmd_q 
*cmdq)
 {
        struct args     *args = self->args;
 
-       return (cmd_attach_session(cmdq, args_get(args, 't'),
-           args_has(args, 'd'), args_has(args, 'r'), args_get(args, 'c')));
+       return (cmd_attach_session(cmdq, args_has(args, 'd'), args_has(args,
+           'r'), args_get(args, 'c')));
 }
diff --git a/cmd-bind-key.c b/cmd-bind-key.c
index 5d68d48..6eda84d 100644
--- a/cmd-bind-key.c
+++ b/cmd-bind-key.c
@@ -36,7 +36,8 @@ const struct cmd_entry cmd_bind_key_entry = {
        "cnrt:", 1, -1,
        "[-cnr] [-t mode-table] key command [arguments]",
        0,
-       cmd_bind_key_exec
+       cmd_bind_key_exec,
+       NULL
 };
 
 enum cmd_retval
diff --git a/cmd-break-pane.c b/cmd-break-pane.c
index 0025167..21d621e 100644
--- a/cmd-break-pane.c
+++ b/cmd-break-pane.c
@@ -34,8 +34,9 @@ const struct cmd_entry cmd_break_pane_entry = {
        "break-pane", "breakp",
        "dPF:t:", 0, 0,
        "[-dP] [-F format] " CMD_TARGET_PANE_USAGE,
-       0,
-       cmd_break_pane_exec
+       CMD_PREPAREWINDOW,
+       cmd_break_pane_exec,
+       NULL
 };
 
 enum cmd_retval
@@ -54,8 +55,10 @@ cmd_break_pane_exec(struct cmd *self, struct cmd_q *cmdq)
        const char              *template;
        char                    *cp;
 
-       if ((wl = cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp)) == NULL)
+       if ((wl = cmdq->state.wl) == NULL)
                return (CMD_RETURN_ERROR);
+       wp = cmdq->state.wp;
+       s = cmdq->state.s;
 
        if (window_count_panes(wl->window) == 1) {
                cmdq_error(cmdq, "can't break with only one pane");
diff --git a/cmd-capture-pane.c b/cmd-capture-pane.c
index ce60b4c..74a2dc1 100644
--- a/cmd-capture-pane.c
+++ b/cmd-capture-pane.c
@@ -40,8 +40,9 @@ const struct cmd_entry cmd_capture_pane_entry = {
        "ab:CeE:JpPqS:t:", 0, 0,
        "[-aCeJpPq] " CMD_BUFFER_USAGE " [-E end-line] [-S start-line]"
        CMD_TARGET_PANE_USAGE,
-       0,
-       cmd_capture_pane_exec
+       CMD_PREPAREPANE,
+       cmd_capture_pane_exec,
+       NULL
 };
 
 char *
@@ -178,7 +179,7 @@ cmd_capture_pane_exec(struct cmd *self, struct cmd_q *cmdq)
        const char              *bufname;
        size_t                   len;
 
-       if (cmd_find_pane(cmdq, args_get(args, 't'), NULL, &wp) == NULL)
+       if ((wp = cmdq->state.wp) == NULL)
                return (CMD_RETURN_ERROR);
 
        len = 0;
diff --git a/cmd-choose-buffer.c b/cmd-choose-buffer.c
index 19f5fba..674ad82 100644
--- a/cmd-choose-buffer.c
+++ b/cmd-choose-buffer.c
@@ -36,8 +36,9 @@ const struct cmd_entry cmd_choose_buffer_entry = {
        "choose-buffer", NULL,
        "F:t:", 0, 1,
        CMD_TARGET_WINDOW_USAGE " [-F format] [template]",
-       0,
-       cmd_choose_buffer_exec
+       CMD_PREPAREWINDOW,
+       cmd_choose_buffer_exec,
+       NULL
 };
 
 enum cmd_retval
@@ -53,7 +54,7 @@ cmd_choose_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
        u_int                            idx;
        int                              utf8flag;
 
-       if ((c = cmd_current_client(cmdq)) == NULL) {
+       if ((c = cmdq->state.c) == NULL) {
                cmdq_error(cmdq, "no client available");
                return (CMD_RETURN_ERROR);
        }
@@ -61,7 +62,7 @@ cmd_choose_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
        if ((template = args_get(args, 'F')) == NULL)
                template = CHOOSE_BUFFER_TEMPLATE;
 
-       if ((wl = cmd_find_window(cmdq, args_get(args, 't'), NULL)) == NULL)
+       if ((wl = cmdq->state.wl) == NULL)
                return (CMD_RETURN_ERROR);
        utf8flag = options_get_number(&wl->window->options, "utf8");
 
diff --git a/cmd-choose-client.c b/cmd-choose-client.c
index 5a1892f..f3237b2 100644
--- a/cmd-choose-client.c
+++ b/cmd-choose-client.c
@@ -34,6 +34,7 @@
        "(last used #{client_activity_string})"
 
 enum cmd_retval         cmd_choose_client_exec(struct cmd *, struct cmd_q *);
+void            cmd_choose_client_prepare(struct cmd *, struct cmd_q *);
 
 void   cmd_choose_client_callback(struct window_choose_data *);
 
@@ -41,8 +42,9 @@ const struct cmd_entry cmd_choose_client_entry = {
        "choose-client", NULL,
        "F:t:", 0, 1,
        CMD_TARGET_WINDOW_USAGE " [-F format] [template]",
-       0,
-       cmd_choose_client_exec
+       CMD_PREPAREWINDOW,
+       cmd_choose_client_exec,
+       NULL
 };
 
 struct cmd_choose_client_data {
@@ -61,12 +63,12 @@ cmd_choose_client_exec(struct cmd *self, struct cmd_q *cmdq)
        char                            *action;
        u_int                            i, idx, cur;
 
-       if ((c = cmd_current_client(cmdq)) == NULL) {
+       if ((c = cmdq->state.c) == NULL) {
                cmdq_error(cmdq, "no client available");
                return (CMD_RETURN_ERROR);
        }
 
-       if ((wl = cmd_find_window(cmdq, args_get(args, 't'), NULL)) == NULL)
+       if ((wl = cmdq->state.wl) == NULL)
                return (CMD_RETURN_ERROR);
 
        if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0)
diff --git a/cmd-choose-tree.c b/cmd-choose-tree.c
index 823d042..4be9f6c 100644
--- a/cmd-choose-tree.c
+++ b/cmd-choose-tree.c
@@ -48,24 +48,27 @@ const struct cmd_entry cmd_choose_tree_entry = {
        "S:W:swub:c:t:", 0, 1,
        "[-suw] [-b session-template] [-c window template] [-S format] " \
        "[-W format] " CMD_TARGET_WINDOW_USAGE,
-       0,
-       cmd_choose_tree_exec
+       CMD_PREPAREWINDOW,
+       cmd_choose_tree_exec,
+       NULL
 };
 
 const struct cmd_entry cmd_choose_session_entry = {
        "choose-session", NULL,
        "F:t:", 0, 1,
        CMD_TARGET_WINDOW_USAGE " [-F format] [template]",
-       0,
-       cmd_choose_tree_exec
+       CMD_PREPAREWINDOW,
+       cmd_choose_tree_exec,
+       NULL
 };
 
 const struct cmd_entry cmd_choose_window_entry = {
        "choose-window", NULL,
        "F:t:", 0, 1,
        CMD_TARGET_WINDOW_USAGE "[-F format] [template]",
-       0,
-       cmd_choose_tree_exec
+       CMD_PREPAREWINDOW,
+       cmd_choose_tree_exec,
+       NULL
 };
 
 enum cmd_retval
@@ -87,12 +90,15 @@ cmd_choose_tree_exec(struct cmd *self, struct cmd_q *cmdq)
        ses_template = win_template = NULL;
        ses_action = win_action = NULL;
 
-       if ((c = cmd_current_client(cmdq)) == NULL) {
+       if ((c = cmdq->state.c) == NULL) {
                cmdq_error(cmdq, "no client available");
                return (CMD_RETURN_ERROR);
        }
 
-       if ((wl = cmd_find_window(cmdq, args_get(args, 't'), &s)) == NULL)
+       if ((s = cmdq->state.c->session) == NULL)
+               return (CMD_RETURN_ERROR);
+
+       if ((wl = cmdq->state.wl) == NULL)
                return (CMD_RETURN_ERROR);
 
        if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0)
diff --git a/cmd-clear-history.c b/cmd-clear-history.c
index e134288..e345238 100644
--- a/cmd-clear-history.c
+++ b/cmd-clear-history.c
@@ -25,23 +25,24 @@
  */
 
 enum cmd_retval         cmd_clear_history_exec(struct cmd *, struct cmd_q *);
+void            cmd_clear_history_prepare(struct cmd *, struct cmd_q *);
 
 const struct cmd_entry cmd_clear_history_entry = {
        "clear-history", "clearhist",
        "t:", 0, 0,
        CMD_TARGET_PANE_USAGE,
-       0,
-       cmd_clear_history_exec
+       CMD_PREPAREPANE,
+       cmd_clear_history_exec,
+       NULL
 };
 
 enum cmd_retval
-cmd_clear_history_exec(struct cmd *self, struct cmd_q *cmdq)
+cmd_clear_history_exec(unused struct cmd *self, struct cmd_q *cmdq)
 {
-       struct args             *args = self->args;
        struct window_pane      *wp;
        struct grid             *gd;
 
-       if (cmd_find_pane(cmdq, args_get(args, 't'), NULL, &wp) == NULL)
+       if ((wp = cmdq->state.wp) == NULL)
                return (CMD_RETURN_ERROR);
        gd = wp->base.grid;
 
diff --git a/cmd-clock-mode.c b/cmd-clock-mode.c
index 8083581..32e8d47 100644
--- a/cmd-clock-mode.c
+++ b/cmd-clock-mode.c
@@ -30,17 +30,17 @@ const struct cmd_entry cmd_clock_mode_entry = {
        "clock-mode", NULL,
        "t:", 0, 0,
        CMD_TARGET_PANE_USAGE,
-       0,
-       cmd_clock_mode_exec
+       CMD_PREPAREPANE,
+       cmd_clock_mode_exec,
+       NULL
 };
 
 enum cmd_retval
-cmd_clock_mode_exec(struct cmd *self, struct cmd_q *cmdq)
+cmd_clock_mode_exec(unused struct cmd *self, struct cmd_q *cmdq)
 {
-       struct args             *args = self->args;
        struct window_pane      *wp;
 
-       if (cmd_find_pane(cmdq, args_get(args, 't'), NULL, &wp) == NULL)
+       if ((wp = cmdq->state.wp) == NULL)
                return (CMD_RETURN_ERROR);
 
        window_pane_set_mode(wp, &window_clock_mode);
diff --git a/cmd-command-prompt.c b/cmd-command-prompt.c
index 22b1d84..7f66fc4 100644
--- a/cmd-command-prompt.c
+++ b/cmd-command-prompt.c
@@ -38,8 +38,9 @@ const struct cmd_entry cmd_command_prompt_entry = {
        "command-prompt", NULL,
        "I:p:t:", 0, 1,
        "[-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE " [template]",
-       0,
-       cmd_command_prompt_exec
+       CMD_PREPARECLIENT,
+       cmd_command_prompt_exec,
+       NULL
 };
 
 struct cmd_command_prompt_cdata {
@@ -62,7 +63,7 @@ cmd_command_prompt_exec(struct cmd *self, struct cmd_q *cmdq)
        char                            *prompt, *ptr, *input = NULL;
        size_t                           n;
 
-       if ((c = cmd_find_client(cmdq, args_get(args, 't'), 0)) == NULL)
+       if ((c = cmdq->state.c) == NULL)
                return (CMD_RETURN_ERROR);
 
        if (c->prompt_string != NULL)
diff --git a/cmd-confirm-before.c b/cmd-confirm-before.c
index 0bf5844..d5ecd8b 100644
--- a/cmd-confirm-before.c
+++ b/cmd-confirm-before.c
@@ -37,8 +37,9 @@ const struct cmd_entry cmd_confirm_before_entry = {
        "confirm-before", "confirm",
        "p:t:", 1, 1,
        "[-p prompt] " CMD_TARGET_CLIENT_USAGE " command",
-       0,
-       cmd_confirm_before_exec
+       CMD_PREPARECLIENT,
+       cmd_confirm_before_exec,
+       NULL
 };
 
 struct cmd_confirm_before_data {
@@ -55,7 +56,7 @@ cmd_confirm_before_exec(struct cmd *self, struct cmd_q *cmdq)
        char                            *cmd, *copy, *new_prompt, *ptr;
        const char                      *prompt;
 
-       if ((c = cmd_find_client(cmdq, args_get(args, 't'), 0)) == NULL)
+       if ((c = cmdq->state.c) == NULL)
                return (CMD_RETURN_ERROR);
 
        if ((prompt = args_get(args, 'p')) != NULL)
diff --git a/cmd-copy-mode.c b/cmd-copy-mode.c
index 8933529..c06967d 100644
--- a/cmd-copy-mode.c
+++ b/cmd-copy-mode.c
@@ -30,17 +30,17 @@ const struct cmd_entry cmd_copy_mode_entry = {
        "copy-mode", NULL,
        "t:u", 0, 0,
        "[-u] " CMD_TARGET_PANE_USAGE,
-       0,
-       cmd_copy_mode_exec
+       CMD_PREPAREPANE,
+       cmd_copy_mode_exec,
+       NULL
 };
 
 enum cmd_retval
 cmd_copy_mode_exec(struct cmd *self, struct cmd_q *cmdq)
 {
-       struct args             *args = self->args;
        struct window_pane      *wp;
 
-       if (cmd_find_pane(cmdq, args_get(args, 't'), NULL, &wp) == NULL)
+       if ((wp = cmdq->state.wp) == NULL)
                return (CMD_RETURN_ERROR);
 
        if (wp->mode != &window_copy_mode) {
diff --git a/cmd-delete-buffer.c b/cmd-delete-buffer.c
index 42268b7..a7a6dc7 100644
--- a/cmd-delete-buffer.c
+++ b/cmd-delete-buffer.c
@@ -33,7 +33,8 @@ const struct cmd_entry cmd_delete_buffer_entry = {
        "b:", 0, 0,
        CMD_BUFFER_USAGE,
        0,
-       cmd_delete_buffer_exec
+       cmd_delete_buffer_exec,
+       NULL
 };
 
 enum cmd_retval
diff --git a/cmd-detach-client.c b/cmd-detach-client.c
index 600554a..cd11542 100644
--- a/cmd-detach-client.c
+++ b/cmd-detach-client.c
@@ -27,23 +27,37 @@
  */
 
 enum cmd_retval         cmd_detach_client_exec(struct cmd *, struct cmd_q *);
+void            cmd_detach_client_prepare(struct cmd *, struct cmd_q *);
 
 const struct cmd_entry cmd_detach_client_entry = {
        "detach-client", "detach",
        "as:t:P", 0, 0,
        "[-P] [-a] [-s target-session] " CMD_TARGET_CLIENT_USAGE,
-       CMD_READONLY,
-       cmd_detach_client_exec
+       CMD_READONLY|CMD_PREPARECLIENT|CMD_PREPARESESSION,
+       cmd_detach_client_exec,
+       cmd_detach_client_prepare
 };
 
 const struct cmd_entry cmd_suspend_client_entry = {
        "suspend-client", "suspendc",
        "t:", 0, 0,
        CMD_TARGET_CLIENT_USAGE,
-       0,
-       cmd_detach_client_exec
+       CMD_PREPARECLIENT,
+       cmd_detach_client_exec,
+       cmd_detach_client_prepare
 };
 
+void
+cmd_detach_client_prepare(struct cmd *self, struct cmd_q *cmdq)
+{
+       struct args     *args = self->args;
+
+       if (args_has(args, 's'))
+               cmdq->state.s = cmd_find_session(cmdq, args_get(args, 's'), 0);
+       else
+               cmdq->state.c = cmd_find_client(cmdq, args_get(args, 't'), 0);
+}
+
 enum cmd_retval
 cmd_detach_client_exec(struct cmd *self, struct cmd_q *cmdq)
 {
@@ -68,8 +82,7 @@ cmd_detach_client_exec(struct cmd *self, struct cmd_q *cmdq)
                msgtype = MSG_DETACH;
 
        if (args_has(args, 's')) {
-               s = cmd_find_session(cmdq, args_get(args, 's'), 0);
-               if (s == NULL)
+               if ((s = cmdq->state.s) == NULL)
                        return (CMD_RETURN_ERROR);
 
                for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
@@ -80,8 +93,7 @@ cmd_detach_client_exec(struct cmd *self, struct cmd_q *cmdq)
                            strlen(c->session->name) + 1);
                }
        } else {
-               c = cmd_find_client(cmdq, args_get(args, 't'), 0);
-               if (c == NULL)
+               if ((c = cmdq->state.c) == NULL)
                        return (CMD_RETURN_ERROR);
 
                if (args_has(args, 'a')) {
diff --git a/cmd-display-message.c b/cmd-display-message.c
index f3547b0..226d159 100644
--- a/cmd-display-message.c
+++ b/cmd-display-message.c
@@ -33,16 +33,37 @@
        "- (%H:%M %d-%b-%y)"
 
 enum cmd_retval         cmd_display_message_exec(struct cmd *, struct cmd_q *);
+void            cmd_display_message_prepare(struct cmd *, struct cmd_q *);
 
 const struct cmd_entry cmd_display_message_entry = {
        "display-message", "display",
        "c:pt:F:", 0, 1,
        "[-p] [-c target-client] [-F format] " CMD_TARGET_PANE_USAGE
        " [message]",
-       0,
-       cmd_display_message_exec
+       CMD_PREPAREWINDOW|CMD_PREPARECLIENT,
+       cmd_display_message_exec,
+       cmd_display_message_prepare
 };
 
+void
+cmd_display_message_prepare(struct cmd *self, struct cmd_q *cmdq)
+{
+       struct args     *args = self->args;
+
+       if (args_has(args, 't')) {
+               cmdq->state.wl = cmd_find_pane(cmdq, args_get(args, 't'),
+                   &cmdq->state.s, &cmdq->state.wp);
+       } else {
+               cmdq->state.wl = cmd_find_pane(cmdq, NULL, &cmdq->state.s,
+                   &cmdq->state.wp);
+       }
+
+       if (args_has(args, 'c'))
+               cmdq->state.c = cmd_find_client(cmdq, args_get(args, 'c'), 0);
+       else
+               cmdq->state.c = cmd_current_client(cmdq);
+}
+
 enum cmd_retval
 cmd_display_message_exec(struct cmd *self, struct cmd_q *cmdq)
 {
@@ -58,27 +79,22 @@ cmd_display_message_exec(struct cmd *self, struct cmd_q 
*cmdq)
        time_t                   t;
        size_t                   len;
 
-       if (args_has(args, 't')) {
-               wl = cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp);
-               if (wl == NULL)
-                       return (CMD_RETURN_ERROR);
-       } else {
-               wl = cmd_find_pane(cmdq, NULL, &s, &wp);
-               if (wl == NULL)
-                       return (CMD_RETURN_ERROR);
-       }
+       if ((wl = cmdq->state.wl) == NULL)
+               return (CMD_RETURN_ERROR);
+
+       wp = cmdq->state.wp;
+       s = cmdq->state.s;
 
        if (args_has(args, 'F') && args->argc != 0) {
                cmdq_error(cmdq, "only one of -F or argument must be given");
                return (CMD_RETURN_ERROR);
        }
 
+       c = cmdq->state.c;
        if (args_has(args, 'c')) {
-               c = cmd_find_client(cmdq, args_get(args, 'c'), 0);
                if (c == NULL)
                        return (CMD_RETURN_ERROR);
        } else {
-               c = cmd_current_client(cmdq);
                if (c == NULL && !args_has(self->args, 'p')) {
                        cmdq_error(cmdq, "no client available");
                        return (CMD_RETURN_ERROR);
diff --git a/cmd-display-panes.c b/cmd-display-panes.c
index 9ce8971..8b9cf58 100644
--- a/cmd-display-panes.c
+++ b/cmd-display-panes.c
@@ -30,17 +30,17 @@ const struct cmd_entry cmd_display_panes_entry = {
        "display-panes", "displayp",
        "t:", 0, 0,
        CMD_TARGET_CLIENT_USAGE,
-       0,
-       cmd_display_panes_exec
+       CMD_PREPARECLIENT,
+       cmd_display_panes_exec,
+       NULL
 };
 
 enum cmd_retval
-cmd_display_panes_exec(struct cmd *self, struct cmd_q *cmdq)
+cmd_display_panes_exec(unused struct cmd *self, struct cmd_q *cmdq)
 {
-       struct args     *args = self->args;
        struct client   *c;
 
-       if ((c = cmd_find_client(cmdq, args_get(args, 't'), 0)) == NULL)
+       if ((c = cmdq->state.c) == NULL)
                return (CMD_RETURN_ERROR);
 
        server_set_identify(c);
diff --git a/cmd-find-window.c b/cmd-find-window.c
index 88e4879..7273633 100644
--- a/cmd-find-window.c
+++ b/cmd-find-window.c
@@ -51,8 +51,9 @@ const struct cmd_entry cmd_find_window_entry = {
        "find-window", "findw",
        "F:CNt:T", 1, 4,
        "[-CNT] [-F format] " CMD_TARGET_WINDOW_USAGE " match-string",
-       0,
-       cmd_find_window_exec
+       CMD_PREPAREWINDOW,
+       cmd_find_window_exec,
+       NULL
 };
 
 struct cmd_find_window_data {
@@ -143,13 +144,13 @@ cmd_find_window_exec(struct cmd *self, struct cmd_q *cmdq)
        const char                      *template;
        u_int                            i, match_flags;
 
-       if ((c = cmd_current_client(cmdq)) == NULL) {
+       if ((c = cmdq->state.c) == NULL) {
                cmdq_error(cmdq, "no client available");
                return (CMD_RETURN_ERROR);
        }
        s = c->session;
 
-       if ((wl = cmd_find_window(cmdq, args_get(args, 't'), NULL)) == NULL)
+       if ((wl = cmdq->state.wl) == NULL)
                return (CMD_RETURN_ERROR);
 
        if ((template = args_get(args, 'F')) == NULL)
diff --git a/cmd-has-session.c b/cmd-has-session.c
index a873b20..78a62f7 100644
--- a/cmd-has-session.c
+++ b/cmd-has-session.c
@@ -30,16 +30,15 @@ const struct cmd_entry cmd_has_session_entry = {
        "has-session", "has",
        "t:", 0, 0,
        CMD_TARGET_SESSION_USAGE,
-       0,
-       cmd_has_session_exec
+       CMD_PREPAREWINDOW,
+       cmd_has_session_exec,
+       NULL
 };
 
 enum cmd_retval
-cmd_has_session_exec(struct cmd *self, struct cmd_q *cmdq)
+cmd_has_session_exec(unused struct cmd *self, struct cmd_q *cmdq)
 {
-       struct args     *args = self->args;
-
-       if (cmd_find_session(cmdq, args_get(args, 't'), 0) == NULL)
+       if (cmdq->state.s == NULL)
                return (CMD_RETURN_ERROR);
 
        return (CMD_RETURN_NORMAL);
diff --git a/cmd-if-shell.c b/cmd-if-shell.c
index 1543291..29783a8 100644
--- a/cmd-if-shell.c
+++ b/cmd-if-shell.c
@@ -30,6 +30,7 @@
  */
 
 enum cmd_retval         cmd_if_shell_exec(struct cmd *, struct cmd_q *);
+void            cmd_if_shell_prepare(struct cmd *, struct cmd_q *);
 
 void   cmd_if_shell_callback(struct job *);
 void   cmd_if_shell_done(struct cmd_q *);
@@ -40,7 +41,8 @@ const struct cmd_entry cmd_if_shell_entry = {
        "bFt:", 2, 3,
        "[-bF] " CMD_TARGET_PANE_USAGE " shell-command command [command]",
        0,
-       cmd_if_shell_exec
+       cmd_if_shell_exec,
+       NULL
 };
 
 struct cmd_if_shell_data {
@@ -51,6 +53,18 @@ struct cmd_if_shell_data {
        int              started;
 };
 
+void
+cmd_if_shell_prepare(struct cmd *self, struct cmd_q *cmdq)
+{
+       struct args     *args = self->args;
+
+       if (args_has(args, 't')) {
+               cmdq->state.wl = cmd_find_pane(cmdq, args_get(args, 't'),
+                   &cmdq->state.s, &cmdq->state.wp);
+       } else
+               cmdq->state.c = cmd_find_client(cmdq, NULL, 1);
+}
+
 enum cmd_retval
 cmd_if_shell_exec(struct cmd *self, struct cmd_q *cmdq)
 {
@@ -64,15 +78,15 @@ cmd_if_shell_exec(struct cmd *self, struct cmd_q *cmdq)
        struct window_pane              *wp = NULL;
        struct format_tree              *ft;
 
-       if (args_has(args, 't'))
-               wl = cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp);
-       else {
-               c = cmd_find_client(cmdq, NULL, 1);
-               if (c != NULL && c->session != NULL) {
-                       s = c->session;
-                       wl = s->curw;
-                       wp = wl->window->active;
-               }
+       wl = cmdq->state.wl;
+       s = cmdq->state.s;
+       wp = cmdq->state.wp;
+       c = cmdq->state.c;
+
+       if (!args_has(args, 't') && c != NULL && c->session != NULL) {
+               s = c->session;
+               wl = s->curw;
+               wp = wl->window->active;
        }
 
        ft = format_create();
diff --git a/cmd-join-pane.c b/cmd-join-pane.c
index 5603541..f6dba10 100644
--- a/cmd-join-pane.c
+++ b/cmd-join-pane.c
@@ -29,6 +29,7 @@
  */
 
 enum cmd_retval         cmd_join_pane_exec(struct cmd *, struct cmd_q *);
+void            cmd_join_pane_prepare(struct cmd *, struct cmd_q *);
 
 enum cmd_retval         join_pane(struct cmd *, struct cmd_q *, int);
 
@@ -36,18 +37,31 @@ const struct cmd_entry cmd_join_pane_entry = {
        "join-pane", "joinp",
        "bdhvp:l:s:t:", 0, 0,
        "[-bdhv] [-p percentage|-l size] [-s src-pane] [-t dst-pane]",
-       0,
-       cmd_join_pane_exec
+       CMD_PREPAREWINDOW,
+       cmd_join_pane_exec,
+       cmd_join_pane_prepare
 };
 
 const struct cmd_entry cmd_move_pane_entry = {
        "move-pane", "movep",
        "bdhvp:l:s:t:", 0, 0,
        "[-bdhv] [-p percentage|-l size] [-s src-pane] [-t dst-pane]",
-       0,
-       cmd_join_pane_exec
+       CMD_PREPAREWINDOW,
+       cmd_join_pane_exec,
+       cmd_join_pane_prepare
 };
 
+
+void
+cmd_join_pane_prepare(struct cmd *self, struct cmd_q *cmdq)
+{
+       struct args     *args = self->args;
+
+       cmdq->state.wl = cmd_find_pane(cmdq, args_get(args, 't'),
+           &cmdq->state.s, &cmdq->state.wp);
+       cmdq->state.wl2 = cmd_find_pane(cmdq, args_get(args, 's'), NULL,
+           &cmdq->state.wp2);
+}
 enum cmd_retval
 cmd_join_pane_exec(struct cmd *self, struct cmd_q *cmdq)
 {
@@ -67,16 +81,17 @@ join_pane(struct cmd *self, struct cmd_q *cmdq, int 
not_same_window)
        enum layout_type         type;
        struct layout_cell      *lc;
 
-       dst_wl = cmd_find_pane(cmdq, args_get(args, 't'), &dst_s, &dst_wp);
-       if (dst_wl == NULL)
+       if ((dst_wl = cmdq->state.wl) == NULL)
                return (CMD_RETURN_ERROR);
+       dst_s =  cmdq->state.s;
+       dst_wp = cmdq->state.wp;
        dst_w = dst_wl->window;
        dst_idx = dst_wl->idx;
        server_unzoom_window(dst_w);
 
-       src_wl = cmd_find_pane(cmdq, args_get(args, 's'), NULL, &src_wp);
-       if (src_wl == NULL)
+       if ((src_wl = cmdq->state.wl2) == NULL)
                return (CMD_RETURN_ERROR);
+       src_wp = cmdq->state.wp2;
        src_w = src_wl->window;
        server_unzoom_window(src_w);
 
diff --git a/cmd-kill-pane.c b/cmd-kill-pane.c
index f4735fd..26f0e0c 100644
--- a/cmd-kill-pane.c
+++ b/cmd-kill-pane.c
@@ -27,24 +27,26 @@
  */
 
 enum cmd_retval         cmd_kill_pane_exec(struct cmd *, struct cmd_q *);
+void            cmd_kill_pane_prepare(struct cmd *, struct cmd_q *);
 
 const struct cmd_entry cmd_kill_pane_entry = {
        "kill-pane", "killp",
        "at:", 0, 0,
        "[-a] " CMD_TARGET_PANE_USAGE,
-       0,
-       cmd_kill_pane_exec
+       CMD_PREPAREPANE,
+       cmd_kill_pane_exec,
+       NULL
 };
 
 enum cmd_retval
 cmd_kill_pane_exec(struct cmd *self, struct cmd_q *cmdq)
 {
-       struct args             *args = self->args;
        struct winlink          *wl;
        struct window_pane      *loopwp, *tmpwp, *wp;
 
-       if ((wl = cmd_find_pane(cmdq, args_get(args, 't'), NULL, &wp)) == NULL)
+       if ((wl = cmdq->state.wl) == NULL)
                return (CMD_RETURN_ERROR);
+       wp = cmdq->state.wp;
        server_unzoom_window(wl->window);
 
        if (window_count_panes(wl->window) == 1) {
diff --git a/cmd-kill-server.c b/cmd-kill-server.c
index 07d9430..930bef5 100644
--- a/cmd-kill-server.c
+++ b/cmd-kill-server.c
@@ -34,7 +34,8 @@ const struct cmd_entry cmd_kill_server_entry = {
        "", 0, 0,
        "",
        0,
-       cmd_kill_server_exec
+       cmd_kill_server_exec,
+       NULL
 };
 
 const struct cmd_entry cmd_start_server_entry = {
@@ -42,7 +43,8 @@ const struct cmd_entry cmd_start_server_entry = {
        "", 0, 0,
        "",
        CMD_STARTSERVER,
-       cmd_kill_server_exec
+       cmd_kill_server_exec,
+       NULL
 };
 
 enum cmd_retval
diff --git a/cmd-kill-session.c b/cmd-kill-session.c
index d7e2a21..3515a67 100644
--- a/cmd-kill-session.c
+++ b/cmd-kill-session.c
@@ -28,13 +28,15 @@
  */
 
 enum cmd_retval         cmd_kill_session_exec(struct cmd *, struct cmd_q *);
+void            cmd_kill_session_prepare(struct cmd *, struct cmd_q *);
 
 const struct cmd_entry cmd_kill_session_entry = {
        "kill-session", NULL,
        "at:", 0, 0,
        "[-a] " CMD_TARGET_SESSION_USAGE,
-       0,
-       cmd_kill_session_exec
+       CMD_PREPARESESSION,
+       cmd_kill_session_exec,
+       NULL
 };
 
 enum cmd_retval
@@ -43,7 +45,7 @@ cmd_kill_session_exec(struct cmd *self, struct cmd_q *cmdq)
        struct args     *args = self->args;
        struct session  *s, *s2, *s3;
 
-       if ((s = cmd_find_session(cmdq, args_get(args, 't'), 0)) == NULL)
+       if ((s = cmdq->state.s) == NULL)
                return (CMD_RETURN_ERROR);
 
        if (args_has(args, 'a')) {
diff --git a/cmd-kill-window.c b/cmd-kill-window.c
index d402acc..9c30e82 100644
--- a/cmd-kill-window.c
+++ b/cmd-kill-window.c
@@ -30,8 +30,9 @@ const struct cmd_entry cmd_kill_window_entry = {
        "kill-window", "killw",
        "at:", 0, 0,
        "[-a] " CMD_TARGET_WINDOW_USAGE,
-       0,
-       cmd_kill_window_exec
+       CMD_PREPAREWINDOW,
+       cmd_kill_window_exec,
+       NULL
 };
 
 const struct cmd_entry cmd_unlink_window_entry = {
@@ -39,7 +40,8 @@ const struct cmd_entry cmd_unlink_window_entry = {
        "kt:", 0, 0,
        "[-k] " CMD_TARGET_WINDOW_USAGE,
        0,
-       cmd_kill_window_exec
+       cmd_kill_window_exec,
+       NULL
 };
 
 enum cmd_retval
@@ -52,7 +54,7 @@ cmd_kill_window_exec(struct cmd *self, struct cmd_q *cmdq)
        struct session_group    *sg;
        u_int                    references;
 
-       if ((wl = cmd_find_window(cmdq, args_get(args, 't'), &s)) == NULL)
+       if ((wl = cmdq->state.wl) == NULL)
                return (CMD_RETURN_ERROR);
        w = wl->window;
 
@@ -65,8 +67,8 @@ cmd_kill_window_exec(struct cmd *self, struct cmd_q *cmdq)
                if (!args_has(self->args, 'k') && w->references == references) {
                        cmdq_error(cmdq, "window only linked to one session");
                        return (CMD_RETURN_ERROR);
-               }
-               server_unlink_window(s, wl);
+       s = cmdq->state.s;
+
        } else {
                if (args_has(args, 'a')) {
                        RB_FOREACH_SAFE(wl2, winlinks, &s->windows, wl3) {
diff --git a/cmd-list-buffers.c b/cmd-list-buffers.c
index 8eb1610..6c5db2c 100644
--- a/cmd-list-buffers.c
+++ b/cmd-list-buffers.c
@@ -37,7 +37,8 @@ const struct cmd_entry cmd_list_buffers_entry = {
        "F:", 0, 0,
        "[-F format]",
        0,
-       cmd_list_buffers_exec
+       cmd_list_buffers_exec,
+       NULL
 };
 
 enum cmd_retval
diff --git a/cmd-list-clients.c b/cmd-list-clients.c
index 292be72..9b51e05 100644
--- a/cmd-list-clients.c
+++ b/cmd-list-clients.c
@@ -39,8 +39,9 @@ const struct cmd_entry cmd_list_clients_entry = {
        "list-clients", "lsc",
        "F:t:", 0, 0,
        "[-F format] " CMD_TARGET_SESSION_USAGE,
-       CMD_READONLY,
-       cmd_list_clients_exec
+       CMD_READONLY|CMD_PREPARESESSION,
+       cmd_list_clients_exec,
+       NULL
 };
 
 enum cmd_retval
@@ -54,12 +55,9 @@ cmd_list_clients_exec(struct cmd *self, struct cmd_q *cmdq)
        u_int                    i;
        char                    *line;
 
-       if (args_has(args, 't')) {
-               s = cmd_find_session(cmdq, args_get(args, 't'), 0);
-               if (s == NULL)
-                       return (CMD_RETURN_ERROR);
-       } else
-               s = NULL;
+       s = cmdq->state.s;
+       if (args_has(args, 't') && s == NULL)
+               return (CMD_RETURN_ERROR);
 
        if ((template = args_get(args, 'F')) == NULL)
                template = LIST_CLIENTS_TEMPLATE;
diff --git a/cmd-list-keys.c b/cmd-list-keys.c
index 0733ee2..bd18b2b 100644
--- a/cmd-list-keys.c
+++ b/cmd-list-keys.c
@@ -36,7 +36,8 @@ const struct cmd_entry cmd_list_keys_entry = {
        "t:", 0, 0,
        "[-t key-table]",
        0,
-       cmd_list_keys_exec
+       cmd_list_keys_exec,
+       NULL
 };
 
 const struct cmd_entry cmd_list_commands_entry = {
@@ -45,6 +46,7 @@ const struct cmd_entry cmd_list_commands_entry = {
        "",
        0,
        cmd_list_keys_exec
+       NULL
 };
 
 enum cmd_retval
diff --git a/cmd-list-panes.c b/cmd-list-panes.c
index 7f62177..caeb48e 100644
--- a/cmd-list-panes.c
+++ b/cmd-list-panes.c
@@ -28,6 +28,7 @@
  */
 
 enum cmd_retval         cmd_list_panes_exec(struct cmd *, struct cmd_q *);
+void            cmd_list_panes_prepare(struct cmd *, struct cmd_q *);
 
 void   cmd_list_panes_server(struct cmd *, struct cmd_q *);
 void   cmd_list_panes_session(
@@ -39,10 +40,24 @@ const struct cmd_entry cmd_list_panes_entry = {
        "list-panes", "lsp",
        "asF:t:", 0, 0,
        "[-as] [-F format] " CMD_TARGET_WINDOW_USAGE,
-       0,
-       cmd_list_panes_exec
+       CMD_PREPARESESSION|CMD_PREPAREWINDOW,
+       cmd_list_panes_exec,
+       cmd_list_panes_prepare
 };
 
+void
+cmd_list_panes_prepare(struct cmd *self, struct cmd_q *cmdq)
+{
+       struct args     *args = self->args;
+
+       if (args_has(args, 's'))
+               cmdq->state.s = cmd_find_session(cmdq, args_get(args, 't'), 0);
+       else if (args_has(args, 't')) {
+               cmdq->state.wl = cmd_find_window(cmdq, args_get(args, 't'),
+                   &cmdq->state.s);
+       }
+}
+
 enum cmd_retval
 cmd_list_panes_exec(struct cmd *self, struct cmd_q *cmdq)
 {
@@ -50,16 +65,16 @@ cmd_list_panes_exec(struct cmd *self, struct cmd_q *cmdq)
        struct session  *s;
        struct winlink  *wl;
 
+       s = cmdq->state.s;
+
        if (args_has(args, 'a'))
                cmd_list_panes_server(self, cmdq);
        else if (args_has(args, 's')) {
-               s = cmd_find_session(cmdq, args_get(args, 't'), 0);
                if (s == NULL)
                        return (CMD_RETURN_ERROR);
                cmd_list_panes_session(self, s, cmdq, 1);
        } else {
-               wl = cmd_find_window(cmdq, args_get(args, 't'), &s);
-               if (wl == NULL)
+               if ((wl = cmdq->state.wl) == NULL)
                        return (CMD_RETURN_ERROR);
                cmd_list_panes_window(self, s, wl, cmdq, 0);
        }
diff --git a/cmd-list-sessions.c b/cmd-list-sessions.c
index ea8f3e3..5b4472f 100644
--- a/cmd-list-sessions.c
+++ b/cmd-list-sessions.c
@@ -43,7 +43,8 @@ const struct cmd_entry cmd_list_sessions_entry = {
        "F:", 0, 0,
        "[-F format]",
        0,
-       cmd_list_sessions_exec
+       cmd_list_sessions_exec,
+       NULL
 };
 
 enum cmd_retval
diff --git a/cmd-list-windows.c b/cmd-list-windows.c
index 5f73e8d..3cd980c 100644
--- a/cmd-list-windows.c
+++ b/cmd-list-windows.c
@@ -40,6 +40,7 @@
        "[#{window_width}x#{window_height}] "
 
 enum cmd_retval         cmd_list_windows_exec(struct cmd *, struct cmd_q *);
+void            cmd_list_windows_prepare(struct cmd *, struct cmd_q *);
 
 void   cmd_list_windows_server(struct cmd *, struct cmd_q *);
 void   cmd_list_windows_session(struct cmd *, struct session *,
@@ -49,10 +50,20 @@ const struct cmd_entry cmd_list_windows_entry = {
        "list-windows", "lsw",
        "F:at:", 0, 0,
        "[-a] [-F format] " CMD_TARGET_SESSION_USAGE,
-       0,
-       cmd_list_windows_exec
+       CMD_PREPARESESSION,
+       cmd_list_windows_exec,
+       cmd_list_windows_prepare
 };
 
+void
+cmd_list_windows_prepare(struct cmd *self, struct cmd_q *cmdq)
+{
+       struct args     *args = self->args;
+
+       if (!args_has(args, 'a'))
+               cmdq->state.s = cmd_find_session(cmdq, args_get(args, 't'), 0);
+}
+
 enum cmd_retval
 cmd_list_windows_exec(struct cmd *self, struct cmd_q *cmdq)
 {
@@ -62,8 +73,7 @@ cmd_list_windows_exec(struct cmd *self, struct cmd_q *cmdq)
        if (args_has(args, 'a'))
                cmd_list_windows_server(self, cmdq);
        else {
-               s = cmd_find_session(cmdq, args_get(args, 't'), 0);
-               if (s == NULL)
+               if ((s = cmdq->state.s) == NULL)
                        return (CMD_RETURN_ERROR);
                cmd_list_windows_session(self, s, cmdq, 0);
        }
diff --git a/cmd-load-buffer.c b/cmd-load-buffer.c
index 785a701..fcf603d 100644
--- a/cmd-load-buffer.c
+++ b/cmd-load-buffer.c
@@ -39,7 +39,8 @@ const struct cmd_entry cmd_load_buffer_entry = {
        "b:", 1, 1,
        CMD_BUFFER_USAGE " path",
        0,
-       cmd_load_buffer_exec
+       cmd_load_buffer_exec,
+       NULL
 };
 
 enum cmd_retval
diff --git a/cmd-lock-server.c b/cmd-lock-server.c
index de76475..4c4ca6e 100644
--- a/cmd-lock-server.c
+++ b/cmd-lock-server.c
@@ -25,13 +25,15 @@
  */
 
 enum cmd_retval         cmd_lock_server_exec(struct cmd *, struct cmd_q *);
+void            cmd_lock_server_prepare(struct cmd *, struct cmd_q *);
 
 const struct cmd_entry cmd_lock_server_entry = {
        "lock-server", "lock",
        "", 0, 0,
        "",
        0,
-       cmd_lock_server_exec
+       cmd_lock_server_exec,
+       cmd_lock_server_prepare,
 };
 
 const struct cmd_entry cmd_lock_session_entry = {
@@ -39,7 +41,8 @@ const struct cmd_entry cmd_lock_session_entry = {
        "t:", 0, 0,
        CMD_TARGET_SESSION_USAGE,
        0,
-       cmd_lock_server_exec
+       cmd_lock_server_exec,
+       cmd_lock_server_prepare
 };
 
 const struct cmd_entry cmd_lock_client_entry = {
@@ -47,26 +50,35 @@ const struct cmd_entry cmd_lock_client_entry = {
        "t:", 0, 0,
        CMD_TARGET_CLIENT_USAGE,
        0,
-       cmd_lock_server_exec
+       cmd_lock_server_exec,
+       cmd_lock_server_prepare
 };
 
+void
+cmd_lock_server_prepare(struct cmd *self, struct cmd_q *cmdq)
+{
+       struct args     *args = self->args;
+
+       if (self->entry == &cmd_lock_session_entry)
+               cmdq->state.s = cmd_find_session(cmdq, args_get(args, 't'), 0);
+       else if (self->entry == &cmd_lock_client_entry)
+               cmdq->state.c = cmd_find_client(cmdq, args_get(args, 't'), 0);
+}
+
 enum cmd_retval
 cmd_lock_server_exec(struct cmd *self, unused struct cmd_q *cmdq)
 {
-       struct args     *args = self->args;
        struct client   *c;
        struct session  *s;
 
        if (self->entry == &cmd_lock_server_entry)
                server_lock();
        else if (self->entry == &cmd_lock_session_entry) {
-               s = cmd_find_session(cmdq, args_get(args, 't'), 0);
-               if (s == NULL)
+               if ((s = cmdq->state.s) == NULL)
                        return (CMD_RETURN_ERROR);
                server_lock_session(s);
        } else {
-               c = cmd_find_client(cmdq, args_get(args, 't'), 0);
-               if (c == NULL)
+               if ((c = cmdq->state.c) == NULL)
                        return (CMD_RETURN_ERROR);
                server_lock_client(c);
        }
diff --git a/cmd-move-window.c b/cmd-move-window.c
index 3064cd6..c864f14 100644
--- a/cmd-move-window.c
+++ b/cmd-move-window.c
@@ -27,12 +27,14 @@
  */
 
 enum cmd_retval         cmd_move_window_exec(struct cmd *, struct cmd_q *);
+void            cmd_move_window_prepare(struct cmd *, struct cmd_q *);
 
 const struct cmd_entry cmd_move_window_entry = {
        "move-window", "movew",
        "dkrs:t:", 0, 0,
        "[-dkr] " CMD_SRCDST_WINDOW_USAGE,
        0,
+<<<<<<< HEAD
        cmd_move_window_exec
 };
 
@@ -40,10 +42,26 @@ const struct cmd_entry cmd_link_window_entry = {
        "link-window", "linkw",
        "dks:t:", 0, 0,
        "[-dk] " CMD_SRCDST_WINDOW_USAGE,
-       0,
-       cmd_move_window_exec
+       CMD_PREPARESESSION|CMD_PREPAREWINDOW,
+       cmd_move_window_exec,
+       cmd_move_window_prepare
 };
 
+void
+cmd_move_window_prepare(struct cmd *self, struct cmd_q *cmdq)
+{
+       struct args     *args = self->args;
+
+       if (args_has(args, 'r'))
+               cmdq->state.s = cmd_find_session(cmdq, args_get(args, 't'), 0);
+       else {
+               cmdq->state.wl = cmd_find_window(cmdq, args_get(args, 's'),
+                   &cmdq->state.s);
+               cmdq->state.idx = cmd_find_index(cmdq, args_get(args, 't'),
+                   &cmdq->state.s2);
+       }
+}
+
 enum cmd_retval
 cmd_move_window_exec(struct cmd *self, struct cmd_q *cmdq)
 {
@@ -54,8 +72,7 @@ cmd_move_window_exec(struct cmd *self, struct cmd_q *cmdq)
        int              idx, kflag, dflag;
 
        if (args_has(args, 'r')) {
-               s = cmd_find_session(cmdq, args_get(args, 't'), 0);
-               if (s == NULL)
+               if ((s = cmdq->state.s) == NULL)
                        return (CMD_RETURN_ERROR);
 
                session_renumber_windows(s);
@@ -63,10 +80,12 @@ cmd_move_window_exec(struct cmd *self, struct cmd_q *cmdq)
 
                return (CMD_RETURN_NORMAL);
        }
+       src = cmdq->state.s;
+       dst = cmdq->state.s2;
 
-       if ((wl = cmd_find_window(cmdq, args_get(args, 's'), &src)) == NULL)
+       if ((wl = cmdq->state.wl) == NULL)
                return (CMD_RETURN_ERROR);
-       if ((idx = cmd_find_index(cmdq, args_get(args, 't'), &dst)) == -2)
+       if ((idx = cmdq->state.idx) == -2)
                return (CMD_RETURN_ERROR);
 
        kflag = args_has(self->args, 'k');
diff --git a/cmd-new-session.c b/cmd-new-session.c
index e244f88..084aa88 100644
--- a/cmd-new-session.c
+++ b/cmd-new-session.c
@@ -42,7 +42,8 @@ const struct cmd_entry cmd_new_session_entry = {
        "[-s session-name] " CMD_TARGET_SESSION_USAGE " [-x width] "
        "[-y height] [command]",
        CMD_STARTSERVER|CMD_CANTNEST,
-       cmd_new_session_exec
+       cmd_new_session_exec,
+       NULL
 };
 
 const struct cmd_entry cmd_has_session_entry = {
@@ -51,6 +52,7 @@ const struct cmd_entry cmd_has_session_entry = {
        CMD_TARGET_SESSION_USAGE,
        0,
        cmd_new_session_exec
+       NULL
 };
 
 enum cmd_retval
@@ -90,8 +92,8 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
                }
                if (session_find(newname) != NULL) {
                        if (args_has(args, 'A')) {
-                               return (cmd_attach_session(cmdq, newname,
-                                   args_has(args, 'D'), 0, NULL));
+                               return (cmd_attach_session(cmdq, args_has(args,
+                                   'D'), 0, NULL));
                        }
                        cmdq_error(cmdq, "duplicate session: %s", newname);
                        return (CMD_RETURN_ERROR);
diff --git a/cmd-new-window.c b/cmd-new-window.c
index 7f14b21..4e222ba 100644
--- a/cmd-new-window.c
+++ b/cmd-new-window.c
@@ -32,23 +32,37 @@
 
 #define NEW_WINDOW_TEMPLATE "#{session_name}:#{window_index}.#{pane_index}"
 
-enum cmd_retval        cmd_new_window_exec(struct cmd *, struct cmd_q *);
+enum cmd_retval         cmd_new_window_exec(struct cmd *, struct cmd_q *);
+void            cmd_new_window_prepare(struct cmd *, struct cmd_q *);
 
 const struct cmd_entry cmd_new_window_entry = {
        "new-window", "neww",
        "ac:dF:kn:Pt:", 0, -1,
        "[-adkP] [-c start-directory] [-F format] [-n window-name] "
        CMD_TARGET_WINDOW_USAGE " [command]",
-       0,
-       cmd_new_window_exec
+       CMD_PREPAREWINDOW,
+       cmd_new_window_exec,
+       cmd_new_window_prepare
 };
 
+void
+cmd_new_window_prepare(struct cmd *self, struct cmd_q *cmdq)
+{
+       struct args     *args = self->args;
+
+       if (args_has(args, 'a')) {
+               cmdq->state.wl = cmd_find_window(cmdq, args_get(args, 't'),
+                   &cmdq->state.s);
+       } else
+               cmd_find_index(cmdq, args_get(args, 't'), &cmdq->state.s);
+}
+
 enum cmd_retval
 cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
 {
        struct args             *args = self->args;
-       struct session          *s;
-       struct winlink          *wl;
+       struct session          *s = cmdq->state.s;
+       struct winlink          *wl = cmdq->state.wl;
        struct client           *c;
        const char              *cmd, *path, *template;
        char                   **argv, *cause, *cp;
@@ -57,7 +71,6 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
        struct environ_entry    *envent;
 
        if (args_has(args, 'a')) {
-               wl = cmd_find_window(cmdq, args_get(args, 't'), &s);
                if (wl == NULL)
                        return (CMD_RETURN_ERROR);
                idx = wl->idx + 1;
diff --git a/cmd-paste-buffer.c b/cmd-paste-buffer.c
index 5d91aef..c3ad875 100644
--- a/cmd-paste-buffer.c
+++ b/cmd-paste-buffer.c
@@ -36,8 +36,9 @@ const struct cmd_entry cmd_paste_buffer_entry = {
        "paste-buffer", "pasteb",
        "db:prs:t:", 0, 0,
        "[-dpr] [-s separator] " CMD_BUFFER_USAGE " " CMD_TARGET_PANE_USAGE,
-       0,
-       cmd_paste_buffer_exec
+       CMD_PREPAREPANE,
+       cmd_paste_buffer_exec,
+       NULL
 };
 
 enum cmd_retval
@@ -45,17 +46,29 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
 {
        struct args             *args = self->args;
        struct window_pane      *wp;
-       struct session          *s;
        struct paste_buffer     *pb;
        const char              *sepstr, *bufname;
 
-       if (cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp) == NULL)
+       if (cmdq->state.wl == NULL)
                return (CMD_RETURN_ERROR);
 
        bufname = NULL;
        if (args_has(args, 'b'))
                bufname = args_get(args, 'b');
 
+       wp = cmdq->state.wp;
+
+       if (!args_has(args, 'b'))
+               buffer = -1;
+       else {
+               buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
+               if (cause != NULL) {
+                       cmdq_error(cmdq, "buffer %s", cause);
+                       free(cause);
+                       return (CMD_RETURN_ERROR);
+               }
+       }
+
        if (bufname == NULL)
                pb = paste_get_top();
        else {
diff --git a/cmd-pipe-pane.c b/cmd-pipe-pane.c
index 4ab1824..facab6f 100644
--- a/cmd-pipe-pane.c
+++ b/cmd-pipe-pane.c
@@ -39,8 +39,9 @@ const struct cmd_entry cmd_pipe_pane_entry = {
        "pipe-pane", "pipep",
        "ot:", 0, 1,
        "[-o] " CMD_TARGET_PANE_USAGE " [command]",
-       0,
-       cmd_pipe_pane_exec
+       CMD_PREPAREPANE,
+       cmd_pipe_pane_exec,
+       NULL
 };
 
 enum cmd_retval
@@ -52,8 +53,9 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmd_q *cmdq)
        char                    *command;
        int                      old_fd, pipe_fd[2], null_fd;
 
-       if (cmd_find_pane(cmdq, args_get(args, 't'), NULL, &wp) == NULL)
+       if (cmdq->state.wl == NULL)
                return (CMD_RETURN_ERROR);
+       wp = cmdq->state.wp;
        c = cmd_find_client(cmdq, NULL, 1);
 
        /* Destroy the old pipe. */
diff --git a/cmd-queue.c b/cmd-queue.c
index a98fa9b..993303f 100644
--- a/cmd-queue.c
+++ b/cmd-queue.c
@@ -21,9 +21,30 @@
 #include <ctype.h>
 #include <stdlib.h>
 #include <time.h>
+#include <string.h>
 
 #include "tmux.h"
 
+void   cmdq_set_state(struct cmd_q *);
+void   cmdq_run_hook(struct hooks *, const char *, struct cmd *,
+           struct cmd_q *);
+
+/* Fill in state members. */
+void
+cmdq_set_state(struct cmd_q *cmdq)
+{
+       memset(&cmdq->state, 0, sizeof cmdq->state);
+
+       cmdq->state.c = cmdq->client;
+
+       cmdq->state.s = cmdq->client != NULL ? cmdq->client->session : NULL;
+       cmdq->state.s2 = NULL;
+
+       cmdq->state.w = NULL;
+       cmdq->state.wl = NULL;
+       cmdq->state.wp = NULL;
+}
+
 /* Create new command queue. */
 struct cmd_q *
 cmdq_new(struct client *c)
@@ -145,6 +166,20 @@ cmdq_run(struct cmd_q *cmdq, struct cmd_list *cmdlist)
        }
 }
 
+/* Run hooks based on the hooks prefix (before/after). */
+void
+cmdq_run_hook(struct hooks *hooks, const char *prefix, struct cmd *cmd,
+    struct cmd_q *cmdq)
+{
+       struct hook     *hook;
+       char            *s;
+
+       xasprintf(&s, "%s-%s", prefix, cmd->entry->name);
+       if ((hook = hooks_find(hooks, s)) != NULL)
+               hooks_run(hook, cmdq);
+       free(s);
+}
+
 /* Add command list to queue. */
 void
 cmdq_append(struct cmd_q *cmdq, struct cmd_list *cmdlist)
@@ -162,12 +197,15 @@ int
 cmdq_continue(struct cmd_q *cmdq)
 {
        struct cmd_q_item       *next;
+       struct hooks            *hooks;
        enum cmd_retval          retval;
        int                      empty, guard, flags;
        char                     s[1024];
 
        notify_disable();
 
+       cmdq_set_state(cmdq);
+
        empty = TAILQ_EMPTY(&cmdq->queue);
        if (empty)
                goto empty;
@@ -180,6 +218,25 @@ cmdq_continue(struct cmd_q *cmdq)
 
        do {
                while (cmdq->cmd != NULL) {
+                       /*
+                        * Call prepare(). This will set up the execution
+                        * context of the command. If a command wishes to do
+                        * more than the default action of prepare() then this
+                        * also call's that command's version.
+                        */
+                       cmd_prepare(cmdq->cmd, cmdq);
+
+                       /*
+                        * If we set no session via this or the prepare()
+                        * function wasn't defined, then use the global hooks,
+                        * otherwise used the intended session's hooks when
+                        * running the command.
+                        */
+                       if (cmdq->state.s != NULL)
+                               hooks = &cmdq->state.s->hooks;
+                       else
+                               hooks = &global_hooks;
+
                        cmd_print(cmdq->cmd, s, sizeof s);
                        log_debug("cmdq %p: %s (client %d)", cmdq, s,
                            cmdq->client != NULL ? cmdq->client->ibuf.fd : -1);
@@ -190,7 +247,11 @@ cmdq_continue(struct cmd_q *cmdq)
                        flags = !!(cmdq->cmd->flags & CMD_CONTROL);
                        guard = cmdq_guard(cmdq, "begin", flags);
 
+                       cmdq_run_hook(hooks, "before", cmdq->cmd, cmdq);
                        retval = cmdq->cmd->entry->exec(cmdq->cmd, cmdq);
+                       if (retval == CMD_RETURN_ERROR)
+                               break;
+                       cmdq_run_hook(hooks, "after", cmdq->cmd, cmdq);
 
                        if (guard) {
                                if (retval == CMD_RETURN_ERROR)
diff --git a/cmd-refresh-client.c b/cmd-refresh-client.c
index f693872..969605b 100644
--- a/cmd-refresh-client.c
+++ b/cmd-refresh-client.c
@@ -30,8 +30,9 @@ const struct cmd_entry cmd_refresh_client_entry = {
        "refresh-client", "refresh",
        "C:St:", 0, 0,
        "[-S] [-C size] " CMD_TARGET_CLIENT_USAGE,
-       0,
-       cmd_refresh_client_exec
+       CMD_PREPARECLIENT,
+       cmd_refresh_client_exec,
+       NULL
 };
 
 enum cmd_retval
@@ -42,7 +43,7 @@ cmd_refresh_client_exec(struct cmd *self, struct cmd_q *cmdq)
        const char      *size;
        u_int            w, h;
 
-       if ((c = cmd_find_client(cmdq, args_get(args, 't'), 0)) == NULL)
+       if ((c = cmdq->state.c) == NULL)
                return (CMD_RETURN_ERROR);
 
        if (args_has(args, 'C')) {
diff --git a/cmd-rename-session.c b/cmd-rename-session.c
index 481154c..e44c45b 100644
--- a/cmd-rename-session.c
+++ b/cmd-rename-session.c
@@ -27,13 +27,15 @@
  */
 
 enum cmd_retval         cmd_rename_session_exec(struct cmd *, struct cmd_q *);
+void            cmd_rename_session_prepare(struct cmd *, struct cmd_q *);
 
 const struct cmd_entry cmd_rename_session_entry = {
        "rename-session", "rename",
        "t:", 1, 1,
        CMD_TARGET_SESSION_USAGE " new-name",
-       0,
-       cmd_rename_session_exec
+       CMD_PREPARESESSION,
+       cmd_rename_session_exec,
+       NULL
 };
 
 enum cmd_retval
@@ -53,7 +55,7 @@ cmd_rename_session_exec(struct cmd *self, struct cmd_q *cmdq)
                return (CMD_RETURN_ERROR);
        }
 
-       if ((s = cmd_find_session(cmdq, args_get(args, 't'), 0)) == NULL)
+       if ((s = cmdq->state.s) == NULL)
                return (CMD_RETURN_ERROR);
 
        RB_REMOVE(sessions, &sessions, s);
diff --git a/cmd-rename-window.c b/cmd-rename-window.c
index 2f677a4..aeee5b9 100644
--- a/cmd-rename-window.c
+++ b/cmd-rename-window.c
@@ -27,23 +27,24 @@
  */
 
 enum cmd_retval         cmd_rename_window_exec(struct cmd *, struct cmd_q *);
+void            cmd_rename_window_prepare(struct cmd *, struct cmd_q *);
 
 const struct cmd_entry cmd_rename_window_entry = {
        "rename-window", "renamew",
        "t:", 1, 1,
        CMD_TARGET_WINDOW_USAGE " new-name",
-       0,
-       cmd_rename_window_exec
+       CMD_PREPAREWINDOW,
+       cmd_rename_window_exec,
+       NULL
 };
 
 enum cmd_retval
 cmd_rename_window_exec(struct cmd *self, struct cmd_q *cmdq)
 {
        struct args     *args = self->args;
-       struct session  *s;
        struct winlink  *wl;
 
-       if ((wl = cmd_find_window(cmdq, args_get(args, 't'), &s)) == NULL)
+       if ((wl = cmdq->state.wl) == NULL)
                return (CMD_RETURN_ERROR);
 
        window_set_name(wl->window, args->argv[0]);
diff --git a/cmd-resize-pane.c b/cmd-resize-pane.c
index 42f0f39..b55b2c3 100644
--- a/cmd-resize-pane.c
+++ b/cmd-resize-pane.c
@@ -32,8 +32,9 @@ const struct cmd_entry cmd_resize_pane_entry = {
        "resize-pane", "resizep",
        "DLRt:Ux:y:Z", 0, 1,
        "[-DLRUZ] [-x width] [-y height] " CMD_TARGET_PANE_USAGE " 
[adjustment]",
-       0,
-       cmd_resize_pane_exec
+       CMD_PREPAREPANE,
+       cmd_resize_pane_exec,
+       NULL
 };
 
 enum cmd_retval
@@ -48,9 +49,10 @@ cmd_resize_pane_exec(struct cmd *self, struct cmd_q *cmdq)
        u_int                    adjust;
        int                      x, y;
 
-       if ((wl = cmd_find_pane(cmdq, args_get(args, 't'), NULL, &wp)) == NULL)
+       if ((wl = cmdq->state.wl) == NULL)
                return (CMD_RETURN_ERROR);
        w = wl->window;
+       wp = cmdq->state.wp;
 
        if (args_has(args, 'Z')) {
                if (w->flags & WINDOW_ZOOMED)
diff --git a/cmd-respawn-pane.c b/cmd-respawn-pane.c
index 4703153..2aaee6b 100644
--- a/cmd-respawn-pane.c
+++ b/cmd-respawn-pane.c
@@ -34,8 +34,9 @@ const struct cmd_entry cmd_respawn_pane_entry = {
        "respawn-pane", "respawnp",
        "kt:", 0, -1,
        "[-k] " CMD_TARGET_PANE_USAGE " [command]",
-       0,
-       cmd_respawn_pane_exec
+       CMD_PREPAREPANE,
+       cmd_respawn_pane_exec,
+       NULL
 };
 
 enum cmd_retval
@@ -52,9 +53,11 @@ cmd_respawn_pane_exec(struct cmd *self, struct cmd_q *cmdq)
        u_int                    idx;
        struct environ_entry    *envent;
 
-       if ((wl = cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp)) == NULL)
+       if ((wl = cmdq->state.wl) == NULL)
                return (CMD_RETURN_ERROR);
        w = wl->window;
+       s = cmdq->state.s;
+       wp = cmdq->state.wp;
 
        if (!args_has(self->args, 'k') && wp->fd != -1) {
                if (window_pane_index(wp, &idx) != 0)
diff --git a/cmd-respawn-window.c b/cmd-respawn-window.c
index 06102ed..af21f2f 100644
--- a/cmd-respawn-window.c
+++ b/cmd-respawn-window.c
@@ -33,8 +33,9 @@ const struct cmd_entry cmd_respawn_window_entry = {
        "respawn-window", "respawnw",
        "kt:", 0, -1,
        "[-k] " CMD_TARGET_WINDOW_USAGE " [command]",
-       0,
-       cmd_respawn_window_exec
+       CMD_PREPAREWINDOW,
+       cmd_respawn_window_exec,
+       NULL
 };
 
 enum cmd_retval
@@ -50,9 +51,10 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_q *cmdq)
        char                    *cause;
        struct environ_entry    *envent;
 
-       if ((wl = cmd_find_window(cmdq, args_get(args, 't'), &s)) == NULL)
+       if ((wl = cmdq->state.wl) == NULL)
                return (CMD_RETURN_ERROR);
        w = wl->window;
+       s = cmdq->state.s;
 
        if (!args_has(self->args, 'k')) {
                TAILQ_FOREACH(wp, &w->panes, entry) {
diff --git a/cmd-rotate-window.c b/cmd-rotate-window.c
index 859ff04..310268c 100644
--- a/cmd-rotate-window.c
+++ b/cmd-rotate-window.c
@@ -30,21 +30,21 @@ const struct cmd_entry cmd_rotate_window_entry = {
        "rotate-window", "rotatew",
        "Dt:U", 0, 0,
        "[-DU] " CMD_TARGET_WINDOW_USAGE,
-       0,
-       cmd_rotate_window_exec
+       CMD_PREPAREWINDOW,
+       cmd_rotate_window_exec,
+       NULL
 };
 
 enum cmd_retval
 cmd_rotate_window_exec(struct cmd *self, struct cmd_q *cmdq)
 {
-       struct args             *args = self->args;
        struct winlink          *wl;
        struct window           *w;
        struct window_pane      *wp, *wp2;
        struct layout_cell      *lc;
        u_int                    sx, sy, xoff, yoff;
 
-       if ((wl = cmd_find_window(cmdq, args_get(args, 't'), NULL)) == NULL)
+       if ((wl = cmdq->state.wl) == NULL)
                return (CMD_RETURN_ERROR);
        w = wl->window;
 
diff --git a/cmd-run-shell.c b/cmd-run-shell.c
index b47c282..cae8068 100644
--- a/cmd-run-shell.c
+++ b/cmd-run-shell.c
@@ -39,8 +39,9 @@ const struct cmd_entry cmd_run_shell_entry = {
        "run-shell", "run",
        "bt:", 1, 1,
        "[-b] " CMD_TARGET_PANE_USAGE " shell-command",
-       0,
-       cmd_run_shell_exec
+       CMD_PREPAREPANE,
+       cmd_run_shell_exec,
+       NULL
 };
 
 struct cmd_run_shell_data {
@@ -82,7 +83,7 @@ cmd_run_shell_exec(struct cmd *self, struct cmd_q *cmdq)
        struct format_tree              *ft;
 
        if (args_has(args, 't'))
-               wl = cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp);
+               wl = cmdq->state.wl;
        else {
                c = cmd_find_client(cmdq, NULL, 1);
                if (c != NULL && c->session != NULL) {
@@ -91,6 +92,9 @@ cmd_run_shell_exec(struct cmd *self, struct cmd_q *cmdq)
                        wp = wl->window->active;
                }
        }
+       s = cmdq->state.s;
+       wl = cmdq->state.wl;
+       wp = cmdq->state.wp;
 
        ft = format_create();
        if (s != NULL)
diff --git a/cmd-save-buffer.c b/cmd-save-buffer.c
index 47a263d..e3ed06b 100644
--- a/cmd-save-buffer.c
+++ b/cmd-save-buffer.c
@@ -38,7 +38,8 @@ const struct cmd_entry cmd_save_buffer_entry = {
        "ab:", 1, 1,
        "[-a] " CMD_BUFFER_USAGE " path",
        0,
-       cmd_save_buffer_exec
+       cmd_save_buffer_exec,
+       NULL
 };
 
 const struct cmd_entry cmd_show_buffer_entry = {
@@ -46,7 +47,8 @@ const struct cmd_entry cmd_show_buffer_entry = {
        "b:", 0, 0,
        CMD_BUFFER_USAGE,
        0,
-       cmd_save_buffer_exec
+       cmd_save_buffer_exec,
+       NULL
 };
 
 enum cmd_retval
diff --git a/cmd-select-layout.c b/cmd-select-layout.c
index 77137b7..4eb3719 100644
--- a/cmd-select-layout.c
+++ b/cmd-select-layout.c
@@ -30,24 +30,27 @@ const struct cmd_entry cmd_select_layout_entry = {
        "select-layout", "selectl",
        "npt:", 0, 1,
        "[-np] " CMD_TARGET_WINDOW_USAGE " [layout-name]",
-       0,
-       cmd_select_layout_exec
+       CMD_PREPAREWINDOW,
+       cmd_select_layout_exec,
+       NULL
 };
 
 const struct cmd_entry cmd_next_layout_entry = {
        "next-layout", "nextl",
        "t:", 0, 0,
        CMD_TARGET_WINDOW_USAGE,
-       0,
-       cmd_select_layout_exec
+       CMD_PREPAREWINDOW,
+       cmd_select_layout_exec,
+       NULL
 };
 
 const struct cmd_entry cmd_previous_layout_entry = {
        "previous-layout", "prevl",
        "t:", 0, 0,
        CMD_TARGET_WINDOW_USAGE,
-       0,
-       cmd_select_layout_exec
+       CMD_PREPAREWINDOW,
+       cmd_select_layout_exec,
+       NULL
 };
 
 enum cmd_retval
@@ -58,7 +61,7 @@ cmd_select_layout_exec(struct cmd *self, struct cmd_q *cmdq)
        const char      *layoutname;
        int              next, previous, layout;
 
-       if ((wl = cmd_find_window(cmdq, args_get(args, 't'), NULL)) == NULL)
+       if ((wl = cmdq->state.wl) == NULL)
                return (CMD_RETURN_ERROR);
        server_unzoom_window(wl->window);
 
diff --git a/cmd-select-pane.c b/cmd-select-pane.c
index 5810eea..e4bebc5 100644
--- a/cmd-select-pane.c
+++ b/cmd-select-pane.c
@@ -25,23 +25,39 @@
  */
 
 enum cmd_retval         cmd_select_pane_exec(struct cmd *, struct cmd_q *);
+void            cmd_select_pane_prepare(struct cmd *, struct cmd_q *);
 
 const struct cmd_entry cmd_select_pane_entry = {
        "select-pane", "selectp",
        "DdeLlRt:U", 0, 0,
        "[-DdeLlRU] " CMD_TARGET_PANE_USAGE,
-       0,
-       cmd_select_pane_exec
+       CMD_PREPAREPANE,
+       cmd_select_pane_exec,
+       cmd_select_pane_prepare
 };
 
 const struct cmd_entry cmd_last_pane_entry = {
        "last-pane", "lastp",
        "det:", 0, 0,
        "[-de] " CMD_TARGET_WINDOW_USAGE,
-       0,
-       cmd_select_pane_exec
+       CMD_PREPAREPANE,
+       cmd_select_pane_exec,
+       cmd_select_pane_prepare
 };
 
+void
+cmd_select_pane_prepare(struct cmd *self, struct cmd_q *cmdq)
+{
+       struct args     *args = self->args;
+
+       if (self->entry == &cmd_last_pane_entry || args_has(args, 'l')) {
+               cmdq->state.wl = cmd_find_window(cmdq, args_get(args, 't'),
+                   NULL);
+       } else {
+               cmdq->state.wl = cmd_find_pane(cmdq, args_get(args, 't'), NULL,
+                   &cmdq->state.wp);
+       }
+}
 enum cmd_retval
 cmd_select_pane_exec(struct cmd *self, struct cmd_q *cmdq)
 {
@@ -50,8 +66,7 @@ cmd_select_pane_exec(struct cmd *self, struct cmd_q *cmdq)
        struct window_pane      *wp;
 
        if (self->entry == &cmd_last_pane_entry || args_has(args, 'l')) {
-               wl = cmd_find_window(cmdq, args_get(args, 't'), NULL);
-               if (wl == NULL)
+               if ((wl = cmdq->state.wl) == NULL)
                        return (CMD_RETURN_ERROR);
 
                if (wl->window->last == NULL) {
@@ -73,9 +88,11 @@ cmd_select_pane_exec(struct cmd *self, struct cmd_q *cmdq)
                return (CMD_RETURN_NORMAL);
        }
 
-       if ((wl = cmd_find_pane(cmdq, args_get(args, 't'), NULL, &wp)) == NULL)
+       if ((wl = cmdq->state.wl) == NULL)
                return (CMD_RETURN_ERROR);
 
+       wp = cmdq->state.wp;
+
        server_unzoom_window(wp->window);
        if (!window_pane_visible(wp)) {
                cmdq_error(cmdq, "pane not visible");
diff --git a/cmd-select-window.c b/cmd-select-window.c
index f530f1f..bbd7f71 100644
--- a/cmd-select-window.c
+++ b/cmd-select-window.c
@@ -27,43 +27,70 @@
  */
 
 enum cmd_retval         cmd_select_window_exec(struct cmd *, struct cmd_q *);
+void            cmd_select_window_prepare(struct cmd *, struct cmd_q *);
 
 const struct cmd_entry cmd_select_window_entry = {
        "select-window", "selectw",
        "lnpTt:", 0, 0,
        "[-lnpT] " CMD_TARGET_WINDOW_USAGE,
-       0,
-       cmd_select_window_exec
+       CMD_PREPAREWINDOW,
+       cmd_select_window_exec,
+       cmd_select_window_prepare
 };
 
 const struct cmd_entry cmd_next_window_entry = {
        "next-window", "next",
        "at:", 0, 0,
        "[-a] " CMD_TARGET_SESSION_USAGE,
-       0,
-       cmd_select_window_exec
+       CMD_PREPAREWINDOW,
+       cmd_select_window_exec,
+       cmd_select_window_prepare
 };
 
 const struct cmd_entry cmd_previous_window_entry = {
        "previous-window", "prev",
        "at:", 0, 0,
        "[-a] " CMD_TARGET_SESSION_USAGE,
-       0,
-       cmd_select_window_exec
+       CMD_PREPAREWINDOW,
+       cmd_select_window_exec,
+       cmd_select_window_prepare
 };
 
 const struct cmd_entry cmd_last_window_entry = {
        "last-window", "last",
        "t:", 0, 0,
        CMD_TARGET_SESSION_USAGE,
-       0,
-       cmd_select_window_exec
+       CMD_PREPAREWINDOW,
+       cmd_select_window_exec,
+       cmd_select_window_prepare
 };
 
+void
+cmd_select_window_prepare(struct cmd *self, struct cmd_q *cmdq)
+{
+       struct args     *args = self->args;
+       int              next, previous, last;
+
+       next = self->entry == &cmd_next_window_entry;
+       if (args_has(self->args, 'n'))
+               next = 1;
+       previous = self->entry == &cmd_previous_window_entry;
+       if (args_has(self->args, 'p'))
+               previous = 1;
+       last = self->entry == &cmd_last_window_entry;
+       if (args_has(self->args, 'l'))
+               last = 1;
+
+       if (next || previous || last)
+               cmdq->state.s = cmd_find_session(cmdq, args_get(args, 't'), 0);
+       else {
+               cmdq->state.wl = cmd_find_window(cmdq, args_get(args, 't'),
+                   &cmdq->state.s);
+       }
+}
 enum cmd_retval
 cmd_select_window_exec(struct cmd *self, struct cmd_q *cmdq)
 {
-       struct args     *args = self->args;
        struct winlink  *wl;
        struct session  *s;
        int              next, previous, last, activity;
@@ -79,8 +106,7 @@ cmd_select_window_exec(struct cmd *self, struct cmd_q *cmdq)
                last = 1;
 
        if (next || previous || last) {
-               s = cmd_find_session(cmdq, args_get(args, 't'), 0);
-               if (s == NULL)
+               if ((s = cmdq->state.s) == NULL)
                        return (CMD_RETURN_ERROR);
 
                activity = args_has(self->args, 'a');
@@ -103,9 +129,9 @@ cmd_select_window_exec(struct cmd *self, struct cmd_q *cmdq)
 
                server_redraw_session(s);
        } else {
-               wl = cmd_find_window(cmdq, args_get(args, 't'), &s);
-               if (wl == NULL)
+               if ((wl = cmdq->state.wl) == NULL)
                        return (CMD_RETURN_ERROR);
+               s = cmdq->state.s;
 
                /*
                 * If -T and select-window is invoked on same window as
diff --git a/cmd-send-keys.c b/cmd-send-keys.c
index 7a4d97d..fb38d00 100644
--- a/cmd-send-keys.c
+++ b/cmd-send-keys.c
@@ -28,21 +28,24 @@
  */
 
 enum cmd_retval         cmd_send_keys_exec(struct cmd *, struct cmd_q *);
+void            cmd_send_keys_prepare(struct cmd *, struct cmd_q *);
 
 const struct cmd_entry cmd_send_keys_entry = {
        "send-keys", "send",
        "lRt:", 0, -1,
        "[-lR] " CMD_TARGET_PANE_USAGE " key ...",
-       0,
-       cmd_send_keys_exec
+       CMD_PREPAREPANE,
+       cmd_send_keys_exec,
+       NULL
 };
 
 const struct cmd_entry cmd_send_prefix_entry = {
        "send-prefix", NULL,
        "2t:", 0, 0,
        "[-2] " CMD_TARGET_PANE_USAGE,
-       0,
-       cmd_send_keys_exec
+       CMD_PREPAREPANE,
+       cmd_send_keys_exec,
+       NULL
 };
 
 enum cmd_retval
@@ -55,8 +58,10 @@ cmd_send_keys_exec(struct cmd *self, struct cmd_q *cmdq)
        const u_char            *str;
        int                      i, key;
 
-       if (cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp) == NULL)
+       if (cmdq->state.wl == NULL)
                return (CMD_RETURN_ERROR);
+       s = cmdq->state.s;
+       wp = cmdq->state.wp;
 
        if (self->entry == &cmd_send_prefix_entry) {
                if (args_has(args, '2'))
diff --git a/cmd-set-buffer.c b/cmd-set-buffer.c
index 0ec362b..afa7069 100644
--- a/cmd-set-buffer.c
+++ b/cmd-set-buffer.c
@@ -34,7 +34,8 @@ const struct cmd_entry cmd_set_buffer_entry = {
        "ab:n:", 0, 1,
        "[-a] " CMD_BUFFER_USAGE " [-n new-buffer-name] data",
        0,
-       cmd_set_buffer_exec
+       cmd_set_buffer_exec,
+       NULL
 };
 
 enum cmd_retval
diff --git a/cmd-set-environment.c b/cmd-set-environment.c
index 83e63b4..bf65a3f 100644
--- a/cmd-set-environment.c
+++ b/cmd-set-environment.c
@@ -28,13 +28,15 @@
  */
 
 enum cmd_retval         cmd_set_environment_exec(struct cmd *, struct cmd_q *);
+void            cmd_set_environment_prepare(struct cmd *, struct cmd_q *);
 
 const struct cmd_entry cmd_set_environment_entry = {
        "set-environment", "setenv",
        "grt:u", 1, 2,
        "[-gru] " CMD_TARGET_SESSION_USAGE " name [value]",
-       0,
-       cmd_set_environment_exec
+       CMD_PREPARESESSION,
+       cmd_set_environment_exec,
+       NULL
 };
 
 enum cmd_retval
@@ -63,7 +65,7 @@ cmd_set_environment_exec(struct cmd *self, struct cmd_q *cmdq)
        if (args_has(self->args, 'g'))
                env = &global_environ;
        else {
-               if ((s = cmd_find_session(cmdq, args_get(args, 't'), 0)) == 
NULL)
+               if ((s = cmdq->state.s) == NULL)
                        return (CMD_RETURN_ERROR);
                env = &s->environ;
        }
diff --git a/cmd-set-hook.c b/cmd-set-hook.c
index b602933..bdf4540 100644
--- a/cmd-set-hook.c
+++ b/cmd-set-hook.c
@@ -34,9 +34,10 @@ const struct cmd_entry cmd_set_hook_entry = {
        "set-hook", NULL,
        "gt:u", 1, 2,
        "[-gu]" CMD_TARGET_SESSION_USAGE " hook-name [command]",
-       0,
+       CMD_PREPARESESSION,
        NULL,
        cmd_set_hook_exec,
+       NULL
 };
 
 enum cmd_retval
@@ -50,7 +51,7 @@ cmd_set_hook_exec(struct cmd *self, struct cmd_q *cmdq)
        char            *cause;
        const char      *name, *cmd;
 
-       if ((s = cmd_find_session(cmdq, args_get(args, 't'), 0)) == NULL)
+       if ((s = cmdq->state.s) == NULL)
                return (CMD_RETURN_ERROR);
        hooks = args_has(args, 'g') ? &global_hooks : &s->hooks;
 
diff --git a/cmd-set-option.c b/cmd-set-option.c
index 01d691d..6bc0e56 100644
--- a/cmd-set-option.c
+++ b/cmd-set-option.c
@@ -69,7 +69,8 @@ const struct cmd_entry cmd_set_option_entry = {
        "agoqst:uw", 1, 2,
        "[-agosquw] [-t target-session|target-window] option [value]",
        0,
-       cmd_set_option_exec
+       cmd_set_option_exec,
+       NULL
 };
 
 const struct cmd_entry cmd_set_window_option_entry = {
@@ -77,7 +78,8 @@ const struct cmd_entry cmd_set_window_option_entry = {
        "agoqt:u", 1, 2,
        "[-agoqu] " CMD_TARGET_WINDOW_USAGE " option [value]",
        0,
-       cmd_set_option_exec
+       cmd_set_option_exec,
+       NULL
 };
 
 enum cmd_retval
diff --git a/cmd-show-environment.c b/cmd-show-environment.c
index 7737752..e5bacd6 100644
--- a/cmd-show-environment.c
+++ b/cmd-show-environment.c
@@ -28,13 +28,15 @@
  */
 
 enum cmd_retval         cmd_show_environment_exec(struct cmd *, struct cmd_q 
*);
+void            cmd_show_environment_prepare(struct cmd *, struct cmd_q *);
 
 const struct cmd_entry cmd_show_environment_entry = {
        "show-environment", "showenv",
        "gt:", 0, 1,
        "[-g] " CMD_TARGET_SESSION_USAGE " [name]",
-       0,
-       cmd_show_environment_exec
+       CMD_PREPARESESSION,
+       cmd_show_environment_exec,
+       NULL
 };
 
 enum cmd_retval
@@ -48,7 +50,7 @@ cmd_show_environment_exec(struct cmd *self, struct cmd_q 
*cmdq)
        if (args_has(self->args, 'g'))
                env = &global_environ;
        else {
-               if ((s = cmd_find_session(cmdq, args_get(args, 't'), 0)) == 
NULL)
+               if ((s = cmdq->state.s) == NULL)
                        return (CMD_RETURN_ERROR);
                env = &s->environ;
        }
diff --git a/cmd-show-hooks.c b/cmd-show-hooks.c
index 384e664..ea14631 100644
--- a/cmd-show-hooks.c
+++ b/cmd-show-hooks.c
@@ -34,9 +34,10 @@ const struct cmd_entry cmd_show_hooks_entry = {
        "show-hooks", NULL,
        "gt:", 0, 1,
        "[-g] " CMD_TARGET_SESSION_USAGE,
-       0,
+       CMD_PREPARESESSION,
        NULL,
-       cmd_show_hooks_exec
+       cmd_show_hooks_exec,
+       NULL
 };
 
 enum cmd_retval
@@ -49,7 +50,7 @@ cmd_show_hooks_exec(struct cmd *self, struct cmd_q *cmdq)
        char             tmp[BUFSIZ];
        size_t           used;
 
-       if ((s = cmd_find_session(cmdq, args_get(args, 't'), 0)) == NULL)
+       if ((s = cmdq->state.s) == NULL)
                return (CMD_RETURN_ERROR);
        hooks = args_has(args, 'g') ? &global_hooks : &s->hooks;
 
diff --git a/cmd-show-messages.c b/cmd-show-messages.c
index 308668f..b2a669d 100644
--- a/cmd-show-messages.c
+++ b/cmd-show-messages.c
@@ -34,8 +34,11 @@ const struct cmd_entry cmd_show_messages_entry = {
        "show-messages", "showmsgs",
        "IJTt:", 0, 0,
        "[-IJT] " CMD_TARGET_CLIENT_USAGE,
-       0,
-       cmd_show_messages_exec
+       CMD_TARGET_CLIENT_USAGE,
+       CMD_PREPARECLIENT,
+       NULL,
+       cmd_show_messages_exec,
+       NULL
 };
 
 const struct cmd_entry cmd_server_info_entry = {
@@ -123,9 +126,8 @@ cmd_show_messages_jobs(struct cmd_q *cmdq)
 }
 
 enum cmd_retval
-cmd_show_messages_exec(struct cmd *self, struct cmd_q *cmdq)
+cmd_show_messages_exec(unused struct cmd *self, struct cmd_q *cmdq)
 {
-       struct args             *args = self->args;
        struct client           *c;
        struct message_entry    *msg;
        char                    *tim;
@@ -152,7 +154,7 @@ cmd_show_messages_exec(struct cmd *self, struct cmd_q *cmdq)
        if (done)
                return (CMD_RETURN_NORMAL);
 
-       if ((c = cmd_find_client(cmdq, args_get(args, 't'), 0)) == NULL)
+       if ((c = cmdq->state.c) == NULL)
                return (CMD_RETURN_ERROR);
 
        for (i = 0; i < ARRAY_LENGTH(&c->message_log); i++) {
diff --git a/cmd-show-options.c b/cmd-show-options.c
index a5011e7..dc596ca 100644
--- a/cmd-show-options.c
+++ b/cmd-show-options.c
@@ -28,6 +28,7 @@
  */
 
 enum cmd_retval         cmd_show_options_exec(struct cmd *, struct cmd_q *);
+void            cmd_show_options_prepare(struct cmd *, struct cmd_q *);
 
 enum cmd_retval        cmd_show_options_one(struct cmd *, struct cmd_q *,
                    struct options *, int);
@@ -38,8 +39,9 @@ const struct cmd_entry cmd_show_options_entry = {
        "show-options", "show",
        "gqst:vw", 0, 1,
        "[-gqsvw] [-t target-session|target-window] [option]",
-       0,
-       cmd_show_options_exec
+       CMD_PREPARESESSION|CMD_PREPAREWINDOW,
+       cmd_show_options_exec,
+       cmd_show_options_prepare
 };
 
 const struct cmd_entry cmd_show_window_options_entry = {
@@ -47,9 +49,23 @@ const struct cmd_entry cmd_show_window_options_entry = {
        "gvt:", 0, 1,
        "[-gv] " CMD_TARGET_WINDOW_USAGE " [option]",
        0,
-       cmd_show_options_exec
+       cmd_show_options_exec,
+       cmd_show_options_prepare
 };
 
+void
+cmd_show_options_prepare(struct cmd *self, struct cmd_q *cmdq)
+{
+       struct args     *args = self->args;
+
+       if (args_has(args, 'g') && args_has(args, 'w') &&
+           self->entry == &cmd_show_window_options_entry) {
+               cmdq->state.wl = cmd_find_window(cmdq, args_get(args, 't'),
+                   NULL);
+       } else
+               cmdq->state.s = cmd_find_session(cmdq, args_get(args, 't'), 0);
+}
+
 enum cmd_retval
 cmd_show_options_exec(struct cmd *self, struct cmd_q *cmdq)
 {
@@ -69,8 +85,7 @@ cmd_show_options_exec(struct cmd *self, struct cmd_q *cmdq)
                if (args_has(self->args, 'g'))
                        oo = &global_w_options;
                else {
-                       wl = cmd_find_window(cmdq, args_get(args, 't'), NULL);
-                       if (wl == NULL)
+                       if ((wl = cmdq->state.wl) == NULL)
                                return (CMD_RETURN_ERROR);
                        oo = &wl->window->options;
                }
@@ -79,8 +94,7 @@ cmd_show_options_exec(struct cmd *self, struct cmd_q *cmdq)
                if (args_has(self->args, 'g'))
                        oo = &global_s_options;
                else {
-                       s = cmd_find_session(cmdq, args_get(args, 't'), 0);
-                       if (s == NULL)
+                       if ((s = cmdq->state.s) == NULL)
                                return (CMD_RETURN_ERROR);
                        oo = &s->options;
                }
diff --git a/cmd-source-file.c b/cmd-source-file.c
index e5710a0..247e72f 100644
--- a/cmd-source-file.c
+++ b/cmd-source-file.c
@@ -35,7 +35,8 @@ const struct cmd_entry cmd_source_file_entry = {
        "", 1, 1,
        "path",
        0,
-       cmd_source_file_exec
+       cmd_source_file_exec,
+       NULL
 };
 
 enum cmd_retval
diff --git a/cmd-split-window.c b/cmd-split-window.c
index 6b90125..d8ae7af 100644
--- a/cmd-split-window.c
+++ b/cmd-split-window.c
@@ -39,8 +39,9 @@ const struct cmd_entry cmd_split_window_entry = {
        "bc:dF:l:hp:Pt:v", 0, -1,
        "[-bdhvP] [-c start-directory] [-F format] [-p percentage|-l size] "
        CMD_TARGET_PANE_USAGE " [command]",
-       0,
-       cmd_split_window_exec
+       CMD_PREPAREPANE,
+       cmd_split_window_exec,
+       NULL
 };
 
 enum cmd_retval
@@ -62,9 +63,11 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
        struct format_tree      *ft;
        struct environ_entry    *envent;
 
-       if ((wl = cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp)) == NULL)
+       if ((wl = cmdq->state.wl) == NULL)
                return (CMD_RETURN_ERROR);
        w = wl->window;
+       s = cmdq->state.s;
+       wp = cmdq->state.wp;
        server_unzoom_window(w);
 
        environ_init(&env);
diff --git a/cmd-swap-pane.c b/cmd-swap-pane.c
index 918a2e4..75094cb 100644
--- a/cmd-swap-pane.c
+++ b/cmd-swap-pane.c
@@ -32,8 +32,9 @@ const struct cmd_entry cmd_swap_pane_entry = {
        "swap-pane", "swapp",
        "dDs:t:U", 0, 0,
        "[-dDU] " CMD_SRCDST_PANE_USAGE,
-       0,
-       cmd_swap_pane_exec
+       CMD_PREPAREPANE,
+       cmd_swap_pane_exec,
+       NULL
 };
 
 enum cmd_retval
@@ -46,10 +47,10 @@ cmd_swap_pane_exec(struct cmd *self, struct cmd_q *cmdq)
        struct layout_cell      *src_lc, *dst_lc;
        u_int                    sx, sy, xoff, yoff;
 
-       dst_wl = cmd_find_pane(cmdq, args_get(args, 't'), NULL, &dst_wp);
-       if (dst_wl == NULL)
+       if ((dst_wl = cmdq->state.wl) == NULL)
                return (CMD_RETURN_ERROR);
        dst_w = dst_wl->window;
+       dst_wp = cmdq->state.wp;
        server_unzoom_window(dst_w);
 
        if (!args_has(args, 's')) {
diff --git a/cmd-swap-window.c b/cmd-swap-window.c
index 655b910..745b2bf 100644
--- a/cmd-swap-window.c
+++ b/cmd-swap-window.c
@@ -27,31 +27,42 @@
  */
 
 enum cmd_retval        cmd_swap_window_exec(struct cmd *, struct cmd_q *);
+void           cmd_swap_window_prepare(struct cmd *, struct cmd_q *);
 
 const struct cmd_entry cmd_swap_window_entry = {
        "swap-window", "swapw",
        "ds:t:", 0, 0,
        "[-d] " CMD_SRCDST_WINDOW_USAGE,
-       0,
-       cmd_swap_window_exec
+       CMD_PREPAREWINDOW,
+       cmd_swap_window_exec,
+       cmd_swap_window_prepare
 };
 
+void
+cmd_swap_window_prepare(struct cmd *self, struct cmd_q *cmdq)
+{
+       struct args     *args = self->args;
+
+       cmdq->state.wl = cmd_find_window(cmdq, args_get(args, 's'),
+           &cmdq->state.s);
+       cmdq->state.wl2 = cmd_find_window(cmdq, args_get(args, 't'),
+           &cmdq->state.s2);
+}
+
 enum cmd_retval
 cmd_swap_window_exec(struct cmd *self, struct cmd_q *cmdq)
 {
-       struct args             *args = self->args;
-       const char              *target_src, *target_dst;
        struct session          *src, *dst;
        struct session_group    *sg_src, *sg_dst;
        struct winlink          *wl_src, *wl_dst;
        struct window           *w;
 
-       target_src = args_get(args, 's');
-       if ((wl_src = cmd_find_window(cmdq, target_src, &src)) == NULL)
+       if ((wl_src = cmdq->state.wl) == NULL)
                return (CMD_RETURN_ERROR);
-       target_dst = args_get(args, 't');
-       if ((wl_dst = cmd_find_window(cmdq, target_dst, &dst)) == NULL)
+       src = cmdq->state.s;
+       if ((wl_dst = cmdq->state.wl2) == NULL)
                return (CMD_RETURN_ERROR);
+       dst = cmdq->state.s2;
 
        sg_src = session_group_find(src);
        sg_dst = session_group_find(dst);
diff --git a/cmd-switch-client.c b/cmd-switch-client.c
index 439f593..c81b386 100644
--- a/cmd-switch-client.c
+++ b/cmd-switch-client.c
@@ -28,15 +28,26 @@
  */
 
 enum cmd_retval         cmd_switch_client_exec(struct cmd *, struct cmd_q *);
+void            cmd_switch_client_prepare(struct cmd *, struct cmd_q *);
 
 const struct cmd_entry cmd_switch_client_entry = {
        "switch-client", "switchc",
        "lc:npt:r", 0, 0,
        "[-lnpr] [-c target-client] [-t target-session]",
-       CMD_READONLY,
-       cmd_switch_client_exec
+       CMD_READONLY|CMD_PREPARECLIENT|CMD_PREPARESESSION,
+       cmd_switch_client_exec,
+       cmd_switch_client_prepare
 };
 
+void
+cmd_switch_client_prepare(struct cmd *self, struct cmd_q *cmdq)
+{
+       struct args     *args = self->args;
+
+       cmdq->state.c = cmd_find_client(cmdq, args_get(args, 'c'), 0);
+       cmdq->state.s = cmd_find_session(cmdq, args_get(args, 't'), 0);
+}
+
 enum cmd_retval
 cmd_switch_client_exec(struct cmd *self, struct cmd_q *cmdq)
 {
@@ -48,7 +59,7 @@ cmd_switch_client_exec(struct cmd *self, struct cmd_q *cmdq)
        struct window_pane      *wp = NULL;
        const char              *tflag;
 
-       if ((c = cmd_find_client(cmdq, args_get(args, 'c'), 0)) == NULL)
+       if ((c = cmdq->state.c) == NULL)
                return (CMD_RETURN_ERROR);
 
        if (args_has(args, 'r')) {
@@ -102,7 +113,9 @@ cmd_switch_client_exec(struct cmd *self, struct cmd_q *cmdq)
                                window_set_active_pane(wp->window, wp);
                        session_set_current(s, wl);
                }
-       }
+       } else
+               if ((s = cmdq->state.s) == NULL)
+                       return (CMD_RETURN_ERROR);
 
        if (c->session != NULL)
                c->last_session = c->session;
diff --git a/cmd-unbind-key.c b/cmd-unbind-key.c
index 710210c..284c86e 100644
--- a/cmd-unbind-key.c
+++ b/cmd-unbind-key.c
@@ -34,7 +34,8 @@ const struct cmd_entry cmd_unbind_key_entry = {
        "acnt:", 0, 1,
        "[-acn] [-t mode-table] key",
        0,
-       cmd_unbind_key_exec
+       cmd_unbind_key_exec,
+       NULL
 };
 
 enum cmd_retval
diff --git a/cmd-wait-for.c b/cmd-wait-for.c
index a3e8585..c90427d 100644
--- a/cmd-wait-for.c
+++ b/cmd-wait-for.c
@@ -35,7 +35,8 @@ const struct cmd_entry cmd_wait_for_entry = {
        "LSU", 1, 1,
        "[-L|-S|-U] channel",
        0,
-       cmd_wait_for_exec
+       cmd_wait_for_exec,
+       NULL
 };
 
 struct wait_channel {
diff --git a/cmd.c b/cmd.c
index 2b05c5c..54d0e8f 100644
--- a/cmd.c
+++ b/cmd.c
@@ -96,9 +96,11 @@ const struct cmd_entry *cmd_table[] = {
        &cmd_set_buffer_entry,
        &cmd_set_hook_entry,
        &cmd_set_environment_entry,
+       &cmd_set_hook_entry,
        &cmd_set_option_entry,
        &cmd_set_window_option_entry,
        &cmd_show_buffer_entry,
+       &cmd_show_hooks_entry,
        &cmd_show_environment_entry,
        &cmd_show_hooks_entry,
        &cmd_show_messages_entry,
@@ -314,6 +316,28 @@ usage:
        return (NULL);
 }
 
+void
+cmd_prepare(struct cmd *cmd, struct cmd_q *cmdq)
+{
+       struct args             *args = cmd->args;
+       const char              *tflag = args_get(args, 't');
+       struct cmd_state        *state = &cmdq->state;
+
+       cmdq->state.c = cmd_current_client(cmdq);
+
+       if (cmd->entry->flags & CMD_PREPARESESSION)
+               state->s = cmd_find_session(cmdq, tflag, 1);
+       if (cmd->entry->flags & CMD_PREPAREWINDOW)
+               state->wl = cmd_find_window(cmdq, tflag, NULL);
+       if (cmd->entry->flags & CMD_PREPAREPANE)
+               state->wl = cmd_find_pane(cmdq, tflag, &state->s, &state->wp);
+       if (cmd->entry->flags & CMD_PREPARECLIENT)
+               state->c = cmd_find_client(cmdq, tflag, 0);
+
+       if (cmd->entry->prepare != NULL)
+               cmd->entry->prepare(cmd, cmdq);
+}
+
 size_t
 cmd_print(struct cmd *cmd, char *buf, size_t len)
 {
diff --git a/tmux.h b/tmux.h
index 875894c..79216fc 100644
--- a/tmux.h
+++ b/tmux.h
@@ -1359,6 +1359,25 @@ struct args {
        char                    **argv;
 };
 
+/* Context for a command about to be executed. */
+struct cmd_state {
+       struct client           *c;
+
+       struct session          *s;
+       struct session          *s2;
+
+       struct winlink          *wl;
+       struct winlink          *wl2;
+
+       struct window           *w;
+       struct window           *w2;
+
+       struct window_pane      *wp;
+       struct window_pane      *wp2;
+
+       int                      idx;
+};
+
 /* Command and list of commands. */
 struct cmd {
        const struct cmd_entry  *entry;
@@ -1403,6 +1422,7 @@ struct cmd_q {
        struct cmd_q_items       queue;
        struct cmd_q_item       *item;
        struct cmd              *cmd;
+       struct cmd_state         state;
 
        time_t                   time;
        u_int                    number;
@@ -1427,9 +1447,14 @@ struct cmd_entry {
 #define CMD_STARTSERVER 0x1
 #define CMD_CANTNEST 0x2
 #define CMD_READONLY 0x4
+#define CMD_PREPARESESSION 0x8
+#define CMD_PREPAREWINDOW 0x10
+#define CMD_PREPAREPANE 0x20
+#define CMD_PREPARECLIENT 0x40
        int              flags;
 
        enum cmd_retval  (*exec)(struct cmd *, struct cmd_q *);
+       void             (*prepare)(struct cmd *, struct cmd_q *);
 };
 
 /* Key binding. */
@@ -1737,6 +1762,7 @@ char             **cmd_copy_argv(int, char **);
 void            cmd_free_argv(int, char **);
 char           *cmd_stringify_argv(int, char **);
 struct cmd     *cmd_parse(int, char **, const char *, u_int, char **);
+void            cmd_prepare(struct cmd *, struct cmd_q *);
 size_t          cmd_print(struct cmd *, char *, size_t);
 struct session *cmd_current_session(struct cmd_q *, int);
 struct client  *cmd_current_client(struct cmd_q *);
@@ -1842,8 +1868,7 @@ extern const struct cmd_entry cmd_up_pane_entry;
 extern const struct cmd_entry cmd_wait_for_entry;
 
 /* cmd-attach-session.c */
-enum cmd_retval         cmd_attach_session(struct cmd_q *, const char *, int, 
int,
-                    const char *);
+enum cmd_retval         cmd_attach_session(struct cmd_q *, int, int, const 
char *);
 
 /* cmd-list.c */
 struct cmd_list        *cmd_list_parse(int, char **, const char *, u_int, char 
**);


commit 2103ae2e24a53668f9ca003d2b28f6f3c1eaa02f
Author: Nicholas Marriott <nicholas.marri...@gmail.com>
Commit: Thomas Adam <tho...@xteddy.org>

    Infrastructure for hooks - structures and the set-hook and show-hook 
commands.
---
 Makefile.am      |    3 +
 cmd-set-hook.c   |   93 ++++++++++++++++++++++++++++++++++++++++++++++
 cmd-show-hooks.c |   63 +++++++++++++++++++++++++++++++
 cmd.c            |    2 +
 hooks.c          |  109 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 session.c        |    2 +
 tmux.c           |    2 +
 tmux.h           |   27 +++++++++++++
 8 files changed, 301 insertions(+), 0 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index 82469e4..237cee9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -118,8 +118,10 @@ 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-hooks.c \
        cmd-show-messages.c \
        cmd-show-options.c \
        cmd-source-file.c \
@@ -139,6 +141,7 @@ dist_tmux_SOURCES = \
        grid-cell.c \
        grid-view.c \
        grid.c \
+       hooks.c \
        input-keys.c \
        input.c \
        job.c \
diff --git a/cmd-set-hook.c b/cmd-set-hook.c
new file mode 100644
index 0000000..b602933
--- /dev/null
+++ b/cmd-set-hook.c
@@ -0,0 +1,93 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 2012 Thomas Adam <tho...@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 a global or session hook.
+ */
+
+enum cmd_retval cmd_set_hook_exec(struct cmd *, struct cmd_q *);
+void           cmd_set_hook_prepare(struct cmd *, struct cmd_q *);
+
+const struct cmd_entry cmd_set_hook_entry = {
+       "set-hook", NULL,
+       "gt:u", 1, 2,
+       "[-gu]" CMD_TARGET_SESSION_USAGE " hook-name [command]",
+       0,
+       NULL,
+       cmd_set_hook_exec,
+};
+
+enum cmd_retval
+cmd_set_hook_exec(struct cmd *self, struct cmd_q *cmdq)
+{
+       struct args     *args = self->args;
+       struct session  *s;
+       struct cmd_list *cmdlist;
+       struct hooks    *hooks;
+       struct hook     *hook;
+       char            *cause;
+       const char      *name, *cmd;
+
+       if ((s = cmd_find_session(cmdq, args_get(args, 't'), 0)) == NULL)
+               return (CMD_RETURN_ERROR);
+       hooks = args_has(args, 'g') ? &global_hooks : &s->hooks;
+
+       name = args->argv[0];
+       if (*name == '\0') {
+               cmdq_error(cmdq, "invalid hook name");
+               return (CMD_RETURN_ERROR);
+       }
+       if (args->argc < 2)
+               cmd = NULL;
+       else
+               cmd = args->argv[1];
+
+       if (args_has(args, 'u')) {
+               if (cmd != NULL) {
+                       cmdq_error(cmdq, "command passed to unset hook: %s",
+                           name);
+                       return (CMD_RETURN_ERROR);
+               }
+               if ((hook = hooks_find(hooks, name)) != NULL)
+                       hooks_remove(hooks, hook);
+               return (CMD_RETURN_NORMAL);
+       }
+
+       if (cmd == NULL) {
+               cmdq_error(cmdq, "no command to set hook: %s", name);
+               return (CMD_RETURN_ERROR);
+       }
+       if (cmd_string_parse(cmd, &cmdlist, NULL, 0, &cause) != 0) {
+               if (cause != NULL) {
+                       cmdq_error(cmdq, "%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-show-hooks.c b/cmd-show-hooks.c
new file mode 100644
index 0000000..384e664
--- /dev/null
+++ b/cmd-show-hooks.c
@@ -0,0 +1,63 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 2012 Thomas Adam <tho...@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"
+
+/*
+ * Show global or session hooks.
+ */
+
+enum cmd_retval cmd_show_hooks_exec(struct cmd *, struct cmd_q *);
+void           cmd_show_hooks_prepare(struct cmd *, struct cmd_q *);
+
+const struct cmd_entry cmd_show_hooks_entry = {
+       "show-hooks", NULL,
+       "gt:", 0, 1,
+       "[-g] " CMD_TARGET_SESSION_USAGE,
+       0,
+       NULL,
+       cmd_show_hooks_exec
+};
+
+enum cmd_retval
+cmd_show_hooks_exec(struct cmd *self, struct cmd_q *cmdq)
+{
+       struct args     *args = self->args;
+       struct session  *s;
+       struct hooks    *hooks;
+       struct hook     *hook;
+       char             tmp[BUFSIZ];
+       size_t           used;
+
+       if ((s = cmd_find_session(cmdq, args_get(args, 't'), 0)) == NULL)
+               return (CMD_RETURN_ERROR);
+       hooks = args_has(args, 'g') ? &global_hooks : &s->hooks;
+
+       RB_FOREACH(hook, hooks_tree, &hooks->tree) {
+               used = xsnprintf(tmp, sizeof tmp, "%s -> ", hook->name);
+               cmd_list_print(hook->cmdlist, tmp + used, (sizeof tmp) - used);
+               cmdq_print(cmdq, "%s", tmp);
+       }
+
+       return (CMD_RETURN_NORMAL);
+}
diff --git a/cmd.c b/cmd.c
index eeffe4c..2b05c5c 100644
--- a/cmd.c
+++ b/cmd.c
@@ -94,11 +94,13 @@ const struct cmd_entry *cmd_table[] = {
        &cmd_send_prefix_entry,
        &cmd_server_info_entry,
        &cmd_set_buffer_entry,
+       &cmd_set_hook_entry,
        &cmd_set_environment_entry,
        &cmd_set_option_entry,
        &cmd_set_window_option_entry,
        &cmd_show_buffer_entry,
        &cmd_show_environment_entry,
+       &cmd_show_hooks_entry,
        &cmd_show_messages_entry,
        &cmd_show_options_entry,
        &cmd_show_window_options_entry,
diff --git a/hooks.c b/hooks.c
new file mode 100644
index 0000000..7157eef
--- /dev/null
+++ b/hooks.c
@@ -0,0 +1,109 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 2012 Thomas Adam <tho...@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"
+
+RB_GENERATE(hooks_tree, hook, entry, hooks_cmp);
+
+struct hook    *hooks_find1(struct hooks *, const char *);
+
+int
+hooks_cmp(struct hook *hook1, struct hook *hook2)
+{
+       return (strcmp(hook1->name, hook2->name));
+}
+
+void
+hooks_init(struct hooks *hooks, struct hooks *parent)
+{
+       RB_INIT(&hooks->tree);
+       hooks->parent = parent;
+}
+
+void
+hooks_free(struct hooks *hooks)
+{
+       struct hook     *hook, *hook1;
+
+       RB_FOREACH_SAFE(hook, hooks_tree, &hooks->tree, hook1)
+               hooks_remove(hooks, 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_remove(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, struct hook *hook)
+{
+       RB_REMOVE(hooks_tree, &hooks->tree, hook);
+       cmd_list_free(hook->cmdlist);
+       free((char *) hook->name);
+       free(hook);
+}
+
+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_run(struct hook *hook, struct cmd_q *cmdq)
+{
+       struct cmd      *cmd;
+
+       TAILQ_FOREACH(cmd, &hook->cmdlist->list, qentry)
+               cmd->entry->exec(cmd, cmdq);
+}
diff --git a/session.c b/session.c
index 3ac9fb2..4453164 100644
--- a/session.c
+++ b/session.c
@@ -105,6 +105,7 @@ session_create(const char *name, int argc, char **argv, 
const char *path,
        TAILQ_INIT(&s->lastw);
        RB_INIT(&s->windows);
 
+       hooks_init(&s->hooks, &global_hooks);
        options_init(&s->options, &global_s_options);
        environ_init(&s->environ);
        if (env != NULL)
@@ -163,6 +164,7 @@ session_destroy(struct session *s)
        session_group_remove(s);
        environ_free(&s->environ);
        options_free(&s->options);
+       hooks_free(&s->hooks);
 
        while (!TAILQ_EMPTY(&s->lastw))
                winlink_stack_remove(&s->lastw, TAILQ_FIRST(&s->lastw));
diff --git a/tmux.c b/tmux.c
index 5a1988e..36ca7a8 100644
--- a/tmux.c
+++ b/tmux.c
@@ -39,6 +39,7 @@ 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 event_base *ev_base;
 
@@ -289,6 +290,7 @@ main(int argc, char **argv)
                        flags |= CLIENT_UTF8;
        }
 
+       hooks_init(&global_hooks, NULL);
        environ_init(&global_environ);
        for (var = environ; *var != NULL; var++)
                environ_put(&global_environ, *var);
diff --git a/tmux.h b/tmux.h
index 61f2ca7..875894c 100644
--- a/tmux.h
+++ b/tmux.h
@@ -1026,6 +1026,18 @@ struct environ_entry {
 };
 RB_HEAD(environ, environ_entry);
 
+/* Hooks. */
+struct hook {
+       const char      *name;
+       struct cmd_list *cmdlist;
+       RB_ENTRY(hook)   entry;
+};
+
+struct hooks {
+       RB_HEAD(hooks_tree, hook) tree;
+       struct hooks    *parent;
+};
+
 /* Client session. */
 struct session_group {
        TAILQ_HEAD(, session) sessions;
@@ -1051,6 +1063,7 @@ struct session {
        struct winlink_stack lastw;
        struct winlinks  windows;
 
+       struct hooks     hooks;
        struct options   options;
 
 #define SESSION_UNATTACHED 0x1 /* not attached to any clients */
@@ -1471,6 +1484,7 @@ struct options_table_entry {
 #define CMD_BUFFER_USAGE "[-b buffer-name]"
 
 /* tmux.c */
+extern struct hooks   global_hooks;
 extern struct options global_options;
 extern struct options global_s_options;
 extern struct options global_w_options;
@@ -1519,6 +1533,17 @@ void              format_window_pane(struct format_tree 
*,
 void            format_paste_buffer(struct format_tree *,
                     struct paste_buffer *, int);
 
+/* hooks.c */
+int             hooks_cmp(struct hook *, struct hook *);
+RB_PROTOTYPE(hooks_tree, hook, entry, hooks_cmp);
+void            hooks_init(struct hooks *, struct hooks *);
+void            hooks_free(struct hooks *);
+void            hooks_add(struct hooks *, const char *, struct cmd_list *);
+void            hooks_copy(struct hooks *, struct hooks *);
+void            hooks_remove(struct hooks *, struct hook *);
+void            hooks_run(struct hook *, struct cmd_q *);
+struct hook    *hooks_find(struct hooks *, const char *);
+
 /* mode-key.c */
 extern const struct mode_key_table mode_key_tables[];
 extern struct mode_key_tree mode_key_tree_vi_edit;
@@ -1795,10 +1820,12 @@ extern const struct cmd_entry cmd_send_prefix_entry;
 extern const struct cmd_entry cmd_server_info_entry;
 extern const struct cmd_entry cmd_set_buffer_entry;
 extern const struct cmd_entry cmd_set_environment_entry;
+extern const struct cmd_entry cmd_set_hook_entry;
 extern const struct cmd_entry cmd_set_option_entry;
 extern const struct cmd_entry cmd_set_window_option_entry;
 extern const struct cmd_entry cmd_show_buffer_entry;
 extern const struct cmd_entry cmd_show_environment_entry;
+extern const struct cmd_entry cmd_show_hooks_entry;
 extern const struct cmd_entry cmd_show_messages_entry;
 extern const struct cmd_entry cmd_show_options_entry;
 extern const struct cmd_entry cmd_show_window_options_entry;


-----------------------------------------------------------------------

Summary of changes:
 cmd-if-shell.c  |   31 ++++++++++++++++++---
 format.c        |   80 ++++++++++++++++++++++++++++++++++++++++++++----------
 grid-view.c     |    7 +++--
 log.c           |    2 +-
 tmux.1          |   34 +++++++++++++++++++----
 tmux.h          |   15 +---------
 window-choose.c |   30 --------------------
 7 files changed, 125 insertions(+), 74 deletions(-)


hooks/post-receive
-- 
tmux

------------------------------------------------------------------------------
Dive into the World of Parallel Programming! The Go Parallel Website,
sponsored by Intel and developed in partnership with Slashdot Media, is your
hub for all things parallel software development, from weekly thought
leadership blogs to news, videos, case studies, tutorials and more. Take a
look and join the conversation now. http://goparallel.sourceforge.net
_______________________________________________
tmux-cvs mailing list
tmux-cvs@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tmux-cvs

Reply via email to