Add a flag to display-menu to select the manu item chosen first, GitHub

issue 3442.
This commit is contained in:
nicm 2023-01-20 21:36:00 +00:00
parent 9789ea3fb4
commit 3aa458ea63
7 changed files with 74 additions and 34 deletions

View File

@ -39,9 +39,10 @@ const struct cmd_entry cmd_display_menu_entry = {
.name = "display-menu", .name = "display-menu",
.alias = "menu", .alias = "menu",
.args = { "c:t:OT:x:y:", 1, -1, cmd_display_menu_args_parse }, .args = { "c:t:S:OT:x:y:", 1, -1, cmd_display_menu_args_parse },
.usage = "[-O] [-c target-client] " CMD_TARGET_PANE_USAGE " [-T title] " .usage = "[-O] [-c target-client] [-S starting-choice] "
"[-x position] [-y position] name key command ...", CMD_TARGET_PANE_USAGE " [-T title] [-x position] "
"[-y position] name key command ...",
.target = { 't', CMD_FIND_PANE, 0 }, .target = { 't', CMD_FIND_PANE, 0 },
@ -288,13 +289,27 @@ cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item)
struct menu *menu = NULL; struct menu *menu = NULL;
struct menu_item menu_item; struct menu_item menu_item;
const char *key, *name; const char *key, *name;
char *title; char *title, *cause;
int flags = 0; int flags = 0, starting_choice = 0;
u_int px, py, i, count = args_count(args); u_int px, py, i, count = args_count(args);
if (tc->overlay_draw != NULL) if (tc->overlay_draw != NULL)
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);
if (args_has(args, 'S')) {
if (strcmp(args_get(args, 'S'), "-") == 0)
starting_choice = -1;
else {
starting_choice = args_strtonum(args, 'S', 0, UINT_MAX,
&cause);
if (cause != NULL) {
cmdq_error(item, "starting choice %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
}
}
if (args_has(args, 'T')) if (args_has(args, 'T'))
title = format_single_from_target(item, args_get(args, 'T')); title = format_single_from_target(item, args_get(args, 'T'));
else else
@ -341,8 +356,8 @@ cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item)
flags |= MENU_STAYOPEN; flags |= MENU_STAYOPEN;
if (!event->m.valid) if (!event->m.valid)
flags |= MENU_NOMOUSE; flags |= MENU_NOMOUSE;
if (menu_display(menu, flags, item, px, py, tc, target, NULL, if (menu_display(menu, flags, starting_choice, item, px, py, tc, target,
NULL) != 0) NULL, NULL) != 0)
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);
return (CMD_RETURN_WAIT); return (CMD_RETURN_WAIT);
} }

55
menu.c
View File

