[BACK]Return to cmd-find.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / tmux

Diff for /src/usr.bin/tmux/cmd-find.c between version 1.47 and 1.48

version 1.47, 2017/04/21 17:22:20 version 1.48, 2017/04/21 20:26:34
Line 27 
Line 27 
   
 #include "tmux.h"  #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 *,  static int      cmd_find_session_better(struct session *, struct session *,
                     int);                      int);
 static struct session *cmd_find_best_session(struct session **, u_int, 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_session_with_window(struct cmd_find_state *);
 static int      cmd_find_best_winlink_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 const char *cmd_find_map_table(const char *[][2], const char *);
   
 static int      cmd_find_get_session(struct cmd_find_state *, const char *);  static int      cmd_find_get_session(struct cmd_find_state *, const char *);
Line 84 
Line 77 
   
 /* Get session from TMUX if present. */  /* Get session from TMUX if present. */
 static struct session *  static struct session *
 cmd_find_try_TMUX(struct client *c, struct window *w)  cmd_find_try_TMUX(struct client *c)
 {  {
         struct environ_entry    *envent;          struct environ_entry    *envent;
         char                     tmp[256];          char                     tmp[256];
         long long                pid;          long long                pid;
         u_int                    session;          u_int                    session;
         struct session          *s;  
   
         envent = environ_find(c->environ, "TMUX");          envent = environ_find(c->environ, "TMUX");
         if (envent == NULL)          if (envent == NULL)
Line 100 
Line 92 
                 return (NULL);                  return (NULL);
         if (pid != getpid())          if (pid != getpid())
                 return (NULL);                  return (NULL);
         log_debug("client %p TMUX is %s (session @%u)", c, envent->value,          log_debug("client %p TMUX %s (session @%u)", c, envent->value, session);
             session);          return (session_find_by_id(session));
   
         s = session_find_by_id(session);  
         if (s == NULL || (w != NULL && !session_has(s, w)))  
                 return (NULL);  
         return (s);  
 }  }
   
 /* Is this client better? */  /* Is this client better? */
Line 118 
Line 105 
         return (timercmp(&c->activity_time, &than->activity_time, >));          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 *  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;          struct client   *c_loop, *c;
         u_int            i;  
   
           if (s->flags & SESSION_UNATTACHED)
                   s = NULL;
   
         c = NULL;          c = NULL;
         if (clist != NULL) {          TAILQ_FOREACH(c_loop, &clients, entry) {
                 for (i = 0; i < csize; i++) {                  if (c_loop->session == NULL)
                         if (clist[i]->session == NULL)                          continue;
                                 continue;                  if (s != NULL && c_loop->session != s)
                         if (cmd_find_client_better(clist[i], c))                          continue;
                                 c = clist[i];                  if (cmd_find_client_better(c_loop, c))
                 }                          c = c_loop;
         } else {  
                 TAILQ_FOREACH(c_loop, &clients, entry) {  
                         if (c_loop->session == NULL)  
                                 continue;  
                         if (cmd_find_client_better(c_loop, c))  
                                 c = c_loop;  
                 }  
         }          }
         return (c);          return (c);
 }  }
