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