@ -427,12 +427,12 @@ chosen:
} }
struct menu_data * struct menu_data *
menu_prepare(struct menu *menu, int flags, struct cmdq_item *item, u_int px, menu_prepare(struct menu *menu, int flags, int starting_choice,
u_int py, struct client *c, struct cmd_find_state *fs, menu_choice_cb cb, struct cmdq_item *item, u_int px, u_int py, struct client *c,
void *data) struct cmd_find_state *fs, menu_choice_cb cb, void *data)
{ {
struct menu_data *md; struct menu_data *md;
u_int i; int choice;
const char *name; const char *name;
if (c->tty.sx < menu->width + 4 || c->tty.sy < menu->count + 2) if (c->tty.sx < menu->width + 4 || c->tty.sy < menu->count + 2)
@ -457,18 +457,38 @@ menu_prepare(struct menu *menu, int flags, struct cmdq_item *item, u_int px,
md->py = py; md->py = py;
md->menu = menu; md->menu = menu;
md->choice = -1;
if (md->flags & MENU_NOMOUSE) { if (md->flags & MENU_NOMOUSE) {
for (i = 0; i < menu->count; i++) { if (starting_choice >= (int)menu->count) {
name = menu->items[i].name; starting_choice = menu->count - 1;
if (name != NULL && *name != '-') choice = starting_choice + 1;
for (;;) {
name = menu->items[choice - 1].name;
if (name != NULL && *name != '-') {
md->choice = choice - 1;
break; break;
} }
if (i != menu->count) if (--choice == 0)
md->choice = i; choice = menu->count;
else if (choice == starting_choice + 1)
md->choice = -1; break;
} else }
md->choice = -1; } else if (starting_choice >= 0) {
choice = starting_choice;
for (;;) {
name = menu->items[choice].name;
if (name != NULL && *name != '-') {
md->choice = choice;
break;
}
if (++choice == (int)menu->count)
choice = 0;
if (choice == starting_choice)
break;
}
}
}
md->cb = cb; md->cb = cb;
md->data = data; md->data = data;
@ -476,13 +496,14 @@ menu_prepare(struct menu *menu, int flags, struct cmdq_item *item, u_int px,
} }
int int
menu_display(struct menu *menu, int flags, struct cmdq_item *item, u_int px, menu_display(struct menu *menu, int flags, int starting_choice,
u_int py, struct client *c, struct cmd_find_state *fs, menu_choice_cb cb, struct cmdq_item *item, u_int px, u_int py, struct client *c,
void *data) struct cmd_find_state *fs, menu_choice_cb cb, void *data)
{ {
struct menu_data *md; struct menu_data *md;
md = menu_prepare(menu, flags, item, px, py, c, fs, cb, data); md = menu_prepare(menu, flags, starting_choice, item, px, py, c, fs, cb,
data);
if (md == NULL) if (md == NULL)
return (-1); return (-1);
server_client_set_overlay(c, 0, NULL, menu_mode_cb, menu_draw_cb, server_client_set_overlay(c, 0, NULL, menu_mode_cb, menu_draw_cb,

View File

@ -962,8 +962,8 @@ mode_tree_display_menu(struct mode_tree_data *mtd, struct client *c, u_int x,
x -= (menu->width + 4) / 2; x -= (menu->width + 4) / 2;
else else
x = 0; x = 0;
if (menu_display(menu, 0, NULL, x, y, c, NULL, mode_tree_menu_callback, if (menu_display(menu, 0, 0, NULL, x, y, c, NULL,
mtm) != 0) mode_tree_menu_callback, mtm) != 0)
menu_free(menu); menu_free(menu);
} }

View File

@ -574,7 +574,7 @@ menu:
x = m->x - (pd->menu->width + 4) / 2; x = m->x - (pd->menu->width + 4) / 2;
else else
x = 0; x = 0;
pd->md = menu_prepare(pd->menu, 0, NULL, x, m->y, c, NULL, pd->md = menu_prepare(pd->menu, 0, 0, NULL, x, m->y, c, NULL,
popup_menu_done, pd); popup_menu_done, pd);
c->flags |= CLIENT_REDRAWOVERLAY; c->flags |= CLIENT_REDRAWOVERLAY;

View File

@ -1766,7 +1766,7 @@ status_prompt_complete_list_menu(struct client *c, char **list, u_int size,
else else
offset = 0; offset = 0;
if (menu_display(menu, MENU_NOMOUSE|MENU_TAB, NULL, offset, if (menu_display(menu, MENU_NOMOUSE|MENU_TAB, 0, NULL, offset,
py, c, NULL, status_prompt_menu_callback, spm) != 0) { py, c, NULL, status_prompt_menu_callback, spm) != 0) {
menu_free(menu); menu_free(menu);
free(spm); free(spm);
@ -1859,7 +1859,7 @@ status_prompt_complete_window_menu(struct client *c, struct session *s,
else else
offset = 0; offset = 0;
if (menu_display(menu, MENU_NOMOUSE|MENU_TAB, NULL, offset, if (menu_display(menu, MENU_NOMOUSE|MENU_TAB, 0, NULL, offset,
py, c, NULL, status_prompt_menu_callback, spm) != 0) { py, c, NULL, status_prompt_menu_callback, spm) != 0) {
menu_free(menu); menu_free(menu);
free(spm); free(spm);

4
tmux.1
View File

@ -5815,6 +5815,7 @@ until it is dismissed.
.Op Fl O .Op Fl O
.Op Fl c Ar target-client .Op Fl c Ar target-client
.Op Fl t Ar target-pane .Op Fl t Ar target-pane
.Op Fl S Ar starting-choice
.Op Fl T Ar title .Op Fl T Ar title
.Op Fl x Ar position .Op Fl x Ar position
.Op Fl y Ar position .Op Fl y Ar position
@ -5844,6 +5845,9 @@ command should be omitted.
.Fl T .Fl T
is a format for the menu title (see is a format for the menu title (see
.Sx FORMATS ) . .Sx FORMATS ) .
.Fl S
sets the menu item selected by default, if the menu is not bound to a mouse key
binding.
.Pp .Pp
.Fl x .Fl x
and and

8
tmux.h
View File

@ -3292,11 +3292,11 @@ void menu_add_item(struct menu *, const struct menu_item *,
struct cmdq_item *, struct client *, struct cmdq_item *, struct client *,
struct cmd_find_state *); struct cmd_find_state *);
void menu_free(struct menu *); void menu_free(struct menu *);
struct menu_data *menu_prepare(struct menu *, int, struct cmdq_item *, u_int, struct menu_data *menu_prepare(struct menu *, int, int, struct cmdq_item *,
u_int, struct client *, struct cmd_find_state *, u_int, u_int, struct client *, struct cmd_find_state *,
menu_choice_cb, void *); menu_choice_cb, void *);
int menu_display(struct menu *, int, struct cmdq_item *, u_int, int menu_display(struct menu *, int, int, struct cmdq_item *,
u_int, struct client *, struct cmd_find_state *, u_int, u_int, struct client *, struct cmd_find_state *,
menu_choice_cb, void *); menu_choice_cb, void *);
struct screen *menu_mode_cb(struct client *, void *, u_int *, u_int *); struct screen *menu_mode_cb(struct client *, void *, u_int *, u_int *);
void menu_check_cb(struct client *, void *, u_int, u_int, u_int, void menu_check_cb(struct client *, void *, u_int, u_int, u_int,