Line 192 
Line 174 
         u_int             ssize;          u_int             ssize;
         struct session   *s;          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;          ssize = 0;
         RB_FOREACH(s, sessions, &sessions) {          RB_FOREACH(s, sessions, &sessions) {
                 if (!session_has(s, fs->w))                  if (!session_has(s, fs->w))
Line 245 
Line 221 
         return (0);          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(&current, item, 0);  
         if (cmd_find_current_session(&current) != 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. */  /* Maps string in table. */
 static const char *  static const char *
 cmd_find_map_table(const char *table[][2], const char *s)  cmd_find_map_table(const char *table[][2], const char *s)
Line 797 
Line 633 
   
 /* Clear state. */  /* Clear state. */
 void  void
 cmd_find_clear_state(struct cmd_find_state *fs, struct cmdq_item *item,  cmd_find_clear_state(struct cmd_find_state *fs, int flags)
     int flags)  
 {  {
         memset(fs, 0, sizeof *fs);          memset(fs, 0, sizeof *fs);
   
         fs->item = item;  
         fs->flags = flags;          fs->flags = flags;
   
         fs->idx = -1;          fs->idx = -1;
 }  }
   
 /* Check if state is empty/ */  /* Check if state is empty. */
 int  int
 cmd_find_empty_state(struct cmd_find_state *fs)  cmd_find_empty_state(struct cmd_find_state *fs)
 {  {
Line 882 
Line 716 
 void  void
 cmd_find_from_session(struct cmd_find_state *fs, struct session *s)  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->s = s;
         fs->wl = fs->s->curw;          fs->wl = fs->s->curw;
Line 896 
Line 730 
 void  void
 cmd_find_from_winlink(struct cmd_find_state *fs, struct winlink *wl)  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->s = wl->session;
         fs->wl = wl;          fs->wl = wl;
Line 911 
Line 745 
 cmd_find_from_session_window(struct cmd_find_state *fs, struct session *s,  cmd_find_from_session_window(struct cmd_find_state *fs, struct session *s,
     struct window *w)      struct window *w)
 {  {
         cmd_find_clear_state(fs, NULL, 0);          cmd_find_clear_state(fs, 0);
   
         fs->s = s;          fs->s = s;
         fs->w = w;          fs->w = w;
Line 927 
Line 761 
 int  int
 cmd_find_from_window(struct cmd_find_state *fs, struct window *w)  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;          fs->w = w;
         if (cmd_find_best_session_with_window(fs) != 0)          if (cmd_find_best_session_with_window(fs) != 0)
Line 945 
Line 779 
 cmd_find_from_winlink_pane(struct cmd_find_state *fs, struct winlink *wl,  cmd_find_from_winlink_pane(struct cmd_find_state *fs, struct winlink *wl,
     struct window_pane *wp)      struct window_pane *wp)
 {  {
         cmd_find_clear_state(fs, NULL, 0);          cmd_find_clear_state(fs, 0);
   
         fs->s = wl->session;          fs->s = wl->session;
         fs->wl = wl;          fs->wl = wl;
Line 970 
Line 804 
         return (0);          return (0);
 }  }
   
 /* Find current state. */  /* Find state from nothing. */
 int  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);          cmd_find_clear_state(fs, 0);
         if (cmd_find_current_session(fs) != 0) {  
                 if (~flags & CMD_FIND_QUIET)          fs->s = cmd_find_best_session(NULL, 0, fs->flags);
                         cmdq_error(item, "no current session");          if (fs->s == NULL)
                 return (-1);                  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);          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));
 }  }
   
 /*  /*
Line 988 
Line 931 
  * state. Returns 0 on success or -1 on error.   * state. Returns 0 on success or -1 on error.
  */   */
 int  int
 cmd_find_target(struct cmd_find_state *fs, struct cmd_find_state *current,  cmd_find_target(struct cmd_find_state *fs, struct cmdq_item *item,
     struct cmdq_item *item, const char *target, enum cmd_find_type type,      const char *target, enum cmd_find_type type, int flags)
     int flags)  
 {  {
         struct mouse_event      *m;          struct mouse_event      *m;
           struct cmd_find_state    current;
         char                    *colon, *period, *copy = NULL;          char                    *colon, *period, *copy = NULL;
         const char              *session, *window, *pane;          const char              *session, *window, *pane;
         int                      window_only = 0, pane_only = 0;          int                      window_only = 0, pane_only = 0;
Line 1005 
Line 948 
         log_debug("%s: item %p, flags %#x", __func__, item, flags);          log_debug("%s: item %p, flags %#x", __func__, item, flags);
   
         /* Clear new state. */          /* Clear new state. */
         cmd_find_clear_state(fs, item, flags);          cmd_find_clear_state(fs, flags);
   
         /* Find current state. */          /* Find current state. */
         if (server_check_marked() && (flags & CMD_FIND_DEFAULT_MARKED)) {          if (server_check_marked() && (flags & CMD_FIND_DEFAULT_MARKED)) {
Line 1014 
Line 957 
         } else if (cmd_find_valid_state(&item->shared->current)) {          } else if (cmd_find_valid_state(&item->shared->current)) {
                 fs->current = &item->shared->current;                  fs->current = &item->shared->current;
                 log_debug("%s: current is from queue", __func__);                  log_debug("%s: current is from queue", __func__);
         } else {          } else if (cmd_find_from_client(&current, item->client) == 0) {
                 fs->current = current;                  fs->current = &current;
                 log_debug("%s: current is from argument", __func__);                  log_debug("%s: current is from client", __func__);
         }          } else
                   return (-1);
         if (!cmd_find_empty_state(fs->current) &&          if (!cmd_find_empty_state(fs->current) &&
             !cmd_find_valid_state(fs->current))              !cmd_find_valid_state(fs->current))
                 fatalx("invalid current find state");                  fatalx("invalid current find state");
Line 1264 
Line 1208 
 cmd_find_client(struct cmdq_item *item, const char *target, int quiet)  cmd_find_client(struct cmdq_item *item, const char *target, int quiet)
 {  {
         struct client   *c;          struct client   *c;
           struct session  *s;
         char            *copy;          char            *copy;
         size_t           size;          size_t           size;
   
         /* A NULL argument means the current client. */          /* A NULL argument means the current client. */
         if (item != NULL && target == NULL) {          if (target == NULL) {
                 c = cmd_find_current_client(item);                  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)                  if (c == NULL && !quiet)
                         cmdq_error(item, "no current client");                          cmdq_error(item, "no current client");
                 log_debug("%s: no target, return %p", __func__, c);                  log_debug("%s: no target, return %p", __func__, c);

Legend:
Removed from v.1.47  
changed lines
  Added in v.1.48