The branch, hooks has been updated
       via  d60e4b1eaf027e9e5d824442b65e1b538ab16cd6 (commit)
       via  e18db499c832a344a08116fca10f1fb544a09197 (commit)
      from  2e7210c43e57c20d90eda5e26d248a04123ba3ef (commit)

- Log -----------------------------------------------------------------
commit d60e4b1eaf027e9e5d824442b65e1b538ab16cd6
Author: Nicholas Marriott <[email protected]>
Commit: Nicholas Marriott <[email protected]>

    Convert kill-session to use prepare flags.
---
 cmd-kill-session.c |   16 +++++++---------
 1 files changed, 7 insertions(+), 9 deletions(-)

diff --git a/cmd-kill-session.c b/cmd-kill-session.c
index d7e2a21..1bbba41 100644
--- a/cmd-kill-session.c
+++ b/cmd-kill-session.c
@@ -33,7 +33,7 @@ const struct cmd_entry cmd_kill_session_entry = {
        "kill-session", NULL,
        "at:", 0, 0,
        "[-a] " CMD_TARGET_SESSION_USAGE,
-       0,
+       CMD_PREP_SESSION_T,
        cmd_kill_session_exec
 };
 
@@ -41,16 +41,14 @@ enum cmd_retval
 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)
-               return (CMD_RETURN_ERROR);
+       struct session  *s, *sloop, *stmp;
 
