Merge branch 'obsd-master'

This commit is contained in:
Thomas Adam 2019-05-28 09:02:26 +01:00
commit c0116b2c5b
10 changed files with 203 additions and 222 deletions

View File

@ -34,9 +34,9 @@ const struct cmd_entry cmd_display_menu_entry = {
.name = "display-menu", .name = "display-menu",
.alias = "menu", .alias = "menu",
.args = { "c:FM:t:T:x:y:", 0, 0 }, .args = { "c:t:T:x:y:", 1, -1 },
.usage = "[-F] [-c target-client] [-M menu] " CMD_TARGET_PANE_USAGE " " .usage = "[-c target-client] " CMD_TARGET_PANE_USAGE " [-T title] "
"[-T title] [-x position] [-y position]", "[-x position] [-y position] name key command ...",
.target = { 't', CMD_FIND_PANE, 0 }, .target = { 't', CMD_FIND_PANE, 0 },
@ -55,10 +55,11 @@ cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item)
struct cmd_find_state *fs = &item->target; struct cmd_find_state *fs = &item->target;
struct menu *menu = NULL; struct menu *menu = NULL;
struct style_range *sr; struct style_range *sr;
const char *string, *xp, *yp; struct menu_item menu_item;
int at, flags; const char *xp, *yp, *key;
char *title, *name;
int at, flags, i;
u_int px, py, ox, oy, sx, sy; u_int px, py, ox, oy, sx, sy;
char *title;
if ((c = cmd_find_client(item, args_get(args, 'c'), 0)) == NULL) if ((c = cmd_find_client(item, args_get(args, 'c'), 0)) == NULL)
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
@ -66,23 +67,37 @@ cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item)
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);
at = status_at_line(c); at = status_at_line(c);
string = args_get(args, 'M');
if (string == NULL) {
cmdq_error(item, "no menu specified");
return (CMD_RETURN_ERROR);
}
if (args_has(args, 'F'))
string = format_single(NULL, string, c, s, wl, wp);
else
string = xstrdup(string);
if (args_has(args, 'T')) if (args_has(args, 'T'))
title = format_single(NULL, args_get(args, 'T'), c, s, wl, wp); title = format_single(NULL, args_get(args, 'T'), c, s, wl, wp);
else else
title = xstrdup(""); title = xstrdup("");
menu = menu_create(string, item, c, fs, title);
menu = menu_create(title);
for (i = 0; i != args->argc; /* nothing */) {
name = args->argv[i++];
if (*name == '\0') {
menu_add_item(menu, NULL, item, c, fs);
continue;
}
if (args->argc - i < 2) {
cmdq_error(item, "not enough arguments");
free(title);
menu_free(menu);
return (CMD_RETURN_ERROR);
}
key = args->argv[i++];
menu_item.name = name;
menu_item.key = key_string_lookup_string(key);
menu_item.command = args->argv[i++];
menu_add_item(menu, &menu_item, item, c, fs);
}
free(title); free(title);
if (menu == NULL) { if (menu == NULL) {
cmdq_error(item, "invalid menu %s", string); cmdq_error(item, "invalid menu arguments");
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
if (menu->count == 0) { if (menu->count == 0) {

View File

@ -54,52 +54,6 @@ static void format_defaults_session(struct format_tree *,
static void format_defaults_client(struct format_tree *, struct client *); static void format_defaults_client(struct format_tree *, struct client *);
static void format_defaults_winlink(struct format_tree *, struct winlink *); static void format_defaults_winlink(struct format_tree *, struct winlink *);
/* Default menus. */
#define DEFAULT_CLIENT_MENU \
"Detach,d,detach-client|" \
"Detach & Kill,X,detach-client -P|" \
"Detach Others,o,detach-client -a|" \
"|" \
"Lock,l,lock-client"
#define DEFAULT_SESSION_MENU \
"Next,n,switch-client -n|" \
"Previous,p,switch-client -p|" \
"|" \
"Renumber,N,move-window -r|" \
"Rename,n,command-prompt -I \"#S\" \"rename-session -- '%%'\"|" \
"|" \
"New Session,s,new-session|" \
"New Window,w,new-window"
#define DEFAULT_WINDOW_MENU \
"Swap Left,l,swap-window -t:-1|" \
"Swap Right,r,swap-window -t:+1|" \
"#{?pane_marked_set,,#[dim]}Swap Marked,s,swap-window|" \
"|" \
"Kill,X,kill-window|" \
"Respawn,R,respawn-window -k|" \
"#{?pane_marked,Unmark,Mark},m,select-pane -m|" \
"Rename,n,command-prompt -I \"#W\" \"rename-window -- '%%'\"|" \
"|" \
"New After,w,new-window -a|" \
"New At End,W,new-window"
#define DEFAULT_PANE_MENU \
"#{?mouse_word,Search For #[underscore]#{=/9/...:mouse_word},},C-r,copy-mode -t=; send -Xt= search-backward \"#{q:mouse_word}\"|" \
"#{?mouse_word,Type #[underscore]#{=/9/...:mouse_word},},C-y,send-keys -l \"#{q:mouse_word}\"|" \
"#{?mouse_word,Copy #[underscore]#{=/9/...:mouse_word},},c,set-buffer \"#{q:mouse_word}\"|" \
"#{?mouse_line,Copy Line,},l,set-buffer \"#{q:mouse_line}\"|" \
"|" \
"Horizontal Split,h,split-window -h|" \
"Vertical Split,v,split-window -v|" \
"|" \
"Swap Up,u,swap-pane -U|" \
"Swap Down,d,swap-pane -D|" \
"#{?pane_marked_set,,#[dim]}Swap Marked,s,swap-pane|" \
"|" \
"Kill,X,kill-pane|" \
"Respawn,R,respawn-pane -k|" \
"#{?pane_marked,Unmark,Mark},m,select-pane -m|" \
"#{?window_zoomed_flag,Unzoom,Zoom},z,resize-pane -Z"
/* Entry in format job tree. */ /* Entry in format job tree. */
struct format_job { struct format_job {
struct client *client; struct client *client;
@ -960,11 +914,6 @@ format_create(struct client *c, struct cmdq_item *item, int tag, int flags)
} }
} }
format_add(ft, "client_menu", "%s", DEFAULT_CLIENT_MENU);
format_add(ft, "session_menu", "%s", DEFAULT_SESSION_MENU);
format_add(ft, "window_menu", "%s", DEFAULT_WINDOW_MENU);
format_add(ft, "pane_menu", "%s", DEFAULT_PANE_MENU);
if (item != NULL) if (item != NULL)
format_create_add_item(ft, item); format_create_add_item(ft, item);

View File

@ -280,10 +280,51 @@ key_bindings_init(void)
"bind -n MouseDrag1Pane if -Ft= '#{mouse_any_flag}' 'if -Ft= \"#{pane_in_mode}\" \"copy-mode -M\" \"send-keys -M\"' 'copy-mode -M'", "bind -n MouseDrag1Pane if -Ft= '#{mouse_any_flag}' 'if -Ft= \"#{pane_in_mode}\" \"copy-mode -M\" \"send-keys -M\"' 'copy-mode -M'",
"bind -n MouseDown3Pane if -Ft= '#{||:mouse_any_flag,pane_in_mode}' 'select-pane -t=; send-keys -M' 'select-pane -mt='", "bind -n MouseDown3Pane if -Ft= '#{||:mouse_any_flag,pane_in_mode}' 'select-pane -t=; send-keys -M' 'select-pane -mt='",
"bind -n WheelUpPane if -Ft= '#{mouse_any_flag}' 'send-keys -M' 'if -Ft= \"#{pane_in_mode}\" \"send-keys -M\" \"copy-mode -et=\"'", "bind -n WheelUpPane if -Ft= '#{mouse_any_flag}' 'send-keys -M' 'if -Ft= \"#{pane_in_mode}\" \"send-keys -M\" \"copy-mode -et=\"'",
"bind -n MouseDown3StatusRight display-menu -t= -xM -yS -F -M \"#{client_menu}\" -T \"#[align=centre]#{client_name}\"",
"bind -n MouseDown3StatusLeft display-menu -t= -xM -yS -F -M \"#{session_menu}\" -T \"#[align=centre]#{session_name}\"", "bind -n MouseDown3StatusRight display-menu -t= -xM -yS -T \"#[align=centre]#{client_name}\""
"bind -n MouseDown3Status display-menu -t= -xW -yS -F -M \"#{window_menu}\" -T \"#[align=centre]#{window_index}:#{window_name}\"", " 'Detach' 'd' {detach-client}"
"bind -n M-MouseDown3Pane display-menu -t= -xM -yM -F -M \"#{pane_menu}\" -T \"#[align=centre]#{pane_index} (#{pane_id})\"", " 'Detach & Kill' 'X' {detach-client -P}"
" 'Detach Others' 'o' {detach-client -a}"
" ''"
" 'Lock' 'l' {lock-client}",
"bind -n MouseDown3StatusLeft display-menu -t= -xM -yS -T \"#[align=centre]#{session_name}\""
" 'Next' 'n' {switch-client -n}"
" 'Previous' 'p' {switch-client -p}"
" ''"
" 'Renumber' 'N' {move-window -r}"
" 'Rename' 'n' {command-prompt -I \"#S\" \"rename-session -- '%%'\"}"
" ''"
" 'New Session' 's' {new-session}"
" 'New Window' 'w' {new-window}",
"bind -n MouseDown3Status display-menu -t= -xW -yS -T \"#[align=centre]#{window_index}:#{window_name}\""
" 'Swap Left' 'l' {swap-window -t:-1}"
" 'Swap Right' 'r' {swap-window -t:+1}"
" '#{?pane_marked_set,,#[dim]}Swap Marked' 's' {swap-window}"
" ''"
" 'Kill' 'X' {kill-window}"
" 'Respawn' 'R' {respawn-window -k}"
" '#{?pane_marked,Unmark,Mark}' 'm' {select-pane -m}"
" 'Rename' 'n' {command-prompt -I \"#W\" \"rename-window -- '%%'\"}"
" ''"
" 'New After' 'w' {new-window -a}"
" 'New At End' 'W' {new-window}",
"bind -n M-MouseDown3Pane display-menu -t= -xM -yM -T \"#[align=centre]#{pane_index} (#{pane_id})\""
" '#{?mouse_word,Search For #[underscore]#{=/9/...:mouse_word},}' 'C-r' {copy-mode -t=; send -Xt= search-backward \"#{q:mouse_word}\"}"
" '#{?mouse_word,Type #[underscore]#{=/9/...:mouse_word},}' 'C-y' {send-keys -l -- \"#{q:mouse_word}\"}"
" '#{?mouse_word,Copy #[underscore]#{=/9/...:mouse_word},}' 'c' {set-buffer -- \"#{q:mouse_word}\"}"
" '#{?mouse_line,Copy Line,}' 'l' {set-buffer -- \"#{q:mouse_line}\"}"
" ''"
" 'Horizontal Split' 'h' {split-window -h}"
" 'Vertical Split' 'v' {split-window -v}"
" ''"
" 'Swap Up' 'u' {swap-pane -U}"
" 'Swap Down' 'd' {swap-pane -D}"
" '#{?pane_marked_set,,#[dim]}Swap Marked' 's' {swap-pane}"
" ''"
" 'Kill' 'X' {kill-pane}"
" 'Respawn' 'R' {respawn-pane -k}"
" '#{?pane_marked,Unmark,Mark}' 'm' {select-pane -m}"
" '#{?window_zoomed_flag,Unzoom,Zoom}' 'z' {resize-pane -Z}",
"bind -Tcopy-mode C-Space send -X begin-selection", "bind -Tcopy-mode C-Space send -X begin-selection",
"bind -Tcopy-mode C-a send -X start-of-line", "bind -Tcopy-mode C-a send -X start-of-line",

114
menu.c
View File

@ -40,49 +40,63 @@ struct menu_data {
void *data; void *data;
}; };
static void void
menu_add_item(struct menu *menu, struct menu_item *item, menu_add_items(struct menu *menu, const struct menu_item *items,
struct cmdq_item *qitem, struct client *c, struct cmd_find_state *fs)
{
const struct menu_item *loop;
for (loop = items; loop->name != NULL; loop++)
menu_add_item(menu, loop, qitem, c, fs);
}
void
menu_add_item(struct menu *menu, const struct menu_item *item,
struct cmdq_item *qitem, struct client *c, struct cmd_find_state *fs) struct cmdq_item *qitem, struct client *c, struct cmd_find_state *fs)
{ {
struct menu_item *new_item; struct menu_item *new_item;
const char *key; const char *key, *cmd;
char *name; char *s, *name;
u_int width; u_int width;
int line;
line = (item == NULL || item->name == NULL || *item->name == '\0');
if (line && menu->count == 0)
return;
menu->items = xreallocarray(menu->items, menu->count + 1, menu->items = xreallocarray(menu->items, menu->count + 1,
sizeof *menu->items); sizeof *menu->items);
new_item = &menu->items[menu->count++]; new_item = &menu->items[menu->count++];
memset(new_item, 0, sizeof *new_item); memset(new_item, 0, sizeof *new_item);
if (item == NULL || *item->name == '\0') /* horizontal line */ if (line)
return; return;
if (fs != NULL) {
name = format_single(qitem, item->name, c, fs->s, fs->wl, if (fs != NULL)
fs->wp); s = format_single(qitem, item->name, c, fs->s, fs->wl, fs->wp);
} else else
name = format_single(qitem, item->name, c, NULL, NULL, NULL); s = format_single(qitem, item->name, c, NULL, NULL, NULL);
if (*name == '\0') { /* no item if empty after format expanded */ if (*s == '\0') { /* no item if empty after format expanded */
menu->count--; menu->count--;
return; return;
} }
if (item->key != KEYC_UNKNOWN) { if (item->key != KEYC_UNKNOWN && item->key != KEYC_NONE) {
key = key_string_lookup_key(item->key); key = key_string_lookup_key(item->key);
xasprintf(&new_item->name, "%s#[default] #[align=right](%s)", xasprintf(&name, "%s#[default] #[align=right](%s)", s, key);
name, key);
} else } else
xasprintf(&new_item->name, "%s", name); xasprintf(&name, "%s", s);
free(name); new_item->name = name;
free(s);
if (item->command != NULL) { cmd = item->command;
if (fs != NULL) { if (cmd != NULL) {
new_item->command = format_single(qitem, item->command, if (fs != NULL)
c, fs->s, fs->wl, fs->wp); s = format_single(qitem, cmd, c, fs->s, fs->wl, fs->wp);
} else { else
new_item->command = format_single(qitem, item->command, s = format_single(qitem, cmd, c, NULL, NULL, NULL);
c, NULL, NULL, NULL);
}
} else } else
new_item->command = NULL; s = NULL;
new_item->command = s;
new_item->key = item->key; new_item->key = item->key;
width = format_width(new_item->name); width = format_width(new_item->name);
@ -90,56 +104,14 @@ menu_add_item(struct menu *menu, struct menu_item *item,
menu->width = width; menu->width = width;
} }
static void
menu_parse_item(struct menu *menu, const char *s, struct cmdq_item *qitem,
struct client *c, struct cmd_find_state *fs)
{
char *copy, *first;
const char *second, *third;
struct menu_item item;
first = copy = xstrdup(s);
if ((second = format_skip(first, ",")) != NULL) {
*(char *)second++ = '\0';
if ((third = format_skip(second, ",")) != NULL) {
*(char *)third++ = '\0';
item.name = first;
item.command = (char *)third;
item.key = key_string_lookup_string(second);
menu_add_item(menu, &item, qitem, c, fs);
}
}
free(copy);
}
struct menu * struct menu *
menu_create(const char *s, struct cmdq_item *qitem, struct client *c, menu_create(const char *title)
struct cmd_find_state *fs, const char *title)
{ {
struct menu *menu; struct menu *menu;
char *copy, *string, *next;
if (*s == '\0')
return (NULL);
menu = xcalloc(1, sizeof *menu); menu = xcalloc(1, sizeof *menu);
menu->title = xstrdup(title); menu->title = xstrdup(title);
copy = string = xstrdup(s);
do {
next = (char *)format_skip(string, "|");
if (next != NULL)
*next++ = '\0';
if (*string == '\0') {
if (menu->count != 0)
menu_add_item(menu, NULL, qitem, c, fs);
} else
menu_parse_item(menu, string, qitem, c, fs);
string = next;
} while (next != NULL);
free(copy);
return (menu); return (menu);
} }
@ -149,12 +121,12 @@ menu_free(struct menu *menu)
u_int i; u_int i;
for (i = 0; i < menu->count; i++) { for (i = 0; i < menu->count; i++) {
free(menu->items[i].name); free((void *)menu->items[i].name);
free(menu->items[i].command); free((void *)menu->items[i].command);
} }
free(menu->items); free(menu->items);
free(menu->title); free((void *)menu->title);
free(menu); free(menu);
} }

View File

@ -35,7 +35,7 @@ struct mode_tree_data {
struct window_pane *wp; struct window_pane *wp;
void *modedata; void *modedata;
const char *menu; const struct menu_item *menu;
const char **sort_list; const char **sort_list;
u_int sort_size; u_int sort_size;
@ -100,11 +100,14 @@ struct mode_tree_menu {
static void mode_tree_free_items(struct mode_tree_list *); static void mode_tree_free_items(struct mode_tree_list *);
#define MODE_TREE_MENU \ static const struct menu_item mode_tree_menu_items[] = {
"Scroll Left,<,|" \ { "Scroll Left", '<', NULL },
"Scroll Right,>,|" \ { "Scroll Right", '>', NULL },
"|" \ { "", KEYC_NONE, NULL },
"Cancel,q," { "Cancel", 'q', NULL },
{ NULL, KEYC_NONE, NULL }
};
static struct mode_tree_item * static struct mode_tree_item *
mode_tree_find_item(struct mode_tree_list *mtl, uint64_t tag) mode_tree_find_item(struct mode_tree_list *mtl, uint64_t tag)
@ -315,7 +318,7 @@ struct mode_tree_data *
mode_tree_start(struct window_pane *wp, struct args *args, mode_tree_start(struct window_pane *wp, struct args *args,
mode_tree_build_cb buildcb, mode_tree_draw_cb drawcb, mode_tree_build_cb buildcb, mode_tree_draw_cb drawcb,
mode_tree_search_cb searchcb, mode_tree_menu_cb menucb, void *modedata, mode_tree_search_cb searchcb, mode_tree_menu_cb menucb, void *modedata,
const char *menu, const char **sort_list, u_int sort_size, const struct menu_item *menu, const char **sort_list, u_int sort_size,
struct screen **s) struct screen **s)
{ {
struct mode_tree_data *mtd; struct mode_tree_data *mtd;
@ -812,8 +815,8 @@ mode_tree_display_menu(struct mode_tree_data *mtd, struct client *c, u_int x,
{ {
struct mode_tree_item *mti; struct mode_tree_item *mti;
struct menu *menu; struct menu *menu;
const struct menu_item *items;
struct mode_tree_menu *mtm; struct mode_tree_menu *mtm;
const char *s;
char *title; char *title;
u_int line; u_int line;
@ -824,16 +827,15 @@ mode_tree_display_menu(struct mode_tree_data *mtd, struct client *c, u_int x,
mti = mtd->line_list[line].item; mti = mtd->line_list[line].item;
if (!outside) { if (!outside) {
s = mtd->menu; items = mtd->menu;
xasprintf(&title, "#[align=centre]%s", mti->name); xasprintf(&title, "#[align=centre]%s", mti->name);
} else { } else {
s = MODE_TREE_MENU; items = mode_tree_menu_items;
title = xstrdup(""); title = xstrdup("");
} }
menu = menu_create(s, NULL, c, NULL, title); menu = menu_create(title);
menu_add_items(menu, items, NULL, NULL, NULL);
free(title); free(title);
if (menu == NULL)
return;
mtm = xmalloc(sizeof *mtm); mtm = xmalloc(sizeof *mtm);
mtm->data = mtd; mtm->data = mtd;

33
tmux.1
View File

@ -4128,7 +4128,6 @@ The following variables are available, where appropriate:
.It Li "client_height" Ta "" Ta "Height of client" .It Li "client_height" Ta "" Ta "Height of client"
.It Li "client_key_table" Ta "" Ta "Current key table" .It Li "client_key_table" Ta "" Ta "Current key table"
.It Li "client_last_session" Ta "" Ta "Name of the client's last session" .It Li "client_last_session" Ta "" Ta "Name of the client's last session"
.It Li "client_menu" Ta "" Ta "The default client menu"
.It Li "client_name" Ta "" Ta "Name of client" .It Li "client_name" Ta "" Ta "Name of client"
.It Li "client_pid" Ta "" Ta "PID of client process" .It Li "client_pid" Ta "" Ta "PID of client process"
.It Li "client_prefix" Ta "" Ta "1 if prefix key has been pressed" .It Li "client_prefix" Ta "" Ta "1 if prefix key has been pressed"
@ -4190,7 +4189,6 @@ The following variables are available, where appropriate:
.It Li "pane_left" Ta "" Ta "Left of pane" .It Li "pane_left" Ta "" Ta "Left of pane"
.It Li "pane_marked" Ta "" Ta "1 if this is the marked pane" .It Li "pane_marked" Ta "" Ta "1 if this is the marked pane"
.It Li "pane_marked_set" Ta "" Ta "1 if a marked pane is set" .It Li "pane_marked_set" Ta "" Ta "1 if a marked pane is set"
.It Li "pane_menu" Ta "" Ta "The default pane menu"
.It Li "pane_mode" Ta "" Ta "Name of pane mode, if any." .It Li "pane_mode" Ta "" Ta "Name of pane mode, if any."
.It Li "pane_pid" Ta "" Ta "PID of first process in pane" .It Li "pane_pid" Ta "" Ta "PID of first process in pane"
.It Li "pane_pipe" Ta "" Ta "1 if pane is being piped" .It Li "pane_pipe" Ta "" Ta "1 if pane is being piped"
@ -4221,7 +4219,6 @@ The following variables are available, where appropriate:
.It Li "session_id" Ta "" Ta "Unique session ID" .It Li "session_id" Ta "" Ta "Unique session ID"
.It Li "session_last_attached" Ta "" Ta "Time session last attached" .It Li "session_last_attached" Ta "" Ta "Time session last attached"
.It Li "session_many_attached" Ta "" Ta "1 if multiple clients attached" .It Li "session_many_attached" Ta "" Ta "1 if multiple clients attached"
.It Li "session_menu" Ta "" Ta "The default session menu"
.It Li "session_name" Ta "#S" Ta "Name of session" .It Li "session_name" Ta "#S" Ta "Name of session"
.It Li "session_stack" Ta "" Ta "Window indexes in most recent order" .It Li "session_stack" Ta "" Ta "Window indexes in most recent order"
.It Li "session_windows" Ta "" Ta "Number of windows in session" .It Li "session_windows" Ta "" Ta "Number of windows in session"
@ -4242,7 +4239,6 @@ The following variables are available, where appropriate:
.It Li "window_last_flag" Ta "" Ta "1 if window is the last used" .It Li "window_last_flag" Ta "" Ta "1 if window is the last used"
.It Li "window_layout" Ta "" Ta "Window layout description, ignoring zoomed window panes" .It Li "window_layout" Ta "" Ta "Window layout description, ignoring zoomed window panes"
.It Li "window_linked" Ta "" Ta "1 if window is linked across sessions" .It Li "window_linked" Ta "" Ta "1 if window is linked across sessions"
.It Li "window_menu" Ta "" Ta "The default window menu"
.It Li "window_name" Ta "#W" Ta "Name of window" .It Li "window_name" Ta "#W" Ta "Name of window"
.It Li "window_offset_x" Ta "" Ta "X offset into window if larger than client" .It Li "window_offset_x" Ta "" Ta "X offset into window if larger than client"
.It Li "window_offset_y" Ta "" Ta "Y offset into window if larger than client" .It Li "window_offset_y" Ta "" Ta "Y offset into window if larger than client"
@ -4661,13 +4657,15 @@ option.
This command works only from inside This command works only from inside
.Nm . .Nm .
.It Xo Ic display-menu .It Xo Ic display-menu
.Op Fl F
.Op Fl c Ar target-client .Op Fl c Ar target-client
.Op Fl M Ar menu
.Op Fl t Ar target-pane .Op Fl t Ar target-pane
.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
.Ar name
.Ar key
.Ar command
.Ar ...
.Xc .Xc
.D1 (alias: Ic menu ) .D1 (alias: Ic menu )
Display a menu on Display a menu on
@ -4675,27 +4673,16 @@ Display a menu on
.Ar target-pane .Ar target-pane
gives the target for any commands run from the menu. gives the target for any commands run from the menu.
.Pp .Pp
A menu is passed to A menu is passed as a series of arguments: first the menu item name,
.Fl M second the key shortcut (or empty for none) and third the command
as a list of menu items separated by to run when the menu item is chosen.
.Ql | . The name and command are formats, see the
Each menu item consists of three comma-separated parts:
.Bl -enum -width Ds
.It
The menu item name.
This is a format and may include embedded styles, see the
.Sx FORMATS .Sx FORMATS
and and
.Sx STYLES .Sx STYLES
sections. sections.
.It The name may be empty for a separator line, in which case both the key and
The menu item shortcut key. command should be omitted.
If this is empty the menu item has no key shortcut.
.It
The command run when the menu item is chosen.
.El
.Pp
An empty menu item is a separator line.
.Pp .Pp
.Fl T .Fl T
is a format for the menu title (see is a format for the menu title (see

20
tmux.h
View File

@ -754,12 +754,12 @@ struct screen_redraw_ctx {
/* Menu. */ /* Menu. */
struct menu_item { struct menu_item {
char *name; const char *name;
char *command;
key_code key; key_code key;
const char *command;
}; };
struct menu { struct menu {
char *title; const char *title;
struct menu_item *items; struct menu_item *items;
u_int count; u_int count;
u_int width; u_int width;
@ -2469,8 +2469,8 @@ void mode_tree_each_tagged(struct mode_tree_data *, mode_tree_each_cb,
void mode_tree_down(struct mode_tree_data *, int); void mode_tree_down(struct mode_tree_data *, int);
struct mode_tree_data *mode_tree_start(struct window_pane *, struct args *, struct mode_tree_data *mode_tree_start(struct window_pane *, struct args *,
mode_tree_build_cb, mode_tree_draw_cb, mode_tree_search_cb, mode_tree_build_cb, mode_tree_draw_cb, mode_tree_search_cb,
mode_tree_menu_cb, void *, const char *, const char **, u_int, mode_tree_menu_cb, void *, const struct menu_item *, const char **,
struct screen **); u_int, struct screen **);
void mode_tree_zoom(struct mode_tree_data *, struct args *); void mode_tree_zoom(struct mode_tree_data *, struct args *);
void mode_tree_build(struct mode_tree_data *); void mode_tree_build(struct mode_tree_data *);
void mode_tree_free(struct mode_tree_data *); void mode_tree_free(struct mode_tree_data *);
@ -2604,8 +2604,14 @@ __dead void printflike(1, 2) fatal(const char *, ...);
__dead void printflike(1, 2) fatalx(const char *, ...); __dead void printflike(1, 2) fatalx(const char *, ...);
/* menu.c */ /* menu.c */
struct menu *menu_create(const char *, struct cmdq_item *, struct client *, struct menu *menu_create(const char *);
struct cmd_find_state *, const char *); void menu_add_items(struct menu *, const struct menu_item *,
struct cmdq_item *, struct client *,
struct cmd_find_state *);
void menu_add_item(struct menu *, const struct menu_item *,
struct cmdq_item *, struct client *,
struct cmd_find_state *);
void menu_free(struct menu *); void menu_free(struct menu *);
int menu_display(struct menu *, int, struct cmdq_item *, u_int, int menu_display(struct menu *, int, struct cmdq_item *, u_int,
u_int, struct client *, struct cmd_find_state *, u_int, struct client *, struct cmd_find_state *,

View File

@ -38,18 +38,21 @@ static void window_buffer_key(struct window_mode_entry *,
#define WINDOW_BUFFER_DEFAULT_FORMAT \ #define WINDOW_BUFFER_DEFAULT_FORMAT \
"#{buffer_size} bytes (#{t:buffer_created})" "#{buffer_size} bytes (#{t:buffer_created})"
#define WINDOW_BUFFER_MENU \ static const struct menu_item window_buffer_menu_items[] = {
"Paste,p,|" \ { "Paste", 'p', NULL },
"Paste Tagged,P,|" \ { "Paste Tagged", 'P', NULL },
"|" \ { "", KEYC_NONE, NULL },
"Tag,t,|" \ { "Tag", 't', NULL },
"Tag All,C-t,|" \ { "Tag All", '\024', NULL },
"Tag None,T,|" \ { "Tag None", 'T', NULL },
"|" \ { "", KEYC_NONE, NULL },
"Delete,d,|" \ { "Delete", 'd', NULL },
"Delete Tagged,D,|" \ { "Delete Tagged", 'D', NULL },
"|" \ { "", KEYC_NONE, NULL },
"Cancel,q," { "Cancel", 'q', NULL },
{ NULL, KEYC_NONE, NULL }
};
const struct window_mode window_buffer_mode = { const struct window_mode window_buffer_mode = {
.name = "buffer-mode", .name = "buffer-mode",
@ -314,7 +317,7 @@ window_buffer_init(struct window_mode_entry *wme, struct cmd_find_state *fs,
data->data = mode_tree_start(wp, args, window_buffer_build, data->data = mode_tree_start(wp, args, window_buffer_build,
window_buffer_draw, window_buffer_search, window_buffer_menu, data, window_buffer_draw, window_buffer_search, window_buffer_menu, data,
WINDOW_BUFFER_MENU, window_buffer_sort_list, window_buffer_menu_items, window_buffer_sort_list,
nitems(window_buffer_sort_list), &s); nitems(window_buffer_sort_list), &s);
mode_tree_zoom(data->data, args); mode_tree_zoom(data->data, args);

View File

@ -40,15 +40,18 @@ static void window_client_key(struct window_mode_entry *,
"session #{session_name} " \ "session #{session_name} " \
"(#{client_width}x#{client_height}, #{t:client_activity})" "(#{client_width}x#{client_height}, #{t:client_activity})"
#define WINDOW_CLIENT_MENU \ static const struct menu_item window_client_menu_items[] = {
"Detach,d,|" \ { "Detach", 'd', NULL },
"Detach Tagged,D,|" \ { "Detach Tagged", 'D', NULL },
"|" \ { "", KEYC_NONE, NULL },
"Tag,t,|" \ { "Tag", 't', NULL },
"Tag All,C-t,|" \ { "Tag All", '\024', NULL },
"Tag None,T,|" \ { "Tag None", 'T', NULL },
"|" \ { "", KEYC_NONE, NULL },
"Cancel,q," { "Cancel", 'q', NULL },
{ NULL, KEYC_NONE, NULL }
};
const struct window_mode window_client_mode = { const struct window_mode window_client_mode = {
.name = "client-mode", .name = "client-mode",
@ -296,7 +299,7 @@ window_client_init(struct window_mode_entry *wme,
data->data = mode_tree_start(wp, args, window_client_build, data->data = mode_tree_start(wp, args, window_client_build,
window_client_draw, NULL, window_client_menu, data, window_client_draw, NULL, window_client_menu, data,
WINDOW_CLIENT_MENU, window_client_sort_list, window_client_menu_items, window_client_sort_list,
nitems(window_client_sort_list), &s); nitems(window_client_sort_list), &s);
mode_tree_zoom(data->data, args); mode_tree_zoom(data->data, args);

View File

@ -53,18 +53,21 @@ static void window_tree_key(struct window_mode_entry *,
"}" \ "}" \
"}" "}"
#define WINDOW_TREE_MENU \ static const struct menu_item window_tree_menu_items[] = {
"Select,Enter,|" \ { "Select", 'E', NULL },
"Expand,Right,|" \ { "Expand", 'R', NULL },
"|" \ { "", KEYC_NONE, NULL },
"Tag,t,|" \ { "Tag", 't', NULL },
"Tag All,C-t,|" \ { "Tag All", '\024', NULL },
"Tag None,T,|" \ { "Tag None", 'T', NULL },
"|" \ { "", KEYC_NONE, NULL },
"Kill,x,|" \ { "Kill", 'x', NULL },
"Kill Tagged,X,|" \ { "Kill Tagged", 'X', NULL },
"|" \ { "", KEYC_NONE, NULL },
"Cancel,q," { "Cancel", 'q', NULL },
{ NULL, KEYC_NONE, NULL }
};
const struct window_mode window_tree_mode = { const struct window_mode window_tree_mode = {
.name = "tree-mode", .name = "tree-mode",
@ -872,7 +875,7 @@ window_tree_init(struct window_mode_entry *wme, struct cmd_find_state *fs,
data->data = mode_tree_start(wp, args, window_tree_build, data->data = mode_tree_start(wp, args, window_tree_build,
window_tree_draw, window_tree_search, window_tree_menu, data, window_tree_draw, window_tree_search, window_tree_menu, data,
WINDOW_TREE_MENU, window_tree_sort_list, window_tree_menu_items, window_tree_sort_list,
nitems(window_tree_sort_list), &s); nitems(window_tree_sort_list), &s);
mode_tree_zoom(data->data, args); mode_tree_zoom(data->data, args);