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

Diff for /src/usr.bin/tmux/status.c between version 1.203 and 1.204

version 1.203, 2020/05/16 15:01:31 version 1.204, 2020/05/16 15:06:03
Line 37 
Line 37 
 static const char *status_prompt_down_history(u_int *);  static const char *status_prompt_down_history(u_int *);
 static void      status_prompt_add_history(const char *);  static void      status_prompt_add_history(const char *);
   
 static char    **status_prompt_complete_list(u_int *, const char *);  static char     *status_prompt_complete(struct client *, const char *, u_int);
 static char     *status_prompt_complete_prefix(char **, u_int);  
 static char     *status_prompt_complete(struct session *, const char *);  
   
   struct status_prompt_menu {
           struct client    *c;
           u_int             start;
           u_int             size;
           char            **list;
           char              flag;
   };
   
 /* Status prompt history. */  /* Status prompt history. */
 #define PROMPT_HISTORY 100  #define PROMPT_HISTORY 100
 static char     **status_prompt_hlist;  static char     **status_prompt_hlist;
Line 919 
Line 925 
         return (1);          return (1);
 }  }
   
   /* Finish completion. */
   static int
   status_prompt_replace_complete(struct client *c, const char *s)
   {
           char                     word[64], *allocated = NULL;
           size_t                   size, n, off, idx, used;
           struct utf8_data        *first, *last, *ud;
   
           if (c->prompt_buffer[0].size == 0)
                   return (0);
           size = utf8_strlen(c->prompt_buffer);
   
           idx = c->prompt_index;
           if (idx != 0)
                   idx--;
   
           /* Find the word we are in. */
           first = &c->prompt_buffer[idx];
           while (first > c->prompt_buffer && !status_prompt_space(first))
                   first--;
           while (first->size != 0 && status_prompt_space(first))
                   first++;
           last = &c->prompt_buffer[idx];
           while (last->size != 0 && !status_prompt_space(last))
                   last++;
           while (last > c->prompt_buffer && status_prompt_space(last))
                   last--;
           if (last->size != 0)
                   last++;
           if (last <= first)
                   return (0);
           if (s == NULL) {
                   used = 0;
                   for (ud = first; ud < last; ud++) {
                           if (used + ud->size >= sizeof word)
                                   break;
                           memcpy(word + used, ud->data, ud->size);
                           used += ud->size;
                   }
                   if (ud != last)
                           return (0);
                   word[used] = '\0';
           }
   
           /* Try to complete it. */
           if (s == NULL) {
                   allocated = status_prompt_complete(c, word,
                       first - c->prompt_buffer);
                   if (allocated == NULL)
                           return (0);
                   s = allocated;
           }
   
           /* Trim out word. */
           n = size - (last - c->prompt_buffer) + 1; /* with \0 */
           memmove(first, last, n * sizeof *c->prompt_buffer);
           size -= last - first;
   
           /* Insert the new word. */
           size += strlen(s);
           off = first - c->prompt_buffer;
           c->prompt_buffer = xreallocarray(c->prompt_buffer, size + 1,
               sizeof *c->prompt_buffer);
           first = c->prompt_buffer + off;
           memmove(first + strlen(s), first, n * sizeof *c->prompt_buffer);
           for (idx = 0; idx < strlen(s); idx++)
                   utf8_set(&first[idx], s[idx]);
           c->prompt_index = (first - c->prompt_buffer) + strlen(s);
   
           free(allocated);
           return (1);
   }
   
 /* Handle keys in prompt. */  /* Handle keys in prompt. */
 int  int
 status_prompt_key(struct client *c, key_code key)  status_prompt_key(struct client *c, key_code key)
 {  {
         struct options          *oo = c->session->options;          struct options          *oo = c->session->options;
         char                    *s, *cp, word[64], prefix = '=';          char                    *s, *cp, prefix = '=';
         const char              *histstr, *ws = NULL, *keystring;          const char              *histstr, *ws = NULL, *keystring;
         size_t                   size, n, off, idx, used;          size_t                   size, idx;
         struct utf8_data         tmp, *first, *last, *ud;          struct utf8_data         tmp;
         int                      keys;          int                      keys;
   
         if (c->prompt_flags & PROMPT_KEY) {          if (c->prompt_flags & PROMPT_KEY) {
Line 992 
Line 1071 
                 }                  }
                 break;                  break;
         case '\011': /* Tab */          case '\011': /* Tab */
                 if (c->prompt_buffer[0].size == 0)                  if (status_prompt_replace_complete(c, NULL))
                         break;                          goto changed;
                   break;
                 idx = c->prompt_index;  
                 if (idx != 0)  
                         idx--;  
   
                 /* Find the word we are in. */  
                 first = &c->prompt_buffer[idx];  
                 while (first > c->prompt_buffer && !status_prompt_space(first))  
                         first--;  
                 while (first->size != 0 && status_prompt_space(first))  
                         first++;  
                 last = &c->prompt_buffer[idx];  
                 while (last->size != 0 && !status_prompt_space(last))  
                         last++;  
                 while (last > c->prompt_buffer && status_prompt_space(last))  
                         last--;  
                 if (last->size != 0)  
                         last++;  
                 if (last <= first)  
                         break;  
   
                 used = 0;  
                 for (ud = first; ud < last; ud++) {  
                         if (used + ud->size >= sizeof word)  
                                 break;  
                         memcpy(word + used, ud->data, ud->size);  
                         used += ud->size;  
                 }  
                 if (ud != last)  
                         break;  
                 word[used] = '\0';  
   
                 /* And try to complete it. */  
                 if ((s = status_prompt_complete(c->session, word)) == NULL)  
                         break;  
   
                 /* Trim out word. */  
                 n = size - (last - c->prompt_buffer) + 1; /* with \0 */  
                 memmove(first, last, n * sizeof *c->prompt_buffer);  
                 size -= last - first;  
   
                 /* Insert the new word. */  
                 size += strlen(s);  
                 off = first - c->prompt_buffer;  
                 c->prompt_buffer = xreallocarray(c->prompt_buffer, size + 1,  
                     sizeof *c->prompt_buffer);  
                 first = c->prompt_buffer + off;  
                 memmove(first + strlen(s), first, n * sizeof *c->prompt_buffer);  
                 for (idx = 0; idx < strlen(s); idx++)  
                         utf8_set(&first[idx], s[idx]);  
   
                 c->prompt_index = (first - c->prompt_buffer) + strlen(s);  
                 free(s);  
   
                 goto changed;  
         case KEYC_BSPACE:          case KEYC_BSPACE:
         case '\010': /* C-h */          case '\010': /* C-h */
                 if (c->prompt_index != 0) {                  if (c->prompt_index != 0) {
Line 1330 
Line 1355 
 }  }
   
 /* Build completion list. */  /* Build completion list. */
 char **  static char **
 status_prompt_complete_list(u_int *size, const char *s)  status_prompt_complete_list(u_int *size, const char *s, int at_start)
 {  {
         char                                    **list = NULL;          char                                    **list = NULL;
         const char                              **layout, *value, *cp;          const char                              **layout, *value, *cp;
         const struct cmd_entry                  **cmdent;          const struct cmd_entry                  **cmdent;
         const struct options_table_entry         *oe;          const struct options_table_entry         *oe;
         u_int                                     idx;  
         size_t                                    slen = strlen(s), valuelen;          size_t                                    slen = strlen(s), valuelen;
         struct options_entry                     *o;          struct options_entry                     *o;
         struct options_array_item                *a;          struct options_array_item                *a;
Line 1353 
Line 1377 
                         list[(*size)++] = xstrdup((*cmdent)->name);                          list[(*size)++] = xstrdup((*cmdent)->name);
                 }                  }
         }          }
         for (oe = options_table; oe->name != NULL; oe++) {  
                 if (strncmp(oe->name, s, slen) == 0) {  
                         list = xreallocarray(list, (*size) + 1, sizeof *list);  
                         list[(*size)++] = xstrdup(oe->name);  
                 }  
         }  
         for (layout = layouts; *layout != NULL; layout++) {  
                 if (strncmp(*layout, s, slen) == 0) {  
                         list = xreallocarray(list, (*size) + 1, sizeof *list);  
                         list[(*size)++] = xstrdup(*layout);  
                 }  
         }  
         o = options_get_only(global_options, "command-alias");          o = options_get_only(global_options, "command-alias");
         if (o != NULL) {          if (o != NULL) {
                 a = options_array_first(o);                  a = options_array_first(o);
Line 1383 
Line 1395 
                         a = options_array_next(a);                          a = options_array_next(a);
                 }                  }
         }          }
         for (idx = 0; idx < (*size); idx++)          if (at_start)
                 log_debug("complete %u: %s", idx, list[idx]);                  return (list);
   
           for (oe = options_table; oe->name != NULL; oe++) {
                   if (strncmp(oe->name, s, slen) == 0) {
                           list = xreallocarray(list, (*size) + 1, sizeof *list);
                           list[(*size)++] = xstrdup(oe->name);
                   }
           }
           for (layout = layouts; *layout != NULL; layout++) {
                   if (strncmp(*layout, s, slen) == 0) {
                           list = xreallocarray(list, (*size) + 1, sizeof *list);
                           list[(*size)++] = xstrdup(*layout);
                   }
           }
         return (list);          return (list);
 }  }
   
