Make all entries in choose-mode use an ever-increasing numeric ID, and
prompt for that ID, if a user presses a number.  If the number of items are
less than 10, automatically go to the item -- otherwise issue a "Goto item"
prompt instead.
---
 trunk/window-choose.c |  142 +++++++++++++++++++++++++++++++++----------------
 1 file changed, 96 insertions(+), 46 deletions(-)

diff --git a/trunk/window-choose.c b/trunk/window-choose.c
index 79cd06f..c1760e3 100644
--- a/trunk/window-choose.c
+++ b/trunk/window-choose.c
@@ -40,6 +40,11 @@ void window_choose_write_line(
 void   window_choose_scroll_up(struct window_pane *);
 void   window_choose_scroll_down(struct window_pane *);
 
+enum window_choose_input_type {
+       WINDOW_CHOOSE_NORMAL = -1,
+       WINDOW_CHOOSE_GOTO_ITEM,
+};
+
 const struct window_mode window_choose_mode = {
        window_choose_init,
        window_choose_free,
@@ -57,13 +62,18 @@ struct window_choose_mode_data {
        ARRAY_DECL(, struct window_choose_mode_item) list;
        u_int                   top;
        u_int                   selected;
+       enum window_choose_input_type    input_type;
+       const char              *input_prompt;
+       char                    *input_str;
 
        void                    (*callbackfn)(struct window_choose_data *);
        void                    (*freefn)(struct window_choose_data *);
 };
 
-int    window_choose_key_index(struct window_choose_mode_data *, u_int);
-int    window_choose_index_key(struct window_choose_mode_data *, int);
+int    window_choose_index_key(int);
+
+void   window_choose_prompt_input(enum window_choose_input_type,
+           const char *, struct window_pane *, int);
 
 void
 window_choose_add(struct window_pane *wp, struct window_choose_data *wcd)
@@ -108,6 +118,9 @@ window_choose_init(struct window_pane *wp)
 
        data->callbackfn = NULL;
        data->freefn = NULL;
+       data->input_type = WINDOW_CHOOSE_NORMAL;
+       data->input_str = xstrdup("");
+       data->input_prompt = NULL;
 
        ARRAY_INIT(&data->list);
        data->top = 0;
@@ -158,6 +171,7 @@ window_choose_free(struct window_pane *wp)
                free(item->name);
        }
        ARRAY_FREE(&data->list);
+       free(data->input_str);
 
        screen_free(&data->screen);
        free(data);
@@ -192,6 +206,24 @@ window_choose_fire_callback(
        wp->mode = oldmode;
 }
 
+void
+window_choose_prompt_input(enum window_choose_input_type input_type,
+       const char *prompt, struct window_pane *wp, int key)
+{
+       struct window_choose_mode_data  *data = wp->modedata;
+       size_t                           input_len;
+
+       data->input_type = input_type;
+       data->input_prompt = prompt;
+       input_len = strlen(data->input_str) + 2;
+
+       data->input_str = xrealloc(data->input_str, 1, input_len);
+       data->input_str[input_len - 2] = key;
+       data->input_str[input_len - 1] = '\0';
+
+       window_choose_redraw_screen(wp);
+}
+
 /* ARGSUSED */
 void
 window_choose_key(struct window_pane *wp, unused struct session *sess, int key)
@@ -200,6 +232,7 @@ window_choose_key(struct window_pane *wp, unused struct 
session *sess, int key)
        struct screen                   *s = &data->screen;
        struct screen_write_ctx          ctx;
        struct window_choose_mode_item  *item;
+       size_t                           input_len;
        u_int                            items;
        int                              idx;
 
@@ -211,9 +244,21 @@ window_choose_key(struct window_pane *wp, unused struct 
session *sess, int key)
                window_pane_reset_mode(wp);
                break;
        case MODEKEYCHOICE_CHOOSE:
-               item = &ARRAY_ITEM(&data->list, data->selected);
-               window_choose_fire_callback(wp, item->wcd);
-               window_pane_reset_mode(wp);
+               switch (data->input_type) {
+               case WINDOW_CHOOSE_NORMAL:
+                       item = &ARRAY_ITEM(&data->list, data->selected);
+                       window_choose_fire_callback(wp, item->wcd);
+                       window_pane_reset_mode(wp);
+                       break;
+               case WINDOW_CHOOSE_GOTO_ITEM:
+                       if (strtonum(data->input_str, 0, INT_MAX, NULL) > items 
- 1)
+                               break;
+                       item = &ARRAY_ITEM(&data->list, strtonum(
+                                       data->input_str, 0, INT_MAX, NULL));
+                       window_choose_fire_callback(wp, item->wcd);
+                       window_pane_reset_mode(wp);
+                       break;
+               }
                break;
        case MODEKEYCHOICE_UP:
                if (items == 0)
@@ -311,15 +356,35 @@ window_choose_key(struct window_pane *wp, unused struct 
session *sess, int key)
                        data->top = data->selected;
                window_choose_redraw_screen(wp);
                break;
-       default:
-               idx = window_choose_index_key(data, key);
-               if (idx < 0 || (u_int) idx >= ARRAY_LENGTH(&data->list))
+       case MODEKEYCHOICE_BACKSPACE:
+               input_len = strlen(data->input_str);
+               if (input_len > 0)
+                       data->input_str[input_len - 1] = '\0';
+               window_choose_redraw_screen(wp);
+               break;
+       case MODEKEYCHOICE_STARTNUMBERPREFIX:
+               if (key < '0' && key > '9')
                        break;
-               data->selected = idx;
 
-               item = &ARRAY_ITEM(&data->list, data->selected);
-               window_choose_fire_callback(wp, item->wcd);
-               window_pane_reset_mode(wp);
+               /*
+                * If there's less than ten items (0-9) then pressing a number
+                * will automatically select that item; otherwise, prompt for
+                * the item to go to.
+                */
+               if (ARRAY_LENGTH(&data->list) - 1 <= 9) {
+                       idx = window_choose_index_key(key);
+                       if (idx < 0 || (u_int) idx >= ARRAY_LENGTH(&data->list))
+                               break;
+                       data->selected = idx;
+
+                       item = &ARRAY_ITEM(&data->list, data->selected);
+                       window_choose_fire_callback(wp, item->wcd);
+                       window_pane_reset_mode(wp);
+               } else
+                       window_choose_prompt_input(
+                           WINDOW_CHOOSE_GOTO_ITEM, "Goto item", wp, key);
+               break;
+       default:
                break;
        }
 }
