The branch, ta/hooks-nm has been created at 8b7a0304587d70aed1f83fde7c68cd1406ee0b30 (commit)
- Log ----------------------------------------------------------------- commit 8b7a0304587d70aed1f83fde7c68cd1406ee0b30 Author: Thomas Adam <tho...@xteddy.org> Commit: Thomas Adam <tho...@xteddy.org> Convert kill-session --- 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 86ff13abcbf3cac35749db1e0c512db4c9926d90 Author: Thomas Adam <tho...@xteddy.org> Commit: Thomas Adam <tho...@xteddy.org> Check t/s as appropriate * If there's no client, set the -t/-s error flags only if -t/-s needed; * Don't call exec if -t/-s fails. --- cmd-list-windows.c | 3 --- cmd-queue.c | 5 ++++- cmd.c | 13 +++++++------ 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/cmd-list-windows.c b/cmd-list-windows.c index d780c24..3c1277c 100644 --- a/cmd-list-windows.c +++ b/cmd-list-windows.c @@ -58,9 +58,6 @@ cmd_list_windows_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; - if (cmdq->state.tflag.error) - return (CMD_RETURN_ERROR); - if (args_has(args, 'a')) cmd_list_windows_server(self, cmdq); else diff --git a/cmd-queue.c b/cmd-queue.c index ff3de07..fb8eeaa 100644 --- a/cmd-queue.c +++ b/cmd-queue.c @@ -220,13 +220,16 @@ 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); + /* * 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... */ - cmdq_run_hook(hooks, "before", cmdq->cmd, cmdq); 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) diff --git a/cmd.c b/cmd.c index abf54d8..13cef41 100644 --- a/cmd.c +++ b/cmd.c @@ -486,8 +486,6 @@ cmd_prepare_state(struct cmd *cmd, struct cmd_q *cmdq) state->c = cmd_get_state_client(cmdq); else state->c = cmd_find_client(cmdq, cflag, 0); - if (state->c == NULL) - state->tflag.error = state->sflag.error = 1; break; case CMD_PREP_CLIENT_T: tflag = args_get(args, 't'); @@ -495,14 +493,17 @@ cmd_prepare_state(struct cmd *cmd, struct cmd_q *cmdq) state->c = cmd_get_state_client(cmdq); else state->c = cmd_find_client(cmdq, tflag, 0); - if (state->c == NULL) - state->tflag.error = state->sflag.error = 1; break; default: log_fatalx("both -c and -t for %s", cmd->entry->name); } - if (state->c == NULL) + 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, @@ -514,7 +515,7 @@ cmd_prepare_state(struct cmd *cmd, struct cmd_q *cmdq) else cmd_set_state_tflag(cmd, cmdq, 0); sflag = args_get(args, 's'); - if (sflag == NULL && (cmd->entry->flags & CMD_PREP_ALL_T) != 0) + 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); commit 43dcea36b0af7f375b3b5bb7a13f459173c96b28 Author: Thomas Adam <tho...@xteddy.org> Commit: Thomas Adam <tho...@xteddy.org> WIP from NM --- cmd-list-windows.c | 14 ++--- cmd-queue.c | 46 +++----------- cmd.c | 176 ++++++++++++++++++++++++++++++++++++++++++++++------ hooks.c | 2 +- tmux.h | 11 ++-- 5 files changed, 179 insertions(+), 70 deletions(-) diff --git a/cmd-list-windows.c b/cmd-list-windows.c index 579a29b..d780c24 100644 --- a/cmd-list-windows.c +++ b/cmd-list-windows.c @@ -57,16 +57,14 @@ enum cmd_retval cmd_list_windows_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; - struct session *s; + + if (cmdq->state.tflag.error) + return (CMD_RETURN_ERROR); 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 +84,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..ff3de07 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) @@ -250,13 +220,17 @@ cmdq_continue(struct cmd_q *cmdq) flags = !!(cmdq->cmd->flags & CMD_CONTROL); guard = cmdq_guard(cmdq, "begin", flags); + /* + * 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... + */ cmdq_run_hook(hooks, "before", cmdq->cmd, cmdq); + cmd_prepare_state(cmdq->cmd, cmdq); - cmdq_set_state(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) { diff --git a/cmd.c b/cmd.c index aa0b6ca..abf54d8 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,71 +319,205 @@ 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); } - sflag = args_get(args, 't'); - if (sflag == NULL) - sflag = state->sflag.prior; + 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; + 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 (!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 (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 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); + if (state->c == NULL) + state->tflag.error = state->sflag.error = 1; + 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); + if (state->c == NULL) + state->tflag.error = state->sflag.error = 1; + break; + default: + log_fatalx("both -c and -t for %s", cmd->entry->name); } + if (state->c == NULL) + 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_T) != 0) + cmd_set_state_sflag(cmdq->cmd, cmdq, 1); + else + cmd_set_state_sflag(cmd, cmdq, 0); } size_t 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 *); ----------------------------------------------------------------------- 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