Line 1409 
Line 1434 
         return (out);          return (out);
 }  }
   
   /* Complete word menu callback. */
   static void
   status_prompt_menu_callback(__unused struct menu *menu, u_int idx, key_code key,
       void *data)
   {
           struct status_prompt_menu       *spm = data;
           struct client                   *c = spm->c;
           u_int                            i;
           char                            *s;
   
           if (key != KEYC_NONE) {
                   idx += spm->start;
                   if (spm->flag == '\0')
                           s = xstrdup(spm->list[idx]);
                   else
                           xasprintf(&s, "-%c%s", spm->flag, spm->list[idx]);
                   if (status_prompt_replace_complete(c, s))
                           c->flags |= CLIENT_REDRAWSTATUS;
                   free(s);
           }
   
           for (i = 0; i < spm->size; i++)
                   free(spm->list[i]);
           free(spm->list);
   }
   
   /* Show complete word menu. */
   static int
   status_prompt_complete_list_menu(struct client *c, char **list, u_int size,
       u_int offset, char flag)
   {
           struct menu                     *menu;
           struct menu_item                 item;
           struct status_prompt_menu       *spm;
           u_int                            lines = status_line_size(c), height, i;
           u_int                            py;
   
           if (size <= 1)
                   return (0);
           if (c->tty.sy - lines < 3)
                   return (0);
   
           spm = xmalloc(sizeof *spm);
           spm->c = c;
           spm->size = size;
           spm->list = list;
           spm->flag = flag;
   
           height = c->tty.sy - lines - 2;
           if (height > 10)
                   height = 10;
           if (height > size)
                   height = size;
           spm->start = size - height;
   
           menu = menu_create("");
           for (i = spm->start; i < size; i++) {
                   item.name = list[i];
                   item.key = '0' + (i - spm->start);
                   item.command = NULL;
                   menu_add_item(menu, &item, NULL, NULL, NULL);
           }
   
           if (options_get_number(c->session->options, "status-position") == 0)
                   py = lines;
           else
                   py = c->tty.sy - 3 - height;
           offset += utf8_cstrwidth(c->prompt_string);
           if (offset > 2)
                   offset -= 2;
           else
                   offset = 0;
   
           if (menu_display(menu, MENU_NOMOUSE|MENU_TAB, NULL, offset,
               py, c, NULL, status_prompt_menu_callback, spm) != 0) {
                   menu_free(menu);
                   free(spm);
                   return (0);
           }
           return (1);
   }
   
   /* Show complete word menu. */
   static char *
   status_prompt_complete_window_menu(struct client *c, struct session *s,
       u_int offset, char flag)
   {
           struct menu                      *menu;
           struct menu_item                  item;
           struct status_prompt_menu        *spm;
           struct winlink                   *wl;
           char                            **list = NULL, *tmp;
           u_int                             lines = status_line_size(c), height;
           u_int                             py, size = 0;
   
           if (c->tty.sy - lines < 3)
                   return (NULL);
   
           spm = xmalloc(sizeof *spm);
           spm->c = c;
           spm->flag = flag;
   
           height = c->tty.sy - lines - 2;
           if (height > 10)
                   height = 10;
           spm->start = 0;
   
           menu = menu_create("");
           RB_FOREACH(wl, winlinks, &s->windows) {
                   list = xreallocarray(list, size + 1, sizeof *list);
                   xasprintf(&list[size++], "%s:%d", s->name, wl->idx);
   
                   xasprintf(&tmp, "%s:%d (%s)", s->name, wl->idx,
                       wl->window->name);
                   item.name = tmp;
                   item.key = '0' + size - 1;
                   item.command = NULL;
                   menu_add_item(menu, &item, NULL, NULL, NULL);
                   free(tmp);
   
                   if (size == height)
                           break;
           }
           if (size == 1) {
                   menu_free(menu);
                   xasprintf(&tmp, "-%c%s", flag, list[0]);
                   free(list[0]);
                   free(list);
                   return (tmp);
           }
           if (height > size)
                   height = size;
   
           spm->size = size;
           spm->list = list;
   
           if (options_get_number(c->session->options, "status-position") == 0)
                   py = lines;
           else
                   py = c->tty.sy - 3 - height;
           offset += utf8_cstrwidth(c->prompt_string);
           if (offset > 2)
                   offset -= 2;
           else
                   offset = 0;
   
           if (menu_display(menu, MENU_NOMOUSE|MENU_TAB, NULL, offset,
               py, c, NULL, status_prompt_menu_callback, spm) != 0) {
                   menu_free(menu);
                   free(spm);
                   return (NULL);
           }
           return (NULL);
   }
   
   /* Sort complete list. */
   static int
   status_prompt_complete_sort(const void *a, const void *b)
   {
           const char      **aa = (const char **)a, **bb = (const char **)b;
   
           return (strcmp(*aa, *bb));
   }
   
 /* Complete word. */  /* Complete word. */
 static char *  static char *
 status_prompt_complete(struct session *session, const char *s)  status_prompt_complete(struct client *c, const char *word, u_int offset)
 {  {
         char            **list = NULL;          struct session   *session, *loop;
         const char       *colon;          const char       *s, *colon;
           size_t            slen;
           char            **list = NULL, *copy = NULL, *out = NULL, *tmp;
           char              flag = '\0';
         u_int             size = 0, i;          u_int             size = 0, i;
         struct session   *s_loop;  
         struct winlink   *wl;  
         struct window    *w;  
         char             *copy, *out, *tmp;  
   
         if (*s == '\0')          if (*word == '\0')
                 return (NULL);                  return (NULL);
         out = NULL;  
   
         if (strncmp(s, "-t", 2) != 0 && strncmp(s, "-s", 2) != 0) {          if (strncmp(word, "-t", 2) != 0 && strncmp(word, "-s", 2) != 0) {
                 list = status_prompt_complete_list(&size, s);                  list = status_prompt_complete_list(&size, word, offset == 0);
                 if (size == 0)                  if (size == 0)
                         out = NULL;                          out = NULL;
                 else if (size == 1)                  else if (size == 1)
                         xasprintf(&out, "%s ", list[0]);                          xasprintf(&out, "%s ", list[0]);
                 else                  else
                         out = status_prompt_complete_prefix(list, size);                          out = status_prompt_complete_prefix(list, size);
                 for (i = 0; i < size; i++)                  goto found;
                         free(list[i]);  
                 free(list);  
                 return (out);  
         }          }
         copy = xstrdup(s);  
   
         colon = ":";          s = word + 2;
         if (copy[strlen(copy) - 1] == ':')          slen = strlen(s);
                 copy[strlen(copy) - 1] = '\0';  
         else  
                 colon = "";  
         s = copy + 2;  
   
         RB_FOREACH(s_loop, sessions, &sessions) {          flag = word[1];
                 if (strncmp(s_loop->name, s, strlen(s)) == 0) {          offset += 2;
   
           colon = strchr(s, ':');
   
           /* If there is no colon, complete as a session. */
           if (colon == NULL) {
                   RB_FOREACH(loop, sessions, &sessions) {
                           if (strncmp(loop->name, s, strlen(s)) != 0)
                                   continue;
                         list = xreallocarray(list, size + 2, sizeof *list);                          list = xreallocarray(list, size + 2, sizeof *list);
                         list[size++] = s_loop->name;                          xasprintf(&list[size++], "%s:", loop->name);
                 }                  }
         }  
         if (size == 1) {  
                 out = xstrdup(list[0]);  
                 if (session_find(list[0]) != NULL)  
                         colon = ":";  
         } else if (size != 0)  
                 out = status_prompt_complete_prefix(list, size);                  out = status_prompt_complete_prefix(list, size);
         if (out != NULL) {                  if (out != NULL) {
                 xasprintf(&tmp, "-%c%s%s", copy[1], out, colon);                          xasprintf(&tmp, "-%c%s", flag, out);
                 free(out);                          free(out);
                 out = tmp;                          out = tmp;
                   }
                 goto found;                  goto found;
         }          }
   
         colon = "";          /* If there is a colon but no period, find session and show a menu. */
         if (*s == ':') {          if (strchr(colon + 1, '.') == NULL) {
                 RB_FOREACH(wl, winlinks, &session->windows) {                  if (*s == ':')
                         xasprintf(&tmp, ":%s", wl->window->name);                          session = c->session;
                         if (strncmp(tmp, s, strlen(s)) == 0){                  else {
                                 list = xreallocarray(list, size + 1,                          copy = xstrdup(s);
                                     sizeof *list);                          *strchr(copy, ':') = '\0';
                                 list[size++] = tmp;                          session = session_find(copy);
                                 continue;                          free(copy);
                         }                          if (session == NULL)
                         free(tmp);                                  goto found;
   
                         xasprintf(&tmp, ":%d", wl->idx);  
                         if (strncmp(tmp, s, strlen(s)) == 0) {  
                                 list = xreallocarray(list, size + 1,  
                                     sizeof *list);  
                                 list[size++] = tmp;  
                                 continue;  
                         }  
                         free(tmp);  
                 }                  }
         } else {                  out = status_prompt_complete_window_menu(c, session, offset,
                 RB_FOREACH(s_loop, sessions, &sessions) {                      flag);
                         RB_FOREACH(wl, winlinks, &s_loop->windows) {                  if (out == NULL)
                                 w = wl->window;                          return (NULL);
           }
   
                                 xasprintf(&tmp, "%s:%s", s_loop->name, w->name);  found:
                                 if (strncmp(tmp, s, strlen(s)) == 0) {          if (size != 0) {
                                         list = xreallocarray(list, size + 1,                  qsort(list, size, sizeof *list, status_prompt_complete_sort);
                                             sizeof *list);                  for (i = 0; i < size; i++)
                                         list[size++] = tmp;                          log_debug("complete %u: %s", i, list[i]);
                                         continue;          }
                                 }  
                                 free(tmp);  
   
                                 xasprintf(&tmp, "%s:%d", s_loop->name, wl->idx);          if (out != NULL && strcmp(word, out) == 0) {
                                 if (strncmp(tmp, s, strlen(s)) == 0) {                  free(out);
                                         list = xreallocarray(list, size + 1,                  out = NULL;
                                             sizeof *list);  
                                         list[size++] = tmp;  
                                         continue;  
                                 }  
                                 free(tmp);  
                         }  
                 }  
         }          }
         if (size == 1) {          if (out != NULL ||
                 out = xstrdup(list[0]);              !status_prompt_complete_list_menu(c, list, size, offset, flag)) {
                 colon = " ";                  for (i = 0; i < size; i++)
         } else if (size != 0)                          free(list[i]);
                 out = status_prompt_complete_prefix(list, size);                  free(list);
         if (out != NULL) {  
                 xasprintf(&tmp, "-%c%s%s", copy[1], out, colon);  
                 out = tmp;  
         }          }
   
         for (i = 0; i < size; i++)  
                 free((void *)list[i]);  
   
 found:  
         free(copy);  
         free(list);  
         return (out);          return (out);
 }  }

Legend:
Removed from v.1.203  
changed lines
  Added in v.1.204