@@ -360,66 +425,51 @@ window_choose_write_line(
        struct options                  *oo = &wp->window->options;
        struct screen                   *s = &data->screen;
        struct grid_cell                 gc;
-       int                              utf8flag, key;
+       size_t                           last, xoff = 0;
+       char                             hdr[32];
+       int                              utf8flag;
 
        if (data->callbackfn == NULL)
                fatalx("called before callback assigned");
 
+       last = screen_size_y(s) - 1;
        utf8flag = options_get_number(&wp->window->options, "utf8");
        memcpy(&gc, &grid_default_cell, sizeof gc);
-       if (data->selected == data->top + py) {
-               colour_set_fg(&gc, options_get_number(oo, "mode-fg"));
-               colour_set_bg(&gc, options_get_number(oo, "mode-bg"));
-               gc.attr |= options_get_number(oo, "mode-attr");
-       }
+       if (data->selected == data->top + py)
+               window_mode_attrs(&gc, oo);
 
        screen_write_cursormove(ctx, 0, py);
        if (data->top + py  < ARRAY_LENGTH(&data->list)) {
                item = &ARRAY_ITEM(&data->list, data->top + py);
                winlink_set_alert_colours(item->wcd->wl, &gc);
-               key = window_choose_key_index(data, data->top + py);
-               if (key != -1) {
-                       screen_write_nputs(ctx, screen_size_x(s) - 1,
-                           &gc, utf8flag, "(%c) %s", key, item->name);
-               } else {
-                       screen_write_nputs(ctx, screen_size_x(s) - 1,
-                           &gc, utf8flag, "    %s", item->name);
-               }
+               screen_write_nputs(ctx, screen_size_x(s) - 1,
+                       &gc, utf8flag, "(%d) %s", item->pos, item->name);
 
        }
        while (s->cx < screen_size_x(s))
                screen_write_putc(ctx, &gc, ' ');
-}
 
-int
-window_choose_key_index(struct window_choose_mode_data *data, u_int idx)
-{
-       static const char       keys[] = "0123456789abcdefghijklmnopqrstuvwxyz";
-       const char             *ptr;
-       int                     mkey;
+       if (data->input_type != WINDOW_CHOOSE_NORMAL) {
+               window_mode_attrs(&gc, oo);
 
-       for (ptr = keys; *ptr != '\0'; ptr++) {
-               mkey = mode_key_lookup(&data->mdata, *ptr);
-               if (mkey != MODEKEY_NONE && mkey != MODEKEY_OTHER)
-                       continue;
-               if (idx-- == 0)
-                       return (*ptr);
+               xoff = xsnprintf(hdr, sizeof hdr,
+                       "%s: %s", data->input_prompt, data->input_str);
+               screen_write_cursormove(ctx, 0, last);
+               screen_write_puts(ctx, &gc, "%s", hdr);
+               screen_write_cursormove(ctx, xoff, py);
+               memcpy(&gc, &grid_default_cell, sizeof gc);
        }
-       return (-1);
+
 }
 
 int
-window_choose_index_key(struct window_choose_mode_data *data, int key)
+window_choose_index_key(int key)
 {
-       static const char       keys[] = "0123456789abcdefghijklmnopqrstuvwxyz";
+       static const char       keys[] = "0123456789";
        const char             *ptr;
-       int                     mkey;
        u_int                   idx = 0;
 
        for (ptr = keys; *ptr != '\0'; ptr++) {
-               mkey = mode_key_lookup(&data->mdata, *ptr);
-               if (mkey != MODEKEY_NONE && mkey != MODEKEY_OTHER)
-                       continue;
                if (key == *ptr)
                        return (idx);
                idx++;
-- 
1.7.10


------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
tmux-users mailing list
tmux-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tmux-users

Reply via email to