From efaf4c16cf9fafa940dfe16ec48ca4ff68082b47 Mon Sep 17 00:00:00 2001 From: nicm Date: Fri, 21 Apr 2017 20:26:34 +0000 Subject: [PATCH] Make the cmd_find_* functions more obvious when looking for a client, rather than having it inside other functions. Should be no change to the way targets are resolved just yet. --- cmd-find.c | 360 +++++++++++++++++++++--------------------------- cmd-queue.c | 9 +- cmd-run-shell.c | 2 +- cmd.c | 32 ++--- notify.c | 11 +- server.c | 4 +- tmux.h | 19 ++- 7 files changed, 188 insertions(+), 249 deletions(-) diff --git a/cmd-find.c b/cmd-find.c index ea8c1e83..098405aa 100644 --- a/cmd-find.c +++ b/cmd-find.c @@ -27,19 +27,12 @@ #include "tmux.h" -static struct session *cmd_find_try_TMUX(struct client *, struct window *); -static int cmd_find_client_better(struct client *, struct client *); -static struct client *cmd_find_best_client(struct client **, u_int); static int cmd_find_session_better(struct session *, struct session *, int); static struct session *cmd_find_best_session(struct session **, u_int, int); static int cmd_find_best_session_with_window(struct cmd_find_state *); static int cmd_find_best_winlink_with_window(struct cmd_find_state *); -static int cmd_find_current_session_with_client(struct cmd_find_state *); -static int cmd_find_current_session(struct cmd_find_state *); -static struct client *cmd_find_current_client(struct cmdq_item *); - static const char *cmd_find_map_table(const char *[][2], const char *); static int cmd_find_get_session(struct cmd_find_state *, const char *); @@ -84,13 +77,12 @@ static const char *cmd_find_pane_table[][2] = { /* Get session from TMUX if present. */ static struct session * -cmd_find_try_TMUX(struct client *c, struct window *w) +cmd_find_try_TMUX(struct client *c) { struct environ_entry *envent; char tmp[256]; long long pid; u_int session; - struct session *s; envent = environ_find(c->environ, "TMUX"); if (envent == NULL) @@ -100,13 +92,8 @@ cmd_find_try_TMUX(struct client *c, struct window *w) return (NULL); if (pid != getpid()) return (NULL); - log_debug("client %p TMUX is %s (session @%u)", c, envent->value, - session); - - s = session_find_by_id(session); - if (s == NULL || (w != NULL && !session_has(s, w))) - return (NULL); - return (s); + log_debug("client %p TMUX %s (session @%u)", c, envent->value, session); + return (session_find_by_id(session)); } /* Is this client better? */ @@ -118,28 +105,23 @@ cmd_find_client_better(struct client *c, struct client *than) return (timercmp(&c->activity_time, &than->activity_time, >)); } -/* Find best client from a list, or all if list is NULL. */ +/* Find best client for session. */ static struct client * -cmd_find_best_client(struct client **clist, u_int csize) +cmd_find_best_client(struct session *s) { struct client *c_loop, *c; - u_int i; + + if (s->flags & SESSION_UNATTACHED) + s = NULL; c = NULL; - if (clist != NULL) { - for (i = 0; i < csize; i++) { - if (clist[i]->session == NULL) - continue; - if (cmd_find_client_better(clist[i], c)) - c = clist[i]; - } - } else { - TAILQ_FOREACH(c_loop, &clients, entry) { - if (c_loop->session == NULL) - continue; - if (cmd_find_client_better(c_loop, c)) - c = c_loop; - } + TAILQ_FOREACH(c_loop, &clients, entry) { + if (c_loop->session == NULL) + continue; + if (s != NULL && c_loop->session != s) + continue; + if (cmd_find_client_better(c_loop, c)) + c = c_loop; } return (c); } @@ -192,12 +174,6 @@ cmd_find_best_session_with_window(struct cmd_find_state *fs) u_int ssize; struct session *s; - if (fs->item != NULL && fs->item->client != NULL) { - fs->s = cmd_find_try_TMUX(fs->item->client, fs->w); - if (fs->s != NULL) - return (cmd_find_best_winlink_with_window(fs)); - } - ssize = 0; RB_FOREACH(s, sessions, &sessions) { if (!session_has(s, fs->w)) @@ -245,146 +221,6 @@ cmd_find_best_winlink_with_window(struct cmd_find_state *fs) return (0); } -/* Find current session when we have an unattached client. */ -static int -cmd_find_current_session_with_client(struct cmd_find_state *fs) -{ - struct window_pane *wp; - - /* - * If this is running in a pane, we can use that to limit the list of - * sessions to those containing that pane (we still use the current - * window in the best session). - */ - if (fs->item != NULL) { - RB_FOREACH(wp, window_pane_tree, &all_window_panes) { - if (strcmp(wp->tty, fs->item->client->ttyname) == 0) - break; - } - } else - wp = NULL; - - /* Not running in a pane. We know nothing. Find the best session. */ - if (wp == NULL) - goto unknown_pane; - - /* Find the best session and winlink containing this pane. */ - fs->w = wp->window; - if (cmd_find_best_session_with_window(fs) != 0) { - if (wp != NULL) { - /* - * The window may have been destroyed but the pane - * still on all_window_panes due to something else - * holding a reference. - */ - goto unknown_pane; - } - return (-1); - } - - /* Use the current window and pane from this session. */ - fs->wl = fs->s->curw; - fs->idx = fs->wl->idx; - fs->w = fs->wl->window; - fs->wp = fs->w->active; - - return (0); - -unknown_pane: - fs->s = NULL; - if (fs->item != NULL) - fs->s = cmd_find_try_TMUX(fs->item->client, NULL); - if (fs->s == NULL) - fs->s = cmd_find_best_session(NULL, 0, fs->flags); - if (fs->s == NULL) - return (-1); - fs->wl = fs->s->curw; - fs->idx = fs->wl->idx; - fs->w = fs->wl->window; - fs->wp = fs->w->active; - - return (0); -} - -/* - * Work out the best current state. If this function succeeds, the state is - * guaranteed to be completely filled in. - */ -static int -cmd_find_current_session(struct cmd_find_state *fs) -{ - /* If we know the current client, use it. */ - if (fs->item != NULL && fs->item->client != NULL) { - log_debug("%s: have client %p%s", __func__, fs->item->client, - fs->item->client->session == NULL ? "" : " (with session)"); - if (fs->item->client->session == NULL) - return (cmd_find_current_session_with_client(fs)); - fs->s = fs->item->client->session; - fs->wl = fs->s->curw; - fs->idx = fs->wl->idx; - fs->w = fs->wl->window; - fs->wp = fs->w->active; - return (0); - } - - /* We know nothing, find the best session and client. */ - fs->s = cmd_find_best_session(NULL, 0, fs->flags); - if (fs->s == NULL) - return (-1); - fs->wl = fs->s->curw; - fs->idx = fs->wl->idx; - fs->w = fs->wl->window; - fs->wp = fs->w->active; - - return (0); -} - -/* Work out the best current client. */ -static struct client * -cmd_find_current_client(struct cmdq_item *item) -{ - struct cmd_find_state current; - struct session *s; - struct client *c, **clist = NULL; - u_int csize; - - /* If the queue client has a session, use it. */ - if (item->client != NULL && item->client->session != NULL) { - log_debug("%s: using item %p client %p", __func__, item, - item->client); - return (item->client); - } - - /* Otherwise find the current session. */ - cmd_find_clear_state(¤t, item, 0); - if (cmd_find_current_session(¤t) != 0) - return (NULL); - - /* If it is attached, find the best of it's clients. */ - s = current.s; - log_debug("%s: current session $%u %s", __func__, s->id, s->name); - if (~s->flags & SESSION_UNATTACHED) { - csize = 0; - TAILQ_FOREACH(c, &clients, entry) { - if (c->session != s) - continue; - clist = xreallocarray(clist, csize + 1, sizeof *clist); - clist[csize++] = c; - } - if (csize != 0) { - c = cmd_find_best_client(clist, csize); - if (c != NULL) { - free(clist); - return (c); - } - } - free(clist); - } - - /* Otherwise pick best of all clients. */ - return (cmd_find_best_client(NULL, 0)); -} - /* Maps string in table. */ static const char * cmd_find_map_table(const char *table[][2], const char *s) @@ -797,18 +633,16 @@ cmd_find_get_pane_with_window(struct cmd_find_state *fs, const char *pane) /* Clear state. */ void -cmd_find_clear_state(struct cmd_find_state *fs, struct cmdq_item *item, - int flags) +cmd_find_clear_state(struct cmd_find_state *fs, int flags) { memset(fs, 0, sizeof *fs); - fs->item = item; fs->flags = flags; fs->idx = -1; } -/* Check if state is empty/ */ +/* Check if state is empty. */ int cmd_find_empty_state(struct cmd_find_state *fs) { @@ -882,7 +716,7 @@ cmd_find_log_state(const char *prefix, struct cmd_find_state *fs) void cmd_find_from_session(struct cmd_find_state *fs, struct session *s) { - cmd_find_clear_state(fs, NULL, 0); + cmd_find_clear_state(fs, 0); fs->s = s; fs->wl = fs->s->curw; @@ -896,7 +730,7 @@ cmd_find_from_session(struct cmd_find_state *fs, struct session *s) void cmd_find_from_winlink(struct cmd_find_state *fs, struct winlink *wl) { - cmd_find_clear_state(fs, NULL, 0); + cmd_find_clear_state(fs, 0); fs->s = wl->session; fs->wl = wl; @@ -911,7 +745,7 @@ int cmd_find_from_session_window(struct cmd_find_state *fs, struct session *s, struct window *w) { - cmd_find_clear_state(fs, NULL, 0); + cmd_find_clear_state(fs, 0); fs->s = s; fs->w = w; @@ -927,7 +761,7 @@ cmd_find_from_session_window(struct cmd_find_state *fs, struct session *s, int cmd_find_from_window(struct cmd_find_state *fs, struct window *w) { - cmd_find_clear_state(fs, NULL, 0); + cmd_find_clear_state(fs, 0); fs->w = w; if (cmd_find_best_session_with_window(fs) != 0) @@ -945,7 +779,7 @@ void cmd_find_from_winlink_pane(struct cmd_find_state *fs, struct winlink *wl, struct window_pane *wp) { - cmd_find_clear_state(fs, NULL, 0); + cmd_find_clear_state(fs, 0); fs->s = wl->session; fs->wl = wl; @@ -970,17 +804,126 @@ cmd_find_from_pane(struct cmd_find_state *fs, struct window_pane *wp) return (0); } -/* Find current state. */ +/* Find state from nothing. */ int -cmd_find_current(struct cmd_find_state *fs, struct cmdq_item *item, int flags) +cmd_find_from_nothing(struct cmd_find_state *fs) { - cmd_find_clear_state(fs, item, flags); - if (cmd_find_current_session(fs) != 0) { - if (~flags & CMD_FIND_QUIET) - cmdq_error(item, "no current session"); + cmd_find_clear_state(fs, 0); + + fs->s = cmd_find_best_session(NULL, 0, fs->flags); + if (fs->s == NULL) + return (-1); + fs->wl = fs->s->curw; + fs->idx = fs->wl->idx; + fs->w = fs->wl->window; + fs->wp = fs->w->active; + + cmd_find_log_state(__func__, fs); + return (0); +} + +/* Find state from mouse. */ +int +cmd_find_from_mouse(struct cmd_find_state *fs, struct mouse_event *m) +{ + cmd_find_clear_state(fs, 0); + + if (!m->valid) + return (-1); + + fs->wp = cmd_mouse_pane(m, &fs->s, &fs->wl); + if (fs->wp == NULL) + return (-1); + fs->w = fs->wl->window; + + cmd_find_log_state(__func__, fs); + return (0); +} + +/* Find state from client. */ +int +cmd_find_from_client(struct cmd_find_state *fs, struct client *c) +{ + struct session *s; + struct winlink *wl; + struct window_pane *wp; + + /* If no client, treat as from nothing. */ + if (c == NULL) + return (cmd_find_from_nothing(fs)); + + /* If this is an attached client, all done. */ + if (c->session != NULL) { + cmd_find_from_session(fs, c->session); + return (0); + } + cmd_find_clear_state(fs, 0); + + /* + * If this is an unattached client running in a pane, we can use that + * to limit the list of sessions to those containing that pane. + */ + RB_FOREACH(wp, window_pane_tree, &all_window_panes) { + if (strcmp(wp->tty, c->ttyname) == 0) + break; + } + if (wp == NULL) + goto unknown_pane; + + /* If we have a session in TMUX, see if it has this pane. */ + s = cmd_find_try_TMUX(c); + if (s != NULL) { + RB_FOREACH(wl, winlinks, &s->windows) { + if (window_has_pane(wl->window, wp)) + break; + } + if (wl != NULL) { + fs->s = s; + fs->wl = s->curw; /* use active session */ + fs->w = fs->wl->window; + fs->wp = fs->w->active; /* use active pane */ + + cmd_find_log_state(__func__, fs); + return (0); + } + } + + /* + * Don't have a session, or it doesn't have this pane. Try all + * sessions. + */ + fs->w = wp->window; + if (cmd_find_best_session_with_window(fs) != 0) { + if (wp != NULL) { + /* + * The window may have been destroyed but the pane + * still on all_window_panes due to something else + * holding a reference. + */ + goto unknown_pane; + } return (-1); } + fs->wl = fs->s->curw; + fs->w = fs->wl->window; + fs->wp = fs->w->active; /* use active pane */ + + cmd_find_log_state(__func__, fs); return (0); + +unknown_pane: + /* + * We're not running in a known pane, but maybe this client has TMUX + * in the environment. That'd give us a session. + */ + s = cmd_find_try_TMUX(c); + if (s != NULL) { + cmd_find_from_session(fs, s); + return (0); + } + + /* Otherwise we need to guess. */ + return (cmd_find_from_nothing(fs)); } /* @@ -988,11 +931,11 @@ cmd_find_current(struct cmd_find_state *fs, struct cmdq_item *item, int flags) * state. Returns 0 on success or -1 on error. */ int -cmd_find_target(struct cmd_find_state *fs, struct cmd_find_state *current, - struct cmdq_item *item, const char *target, enum cmd_find_type type, - int flags) +cmd_find_target(struct cmd_find_state *fs, struct cmdq_item *item, + const char *target, enum cmd_find_type type, int flags) { struct mouse_event *m; + struct cmd_find_state current; char *colon, *period, *copy = NULL; const char *session, *window, *pane; int window_only = 0, pane_only = 0; @@ -1005,7 +948,7 @@ cmd_find_target(struct cmd_find_state *fs, struct cmd_find_state *current, log_debug("%s: item %p, flags %#x", __func__, item, flags); /* Clear new state. */ - cmd_find_clear_state(fs, item, flags); + cmd_find_clear_state(fs, flags); /* Find current state. */ if (server_check_marked() && (flags & CMD_FIND_DEFAULT_MARKED)) { @@ -1014,10 +957,11 @@ cmd_find_target(struct cmd_find_state *fs, struct cmd_find_state *current, } else if (cmd_find_valid_state(&item->shared->current)) { fs->current = &item->shared->current; log_debug("%s: current is from queue", __func__); - } else { - fs->current = current; - log_debug("%s: current is from argument", __func__); - } + } else if (cmd_find_from_client(¤t, item->client) == 0) { + fs->current = ¤t; + log_debug("%s: current is from client", __func__); + } else + return (-1); if (!cmd_find_empty_state(fs->current) && !cmd_find_valid_state(fs->current)) fatalx("invalid current find state"); @@ -1264,12 +1208,20 @@ struct client * cmd_find_client(struct cmdq_item *item, const char *target, int quiet) { struct client *c; + struct session *s; char *copy; size_t size; /* A NULL argument means the current client. */ - if (item != NULL && target == NULL) { - c = cmd_find_current_client(item); + if (target == NULL) { + c = NULL; + if (item->client != NULL && item->client->session != NULL) + c = item->client; + else { + s = cmd_find_best_session(NULL, 0, CMD_FIND_QUIET); + if (s != NULL) + c = cmd_find_best_client(s); + } if (c == NULL && !quiet) cmdq_error(item, "no current client"); log_debug("%s: no target, return %p", __func__, c); diff --git a/cmd-queue.c b/cmd-queue.c index 804216fa..6607fc04 100644 --- a/cmd-queue.c +++ b/cmd-queue.c @@ -216,11 +216,12 @@ cmdq_fire_command(struct cmdq_item *item) name = cmd->entry->name; if (cmd_find_valid_state(&item->state.tflag)) fsp = &item->state.tflag; - else { - if (cmd_find_current(&fs, item, CMD_FIND_QUIET) != 0) - goto out; + else if (cmd_find_valid_state(&item->shared->current)) + fsp = &item->shared->current; + else if (cmd_find_from_client(&fs, item->client) == 0) fsp = &fs; - } + else + goto out; hooks_insert(fsp->s->hooks, item, fsp, "after-%s", name); } diff --git a/cmd-run-shell.c b/cmd-run-shell.c index 48d88049..906b6909 100644 --- a/cmd-run-shell.c +++ b/cmd-run-shell.c @@ -68,7 +68,7 @@ cmd_run_shell_print(struct job *job, const char *msg) cmdq_print(cdata->item, "%s", msg); return; } - if (cmd_find_current (&fs, NULL, CMD_FIND_QUIET) != 0) + if (cmd_find_from_nothing(&fs) != 0) return; wp = fs.wp; if (wp == NULL) diff --git a/cmd.c b/cmd.c index 751be910..1ea91bdd 100644 --- a/cmd.c +++ b/cmd.c @@ -454,7 +454,6 @@ cmd_prepare_state_flag(char c, const char *target, enum cmd_entry_flag flag, { int targetflags, error; struct cmd_find_state *fs = NULL; - struct cmd_find_state current; if (flag == CMD_NONE || flag == CMD_CLIENT || @@ -511,15 +510,6 @@ cmd_prepare_state_flag(char c, const char *target, enum cmd_entry_flag flag, } log_debug("%s: flag %c %d %#x", __func__, c, flag, targetflags); - error = cmd_find_current(¤t, item, targetflags); - if (error != 0) { - if (~targetflags & CMD_FIND_QUIET) - return (-1); - cmd_find_clear_state(¤t, NULL, 0); - } - if (!cmd_find_empty_state(¤t) && !cmd_find_valid_state(¤t)) - fatalx("invalid current state"); - switch (flag) { case CMD_NONE: case CMD_CLIENT: @@ -529,14 +519,14 @@ cmd_prepare_state_flag(char c, const char *target, enum cmd_entry_flag flag, case CMD_SESSION_CANFAIL: case CMD_SESSION_PREFERUNATTACHED: case CMD_SESSION_WITHPANE: - error = cmd_find_target(fs, ¤t, item, target, - CMD_FIND_SESSION, targetflags); + error = cmd_find_target(fs, item, target, CMD_FIND_SESSION, + targetflags); if (error != 0) goto error; break; case CMD_MOVEW_R: - error = cmd_find_target(fs, ¤t, item, target, - CMD_FIND_SESSION, CMD_FIND_QUIET); + error = cmd_find_target(fs, item, target, CMD_FIND_SESSION, + CMD_FIND_QUIET); if (error == 0) break; /* FALLTHROUGH */ @@ -544,16 +534,16 @@ cmd_prepare_state_flag(char c, const char *target, enum cmd_entry_flag flag, case CMD_WINDOW_CANFAIL: case CMD_WINDOW_MARKED: case CMD_WINDOW_INDEX: - error = cmd_find_target(fs, ¤t, item, target, - CMD_FIND_WINDOW, targetflags); + error = cmd_find_target(fs, item, target, CMD_FIND_WINDOW, + targetflags); if (error != 0) goto error; break; case CMD_PANE: case CMD_PANE_CANFAIL: case CMD_PANE_MARKED: - error = cmd_find_target(fs, ¤t, item, target, - CMD_FIND_PANE, targetflags); + error = cmd_find_target(fs, item, target, CMD_FIND_PANE, + targetflags); if (error != 0) goto error; break; @@ -565,7 +555,7 @@ cmd_prepare_state_flag(char c, const char *target, enum cmd_entry_flag flag, error: if (~targetflags & CMD_FIND_QUIET) return (-1); - cmd_find_clear_state(fs, NULL, 0); + cmd_find_clear_state(fs, 0); return (0); } @@ -584,8 +574,8 @@ cmd_prepare_state(struct cmd *cmd, struct cmdq_item *item) free(tmp); state->c = NULL; - cmd_find_clear_state(&state->tflag, NULL, 0); - cmd_find_clear_state(&state->sflag, NULL, 0); + cmd_find_clear_state(&state->tflag, 0); + cmd_find_clear_state(&state->sflag, 0); flag = cmd->entry->cflag; if (flag == CMD_NONE) { diff --git a/notify.c b/notify.c index 446e71e7..a338c57c 100644 --- a/notify.c +++ b/notify.c @@ -44,9 +44,9 @@ notify_hook(struct cmdq_item *item, struct notify_entry *ne) struct session *s = ne->session; struct window *w = ne->window; - cmd_find_clear_state(&fs, NULL, 0); + cmd_find_clear_state(&fs, 0); if (cmd_find_empty_state(&ne->fs) || !cmd_find_valid_state(&ne->fs)) - cmd_find_current(&fs, item, CMD_FIND_QUIET); + cmd_find_from_nothing(&fs); else cmd_find_copy_state(&fs, &ne->fs); @@ -164,10 +164,7 @@ notify_client(const char *name, struct client *c) { struct cmd_find_state fs; - if (c->session != NULL) - cmd_find_from_session(&fs, c->session); - else - cmd_find_current(&fs, NULL, CMD_FIND_QUIET); + cmd_find_from_client(&fs, c); notify_add(name, &fs, c, NULL, NULL, NULL); } @@ -179,7 +176,7 @@ notify_session(const char *name, struct session *s) if (session_alive(s)) cmd_find_from_session(&fs, s); else - cmd_find_current(&fs, NULL, CMD_FIND_QUIET); + cmd_find_from_nothing(&fs); notify_add(name, &fs, NULL, s, NULL, NULL); } diff --git a/server.c b/server.c index 71c0e25a..78bc70db 100644 --- a/server.c +++ b/server.c @@ -63,7 +63,7 @@ static void server_child_stopped(pid_t, int); void server_set_marked(struct session *s, struct winlink *wl, struct window_pane *wp) { - cmd_find_clear_state(&marked_pane, NULL, 0); + cmd_find_clear_state(&marked_pane, 0); marked_pane.s = s; marked_pane.wl = wl; marked_pane.w = wl->window; @@ -74,7 +74,7 @@ server_set_marked(struct session *s, struct winlink *wl, struct window_pane *wp) void server_clear_marked(void) { - cmd_find_clear_state(&marked_pane, NULL, 0); + cmd_find_clear_state(&marked_pane, 0); } /* Is this the marked pane? */ diff --git a/tmux.h b/tmux.h index e2d46595..81fcc447 100644 --- a/tmux.h +++ b/tmux.h @@ -1145,7 +1145,6 @@ enum cmd_find_type { CMD_FIND_SESSION, }; struct cmd_find_state { - struct cmdq_item *item; int flags; struct cmd_find_state *current; @@ -1730,14 +1729,10 @@ long long args_strtonum(struct args *, u_char, long long, long long, char **); /* cmd-find.c */ -int cmd_find_current(struct cmd_find_state *, struct cmdq_item *, - int); -int cmd_find_target(struct cmd_find_state *, - struct cmd_find_state *, struct cmdq_item *, const char *, - enum cmd_find_type, int); +int cmd_find_target(struct cmd_find_state *, struct cmdq_item *, + const char *, enum cmd_find_type, int); struct client *cmd_find_client(struct cmdq_item *, const char *, int); -void cmd_find_clear_state(struct cmd_find_state *, - struct cmdq_item *, int); +void cmd_find_clear_state(struct cmd_find_state *, int); int cmd_find_empty_state(struct cmd_find_state *); int cmd_find_valid_state(struct cmd_find_state *); void cmd_find_copy_state(struct cmd_find_state *, @@ -1750,10 +1745,14 @@ void cmd_find_from_winlink(struct cmd_find_state *, int cmd_find_from_session_window(struct cmd_find_state *, struct session *, struct window *); int cmd_find_from_window(struct cmd_find_state *, struct window *); -int cmd_find_from_pane(struct cmd_find_state *, - struct window_pane *); void cmd_find_from_winlink_pane(struct cmd_find_state *, struct winlink *, struct window_pane *); +int cmd_find_from_pane(struct cmd_find_state *, + struct window_pane *); +int cmd_find_from_client(struct cmd_find_state *, struct client *); +int cmd_find_from_mouse(struct cmd_find_state *, + struct mouse_event *); +int cmd_find_from_nothing(struct cmd_find_state *); /* cmd.c */ int cmd_pack_argv(int, char **, char *, size_t);