+       s = cmdq->state.tflag.s;
        if (args_has(args, 'a')) {
-               RB_FOREACH_SAFE(s2, sessions, &sessions, s3) {
-                       if (s != s2) {
-                               server_destroy_session(s2);
-                               session_destroy(s2);
+               RB_FOREACH_SAFE(sloop, sessions, &sessions, stmp) {
+                       if (sloop != s) {
+                               server_destroy_session(sloop);
+                               session_destroy(sloop);
                        }
                }
        } else {


commit e18db499c832a344a08116fca10f1fb544a09197
Author: Nicholas Marriott <[email protected]>
Commit: Nicholas Marriott <[email protected]>

    Look up -t and -s in the hooked command if the hook wants one but doesn't
    provide it. Also fail quickly on error.
---
 cmd-list-windows.c |   11 +---
 cmd-queue.c        |   49 ++++-----------
 cmd.c              |  177 ++++++++++++++++++++++++++++++++++++++++++++++------
 hooks.c            |    2 +-
 tmux.h             |   11 ++--
 5 files changed, 180 insertions(+), 70 deletions(-)

diff --git a/cmd-list-windows.c b/cmd-list-windows.c
index 579a29b..3c1277c 100644
--- a/cmd-list-windows.c
+++ b/cmd-list-windows.c
@@ -57,16 +57,11 @@ enum cmd_retval
 cmd_list_windows_exec(struct cmd *self, struct cmd_q *cmdq)
 {
        struct args     *args = self->args;
-       struct session  *s;
 
        if (args_has(args, 'a'))
                cmd_list_windows_server(self, cmdq);
-       else {
-               s = cmdq->state.tflag.s;
-               if (s == NULL)
-                       return (CMD_RETURN_ERROR);
-               cmd_list_windows_session(self, s, cmdq, 0);
-       }
+       else
+               cmd_list_windows_session(self, cmdq->state.tflag.s, cmdq, 0);
 
        return (CMD_RETURN_NORMAL);
 }
@@ -86,7 +81,7 @@ cmd_list_windows_session(struct cmd *self, struct session *s,
 {
        struct args             *args = self->args;
        struct winlink          *wl;
-       u_int                   n;
+       u_int                    n;
        struct format_tree      *ft;
        const char              *template;
        char                    *line;
diff --git a/cmd-queue.c b/cmd-queue.c
index 1a6d4a5..fb8eeaa 100644
--- a/cmd-queue.c
+++ b/cmd-queue.c
@@ -25,37 +25,9 @@
 
 #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)
-{
-       struct cmd_state        *state = &cmdq->state;
-       struct session          *s;
-
-       s = cmd_current_session(cmdq, 0);
-
-       state->c = cmdq->client;
-
-       state->tflag.s = s;
-       state->tflag.wl = NULL;
-       state->tflag.wp = NULL;
-       state->tflag.idx = -1;
-       state->tflag.prior = args_get(cmdq->cmd->args, 't');
-
-       state->sflag.s = s;
-       state->sflag.wl = NULL;
-       state->sflag.wp = NULL;
-       state->sflag.idx = -1;
-       state->sflag.prior = args_get(cmdq->cmd->args, 's');
-
-       cmd_prepare(cmdq->cmd, cmdq);
-
-}
-
 /* Create new command queue. */
 struct cmd_q *
 cmdq_new(struct client *c)
@@ -227,12 +199,10 @@ cmdq_continue(struct cmd_q *cmdq)
 
        do {
                while (cmdq->cmd != NULL) {
-                       /*
-                        * Set the execution context for this command.  This
-                        * then allows for session hooks to be used if this
-                        * command has any.
-                        */
-                       cmdq_set_state(cmdq);
+                       cmd_prepare_state(cmdq->cmd, cmdq);
+                       if (cmdq->state.tflag.error || cmdq->state.sflag.error)
+                               break;
+
                        if (cmdq->state.tflag.s != NULL)
                                hooks = &cmdq->state.tflag.s->hooks;
                        else if (cmdq->state.sflag.s != NULL)
@@ -252,11 +222,18 @@ cmdq_continue(struct cmd_q *cmdq)
 
                        cmdq_run_hook(hooks, "before", cmdq->cmd, cmdq);
 
-                       cmdq_set_state(cmdq);
+                       /*
+                        * hooks_run will change the state before each hook, so
+                        * it needs to be restored afterwards. XXX not very
+                        * obvious how this works from here...
+                        */
+                       cmd_prepare_state(cmdq->cmd, cmdq);
+                       if (cmdq->state.tflag.error || cmdq->state.sflag.error)
+                               break;
+
                        retval = cmdq->cmd->entry->exec(cmdq->cmd, cmdq);
                        if (retval == CMD_RETURN_ERROR)
                                break;
-
                        cmdq_run_hook(hooks, "after", cmdq->cmd, cmdq);
 
                        if (guard) {
diff --git a/cmd.c b/cmd.c
index aa0b6ca..13cef41 100644
--- a/cmd.c
+++ b/cmd.c
@@ -117,6 +117,10 @@ const struct cmd_entry *cmd_table[] = {
        NULL
 };
 
+void            cmd_clear_state(struct cmd_state *);
+struct client  *cmd_get_state_client(struct cmd_q *);
+void            cmd_set_state_tflag(struct cmd *, struct cmd_q *, int);
+void            cmd_set_state_sflag(struct cmd *, struct cmd_q *, int);
 int             cmd_session_better(struct session *, struct session *, int);
 struct session *cmd_choose_session_list(struct sessionslist *);
 struct session *cmd_choose_session(int);
@@ -315,73 +319,208 @@ usage:
 }
 
 void
-cmd_prepare(struct cmd *cmd, struct cmd_q *cmdq)
+cmd_clear_state(struct cmd_state *state)
+{
+       state->c = NULL;
+
+       state->tflag.error = 0;
+       state->tflag.s = NULL;
+       state->tflag.wl = NULL;
+       state->tflag.wp = NULL;
+       state->tflag.idx = -1;
+
+       state->sflag.error = 0;
+       state->sflag.s = NULL;
+       state->sflag.wl = NULL;
+       state->sflag.wp = NULL;
+       state->sflag.idx = -1;
+}
+
+struct client *
+cmd_get_state_client(struct cmd_q *cmdq)
+{
+       struct cmd      *cmd = cmdq->cmd;
+       struct args     *args = cmd->args;
+
+       switch (cmd->entry->flags & (CMD_PREP_CLIENT_C|CMD_PREP_CLIENT_T)) {
+       case 0:
+               return (cmd_current_client(cmdq));
+       case CMD_PREP_CLIENT_C:
+               return (cmd_find_client(cmdq, args_get(args, 'c'), 0));
+       case CMD_PREP_CLIENT_T:
+               return (cmd_find_client(cmdq, args_get(args, 't'), 0));
+       default:
+               log_fatalx("both -t and -c for %s", cmd->entry->name);
+       }
+}
+
+void
+cmd_set_state_tflag(struct cmd *cmd, struct cmd_q *cmdq, int everything)
 {
        struct cmd_state        *state = &cmdq->state;
        struct args             *args = cmd->args;
        const char              *tflag;
-       const char              *sflag;
 
-       /* FIXME:  Handle this!  What should happen during cfg_load? */
-       if (cfg_finished == 0)
+       tflag = args_get(args, 't');
+       if (tflag == NULL && !everything)
                return;
 
-       tflag = args_get(args, 't');
-       if (tflag == NULL)
-               tflag = state->tflag.prior;
        switch (cmd->entry->flags & CMD_PREP_ALL_T) {
        case 0:
                break;
        case CMD_PREP_SESSION_T:
                state->tflag.s = cmd_find_session(cmdq, tflag, 0);
+               if (state->tflag.s == NULL)
+                       state->tflag.error = 1;
                break;
        case CMD_PREP_WINDOW_T:
                state->tflag.wl = cmd_find_window(cmdq, tflag, &state->tflag.s);
+               if (state->tflag.wl == NULL)
+                       state->tflag.error = 1;
                break;
        case CMD_PREP_PANE_T:
                state->tflag.wl = cmd_find_pane(cmdq, tflag, &state->tflag.s,
                    &state->tflag.wp);
-               break;
-       case CMD_PREP_CLIENT_T:
-               state->c = cmd_find_client(cmdq, tflag, 0);
+               if (state->tflag.wl == NULL)
+                       state->tflag.error = 1;
                break;
        case CMD_PREP_INDEX_T:
                state->tflag.idx = cmd_find_index(cmdq, tflag, &state->tflag.s);
+               if (state->tflag.idx == -2)
+                       state->tflag.error = 1;
                break;
        default:
-               log_fatalx("too many -t flags for %s", cmd->entry->name);
+               log_fatalx("too many -t for %s", cmd->entry->name);
+       }
+
+       if (!state->tflag.error && everything) {
+               if (state->tflag.s == NULL)
+                       state->tflag.s = state->c->session;
+               if (state->tflag.wl == NULL)
+                       state->tflag.wl = state->tflag.s->curw;
+               if (state->tflag.wp == NULL)
+                       state->tflag.wp = state->tflag.wl->window->active;
        }
+}
+
+void
+cmd_set_state_sflag(struct cmd *cmd, struct cmd_q *cmdq, int everything)
+{
+       struct cmd_state        *state = &cmdq->state;
+       struct args             *args = cmd->args;
+       const char              *sflag;
+
+       sflag = args_get(args, 's');
+       if (sflag == NULL && !everything)
+               return;
 
-       sflag = args_get(args, 't');
-       if (sflag == NULL)
-               sflag = state->sflag.prior;
        switch (cmd->entry->flags & CMD_PREP_ALL_S) {
        case 0:
                break;
        case CMD_PREP_SESSION_S:
                state->sflag.s = cmd_find_session(cmdq, sflag, 0);
+               if (state->sflag.s == NULL)
+                       state->sflag.error = 1;
                break;
        case CMD_PREP_WINDOW_S:
                state->sflag.wl = cmd_find_window(cmdq, sflag, &state->sflag.s);
+               if (state->sflag.wl == NULL)
+                       state->sflag.error = 1;
                break;
        case CMD_PREP_PANE_S:
                state->sflag.wl = cmd_find_pane(cmdq, sflag, &state->sflag.s,
                    &state->sflag.wp);
+               if (state->sflag.wl == NULL)
+                       state->sflag.error = 1;
                break;
        case CMD_PREP_INDEX_S:
                state->sflag.idx = cmd_find_index(cmdq, sflag, &state->sflag.s);
+               if (state->sflag.idx == -2)
+                       state->sflag.error = 1;
                break;
        default:
-               log_fatalx("too many -s flags for %s", cmd->entry->name);
+               log_fatalx("too many -s for %s", cmd->entry->name);
        }
 
-       if (cmd->entry->flags & CMD_PREP_CLIENT_C) {
-               if (cmd->entry->flags & CMD_PREP_CLIENT_T)
-                       log_fatalx("both -t and -c for %s", cmd->entry->name);
-               state->c = cmd_find_client(cmdq, args_get(args, 'c'), 0);
+       if (!state->sflag.error && everything) {
+               if (state->sflag.s == NULL)
+                       state->sflag.s = state->c->session;
+               if (state->sflag.wl == NULL)
+                       state->sflag.wl = state->sflag.s->curw;
+               if (state->sflag.wp == NULL)
+                       state->sflag.wp = state->sflag.wl->window->active;
        }
 }
 
+void
+cmd_prepare_state(struct cmd *cmd, struct cmd_q *cmdq)
+{
+       struct cmd_state        *state = &cmdq->state;
+       struct args             *args = cmd->args;
+       const char              *cflag;
+       const char              *tflag;
+       const char              *sflag;
+       char                     tmp[BUFSIZ];
+
+       cmd_print(cmd, tmp, sizeof tmp);
+       log_debug("preparing state for: %s (client %p)", tmp, cmdq->client);
+
+       /* Start with an empty state. */
+       cmd_clear_state(state);
+
+       /* FIXME:  Handle this!  What should happen during cfg_load? */
+       if (cfg_finished == 0)
+               return;
+
+       /*
+        * If the command wants a client and provides -c or -t, use it. If not,
+        * try the base command instead via cmd_get_state_client.
+        */
+       switch (cmd->entry->flags & (CMD_PREP_CLIENT_C|CMD_PREP_CLIENT_T)) {
+       case 0:
+               state->c = cmd_get_state_client(cmdq);
+               break;
+       case CMD_PREP_CLIENT_C:
+               cflag = args_get(args, 'c');
+               if (cflag == NULL)
+                       state->c = cmd_get_state_client(cmdq);
+               else
+                       state->c = cmd_find_client(cmdq, cflag, 0);
+               break;
+       case CMD_PREP_CLIENT_T:
+               tflag = args_get(args, 't');
+               if (tflag == NULL)
+                       state->c = cmd_get_state_client(cmdq);
+               else
+                       state->c = cmd_find_client(cmdq, tflag, 0);
+               break;
+       default:
+               log_fatalx("both -c and -t for %s", cmd->entry->name);
+       }
+       if (state->c == NULL) {
+               if ((cmd->entry->flags & CMD_PREP_ALL_T) != 0)
+                       state->tflag.error = 1;
+               if ((cmd->entry->flags & CMD_PREP_ALL_S) != 0)
+                       state->sflag.error = 1;
+               return;
+       }
+
+       /*
+        * If the command wants something for -t and no -t argument is present,
+        * use it the base command's -t instead. Same for -s.
+        */
+       tflag = args_get(args, 't');
+       if (tflag == NULL && (cmd->entry->flags & CMD_PREP_ALL_T) != 0)
+               cmd_set_state_tflag(cmdq->cmd, cmdq, 1);
+       else
+               cmd_set_state_tflag(cmd, cmdq, 0);
+       sflag = args_get(args, 's');
+       if (sflag == NULL && (cmd->entry->flags & CMD_PREP_ALL_S) != 0)
+               cmd_set_state_sflag(cmdq->cmd, cmdq, 1);
+       else
+               cmd_set_state_sflag(cmd, cmdq, 0);
+}
+
 size_t
 cmd_print(struct cmd *cmd, char *buf, size_t len)
 {
diff --git a/hooks.c b/hooks.c
index b187073..5f60dba 100644
--- a/hooks.c
+++ b/hooks.c
@@ -109,8 +109,8 @@ hooks_run(struct hook *hook, struct cmd_q *cmdq)
        log_debug("entering hook %s: %s", hook->name, tmp);
 
        TAILQ_FOREACH(cmd, &hook->cmdlist->list, qentry) {
-               cmd_prepare(cmd, cmdq);
                /* TA:  FIXME:  How do we handle errors here, if at all??? */
+               cmd_prepare_state(cmd, cmdq);
                cmd->entry->exec(cmd, cmdq);
        }
 
diff --git a/tmux.h b/tmux.h
index 372fede..a4281ef 100644
--- a/tmux.h
+++ b/tmux.h
@@ -1365,21 +1365,19 @@ struct cmd_state {
        struct client                   *c;
 
        struct {
+               int                      error;
                struct session          *s;
                struct winlink          *wl;
                struct window_pane      *wp;
                int                      idx;
-
-               const char              *prior;
        } tflag;
 
        struct {
+               int                      error;
                struct session          *s;
                struct winlink          *wl;
                struct window_pane      *wp;
                int                      idx;
-
-               const char              *prior;
        } sflag;
 };
 
@@ -1427,6 +1425,7 @@ struct cmd_q {
        struct cmd_q_items       queue;
        struct cmd_q_item       *item;
        struct cmd              *cmd;
+
        struct cmd_state         state;
 
        time_t                   time;
@@ -1467,7 +1466,7 @@ struct cmd_entry {
        enum cmd_retval  (*exec)(struct cmd *, struct cmd_q *);
 };
 #define CMD_PREP_ALL_T (CMD_PREP_SESSION_T|CMD_PREP_WINDOW_T|CMD_PREP_PANE_T| \
-    CMD_PREP_CLIENT_T|CMD_PREP_INDEX_T)
+    CMD_PREP_INDEX_T)
 #define CMD_PREP_ALL_S (CMD_PREP_SESSION_S|CMD_PREP_WINDOW_S|CMD_PREP_PANE_S| \
     CMD_PREP_INDEX_S)
 
@@ -1776,7 +1775,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 *);
+void            cmd_prepare_state(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 *);


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

Summary of changes:
 cmd-kill-session.c |   16 ++---
 cmd-list-windows.c |   11 +---
 cmd-queue.c        |   49 ++++-----------
 cmd.c              |  177 ++++++++++++++++++++++++++++++++++++++++++++++------
 hooks.c            |    2 +-
 tmux.h             |   11 ++--
 6 files changed, 187 insertions(+), 79 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
[email protected]
https://lists.sourceforge.net/lists/listinfo/tmux-cvs

Reply via email to