summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Marriott <nicm@cvs.openbsd.org>2019-05-28 07:18:43 +0000
committerNicholas Marriott <nicm@cvs.openbsd.org>2019-05-28 07:18:43 +0000
commite24280f07a09b142cec6c35affbda616b270073a (patch)
tree838c2d531cbd21934216d31bc62675be0d06e8c3
parentda4818b66eb44a1b7d0f1f5b2171d8e61b0d068d (diff)
Change display-menu from taking a single string to a set of arguments,
which is much easier to work with. Based on a diff from Avi Halachmi.
-rw-r--r--usr.bin/tmux/cmd-display-menu.c51
-rw-r--r--usr.bin/tmux/format.c53
-rw-r--r--usr.bin/tmux/key-bindings.c51
-rw-r--r--usr.bin/tmux/menu.c118
-rw-r--r--usr.bin/tmux/mode-tree.c30
-rw-r--r--usr.bin/tmux/tmux.137
-rw-r--r--usr.bin/tmux/tmux.h22
-rw-r--r--usr.bin/tmux/window-buffer.c31
-rw-r--r--usr.bin/tmux/window-client.c25
-rw-r--r--usr.bin/tmux/window-tree.c31
10 files changed, 215 insertions, 234 deletions
diff --git a/usr.bin/tmux/cmd-display-menu.c b/usr.bin/tmux/cmd-display-menu.c
index 08d22add102..6e021c77551 100644
--- a/usr.bin/tmux/cmd-display-menu.c
+++ b/usr.bin/tmux/cmd-display-menu.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-display-menu.c,v 1.3 2019/05/26 17:34:45 nicm Exp $ */
+/* $OpenBSD: cmd-display-menu.c,v 1.4 2019/05/28 07:18:42 nicm Exp $ */
/*
* Copyright (c) 2019 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -34,9 +34,9 @@ const struct cmd_entry cmd_display_menu_entry = {
.name = "display-menu",
.alias = "menu",
- .args = { "c:FM:t:T:x:y:", 0, 0 },
- .usage = "[-F] [-c target-client] [-M menu] " CMD_TARGET_PANE_USAGE " "
- "[-T title] [-x position] [-y position]",
+ .args = { "c:t:T:x:y:", 1, -1 },
+ .usage = "[-c target-client] " CMD_TARGET_PANE_USAGE " [-T title] "
+ "[-x position] [-y position] name key command ...",
.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 menu *menu = NULL;
struct style_range *sr;
- const char *string, *xp, *yp;
- int at, flags;
+ struct menu_item menu_item;
+ const char *xp, *yp, *key;
+ char *title, *name;
+ int at, flags, i;
u_int px, py, ox, oy, sx, sy;
- char *title;
if ((c = cmd_find_client(item, args_get(args, 'c'), 0)) == NULL)
return (CMD_RETURN_ERROR);
@@ -66,23 +67,37 @@ cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item)
return (CMD_RETURN_NORMAL);
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'))
title = format_single(NULL, args_get(args, 'T'), c, s, wl, wp);
else
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);
if (menu == NULL) {
- cmdq_error(item, "invalid menu %s", string);
+ cmdq_error(item, "invalid menu arguments");
return (CMD_RETURN_ERROR);
}
if (menu->count == 0) {
diff --git a/usr.bin/tmux/format.c b/usr.bin/tmux/format.c
index d6c6868f2d7..d788766c6f0 100644
--- a/usr.bin/tmux/format.c
+++ b/usr.bin/tmux/format.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: format.c,v 1.199 2019/05/27 15:29:46 nicm Exp $ */
+/* $OpenBSD: format.c,v 1.200 2019/05/28 07:18:42 nicm Exp $ */
/*
* Copyright (c) 2011 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -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_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. */
struct format_job {
struct client *client;
@@ -944,11 +898,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)
format_create_add_item(ft, item);
diff --git a/usr.bin/tmux/key-bindings.c b/usr.bin/tmux/key-bindings.c
index de5fd64f481..d80e808ba43 100644
--- a/usr.bin/tmux/key-bindings.c
+++ b/usr.bin/tmux/key-bindings.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: key-bindings.c,v 1.94 2019/05/27 12:16:27 nicm Exp $ */
+/* $OpenBSD: key-bindings.c,v 1.95 2019/05/28 07:18:42 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -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 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 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 MouseDown3Status display-menu -t= -xW -yS -F -M \"#{window_menu}\" -T \"#[align=centre]#{window_index}:#{window_name}\"",
- "bind -n M-MouseDown3Pane display-menu -t= -xM -yM -F -M \"#{pane_menu}\" -T \"#[align=centre]#{pane_index} (#{pane_id})\"",
+
+ "bind -n MouseDown3StatusRight display-menu -t= -xM -yS -T \"#[align=centre]#{client_name}\""
+ " 'Detach' 'd' {detach-client}"
+ " '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-a send -X start-of-line",
diff --git a/usr.bin/tmux/menu.c b/usr.bin/tmux/menu.c
index c906818e26b..cec97f8d524 100644
--- a/usr.bin/tmux/menu.c
+++ b/usr.bin/tmux/menu.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: menu.c,v 1.7 2019/05/26 18:19:52 nicm Exp $ */
+/* $OpenBSD: menu.c,v 1.8 2019/05/28 07:18:42 nicm Exp $ */
/*
* Copyright (c) 2019 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -40,49 +40,63 @@ struct menu_data {
void *data;
};
-static void
-menu_add_item(struct menu *menu, struct menu_item *item,
+void
+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 menu_item *new_item;
- const char *key;
- char *name;
+ const char *key, *cmd;
+ char *s, *name;
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,
sizeof *menu->items);
new_item = &menu->items[menu->count++];
memset(new_item, 0, sizeof *new_item);
- if (item == NULL || *item->name == '\0') /* horizontal line */
+ if (line)
return;
- if (fs != NULL) {
- name = format_single(qitem, item->name, c, fs->s, fs->wl,
- fs->wp);
- } else
- name = format_single(qitem, item->name, c, NULL, NULL, NULL);
- if (*name == '\0') { /* no item if empty after format expanded */
+
+ if (fs != NULL)
+ s = format_single(qitem, item->name, c, fs->s, fs->wl, fs->wp);
+ else
+ s = format_single(qitem, item->name, c, NULL, NULL, NULL);
+ if (*s == '\0') { /* no item if empty after format expanded */
menu->count--;
return;
}
- if (item->key != KEYC_UNKNOWN) {
+ if (item->key != KEYC_UNKNOWN && item->key != KEYC_NONE) {
key = key_string_lookup_key(item->key);
- xasprintf(&new_item->name, "%s#[default] #[align=right](%s)",
- name, key);
+ xasprintf(&name, "%s#[default] #[align=right](%s)", s, key);
} else
- xasprintf(&new_item->name, "%s", name);
- free(name);
-
- if (item->command != NULL) {
- if (fs != NULL) {
- new_item->command = format_single(qitem, item->command,
- c, fs->s, fs->wl, fs->wp);
- } else {
- new_item->command = format_single(qitem, item->command,
- c, NULL, NULL, NULL);
- }
+ xasprintf(&name, "%s", s);
+ new_item->name = name;
+ free(s);
+
+ cmd = item->command;
+ if (cmd != NULL) {
+ if (fs != NULL)
+ s = format_single(qitem, cmd, c, fs->s, fs->wl, fs->wp);
+ else
+ s = format_single(qitem, cmd, c, NULL, NULL, NULL);
} else
- new_item->command = NULL;
+ s = NULL;
+ new_item->command = s;
new_item->key = item->key;
width = format_width(new_item->name);
@@ -90,56 +104,14 @@ menu_add_item(struct menu *menu, struct menu_item *item,
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 *
-menu_create(const char *s, struct cmdq_item *qitem, struct client *c,
- struct cmd_find_state *fs, const char *title)
+menu_create(const char *title)
{
struct menu *menu;
- char *copy, *string, *next;
-
- if (*s == '\0')
- return (NULL);
menu = xcalloc(1, sizeof *menu);
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);
}
@@ -149,12 +121,12 @@ menu_free(struct menu *menu)
u_int i;
for (i = 0; i < menu->count; i++) {
- free(menu->items[i].name);
- free(menu->items[i].command);
+ free((void *)menu->items[i].name);
+ free((void *)menu->items[i].command);
}
free(menu->items);
- free(menu->title);
+ free((void *)menu->title);
free(menu);
}
diff --git a/usr.bin/tmux/mode-tree.c b/usr.bin/tmux/mode-tree.c
index e726164582d..27c7fa8d578 100644
--- a/usr.bin/tmux/mode-tree.c
+++ b/usr.bin/tmux/mode-tree.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mode-tree.c,v 1.32 2019/05/27 06:50:04 nicm Exp $ */
+/* $OpenBSD: mode-tree.c,v 1.33 2019/05/28 07:18:42 nicm Exp $ */
/*
* Copyright (c) 2017 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -35,7 +35,7 @@ struct mode_tree_data {
struct window_pane *wp;
void *modedata;
- const char *menu;
+ const struct menu_item *menu;
const char **sort_list;
u_int sort_size;
@@ -100,11 +100,14 @@ struct mode_tree_menu {
static void mode_tree_free_items(struct mode_tree_list *);
-#define MODE_TREE_MENU \
- "Scroll Left,<,|" \
- "Scroll Right,>,|" \
- "|" \
- "Cancel,q,"
+static const struct menu_item mode_tree_menu_items[] = {
+ { "Scroll Left", '<', NULL },
+ { "Scroll Right", '>', NULL },
+ { "", KEYC_NONE, NULL },
+ { "Cancel", 'q', NULL },
+
+ { NULL, KEYC_NONE, NULL }
+};
static struct mode_tree_item *
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_build_cb buildcb, mode_tree_draw_cb drawcb,
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 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 menu *menu;
+ const struct menu_item *items;
struct mode_tree_menu *mtm;
- const char *s;
char *title;
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;
if (!outside) {
- s = mtd->menu;
+ items = mtd->menu;
xasprintf(&title, "#[align=centre]%s", mti->name);
} else {
- s = MODE_TREE_MENU;
+ items = mode_tree_menu_items;
title = xstrdup("");
}
- menu = menu_create(s, NULL, c, NULL, title);
+ menu = menu_create(title);
+ menu_add_items(menu, items, NULL, NULL, NULL);
free(title);
- if (menu == NULL)
- return;
mtm = xmalloc(sizeof *mtm);
mtm->data = mtd;
diff --git a/usr.bin/tmux/tmux.1 b/usr.bin/tmux/tmux.1
index e3d5d64a711..24a4e237af5 100644
--- a/usr.bin/tmux/tmux.1
+++ b/usr.bin/tmux/tmux.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: tmux.1,v 1.656 2019/05/27 16:22:32 nicm Exp $
+.\" $OpenBSD: tmux.1,v 1.657 2019/05/28 07:18:42 nicm Exp $
.\"
.\" Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
.\"
@@ -14,7 +14,7 @@
.\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
.\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: May 27 2019 $
+.Dd $Mdocdate: May 28 2019 $
.Dt TMUX 1
.Os
.Sh NAME
@@ -4123,7 +4123,6 @@ The following variables are available, where appropriate:
.It Li "client_height" Ta "" Ta "Height of client"
.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_menu" Ta "" Ta "The default client menu"
.It Li "client_name" Ta "" Ta "Name of client"
.It Li "client_pid" Ta "" Ta "PID of client process"
.It Li "client_prefix" Ta "" Ta "1 if prefix key has been pressed"
@@ -4184,7 +4183,6 @@ The following variables are available, where appropriate:
.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_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_pid" Ta "" Ta "PID of first process in pane"
.It Li "pane_pipe" Ta "" Ta "1 if pane is being piped"
@@ -4215,7 +4213,6 @@ The following variables are available, where appropriate:
.It Li "session_id" Ta "" Ta "Unique session ID"
.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_menu" Ta "" Ta "The default session menu"
.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_windows" Ta "" Ta "Number of windows in session"
@@ -4235,7 +4232,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_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_menu" Ta "" Ta "The default window menu"
.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_y" Ta "" Ta "Y offset into window if larger than client"
@@ -4654,13 +4650,15 @@ option.
This command works only from inside
.Nm .
.It Xo Ic display-menu
-.Op Fl F
.Op Fl c Ar target-client
-.Op Fl M Ar menu
.Op Fl t Ar target-pane
.Op Fl T Ar title
.Op Fl x Ar position
.Op Fl y Ar position
+.Ar name
+.Ar key
+.Ar command
+.Ar ...
.Xc
.D1 (alias: Ic menu )
Display a menu on
@@ -4668,27 +4666,16 @@ Display a menu on
.Ar target-pane
gives the target for any commands run from the menu.
.Pp
-A menu is passed to
-.Fl M
-as a list of menu items separated by
-.Ql | .
-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
+A menu is passed as a series of arguments: first the menu item name,
+second the key shortcut (or empty for none) and third the command
+to run when the menu item is chosen.
+The name and command are formats, see the
.Sx FORMATS
and
.Sx STYLES
sections.
-.It
-The menu item shortcut key.
-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.
+The name may be empty for a separator line, in which case both the key and
+command should be omitted.
.Pp
.Fl T
is a format for the menu title (see
diff --git a/usr.bin/tmux/tmux.h b/usr.bin/tmux/tmux.h
index 2a18becbf95..27ad03f38e8 100644
--- a/usr.bin/tmux/tmux.h
+++ b/usr.bin/tmux/tmux.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: tmux.h,v 1.906 2019/05/26 17:34:45 nicm Exp $ */
+/* $OpenBSD: tmux.h,v 1.907 2019/05/28 07:18:42 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -752,12 +752,12 @@ struct screen_redraw_ctx {
/* Menu. */
struct menu_item {
- char *name;
- char *command;
+ const char *name;
key_code key;
+ const char *command;
};
struct menu {
- char *title;
+ const char *title;
struct menu_item *items;
u_int count;
u_int width;
@@ -2467,8 +2467,8 @@ void mode_tree_each_tagged(struct mode_tree_data *, mode_tree_each_cb,
void mode_tree_down(struct mode_tree_data *, int);
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_menu_cb, void *, const char *, const char **, u_int,
- struct screen **);
+ mode_tree_menu_cb, void *, const struct menu_item *, const char **,
+ u_int, struct screen **);
void mode_tree_zoom(struct mode_tree_data *, struct args *);
void mode_tree_build(struct mode_tree_data *);
void mode_tree_free(struct mode_tree_data *);
@@ -2600,8 +2600,14 @@ __dead void printflike(1, 2) fatal(const char *, ...);
__dead void printflike(1, 2) fatalx(const char *, ...);
/* menu.c */
-struct menu *menu_create(const char *, struct cmdq_item *, struct client *,
- struct cmd_find_state *, const char *);
+struct menu *menu_create(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 *);
int menu_display(struct menu *, int, struct cmdq_item *, u_int,
u_int, struct client *, struct cmd_find_state *,
diff --git a/usr.bin/tmux/window-buffer.c b/usr.bin/tmux/window-buffer.c
index 63347f07b93..46e6e4f9f88 100644
--- a/usr.bin/tmux/window-buffer.c
+++ b/usr.bin/tmux/window-buffer.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: window-buffer.c,v 1.19 2019/05/12 08:58:09 nicm Exp $ */
+/* $OpenBSD: window-buffer.c,v 1.20 2019/05/28 07:18:42 nicm Exp $ */
/*
* Copyright (c) 2017 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -39,18 +39,21 @@ static void window_buffer_key(struct window_mode_entry *,
#define WINDOW_BUFFER_DEFAULT_FORMAT \
"#{buffer_size} bytes (#{t:buffer_created})"
-#define WINDOW_BUFFER_MENU \
- "Paste,p,|" \
- "Paste Tagged,P,|" \
- "|" \
- "Tag,t,|" \
- "Tag All,C-t,|" \
- "Tag None,T,|" \
- "|" \
- "Delete,d,|" \
- "Delete Tagged,D,|" \
- "|" \
- "Cancel,q,"
+static const struct menu_item window_buffer_menu_items[] = {
+ { "Paste", 'p', NULL },
+ { "Paste Tagged", 'P', NULL },
+ { "", KEYC_NONE, NULL },
+ { "Tag", 't', NULL },
+ { "Tag All", '\024', NULL },
+ { "Tag None", 'T', NULL },
+ { "", KEYC_NONE, NULL },
+ { "Delete", 'd', NULL },
+ { "Delete Tagged", 'D', NULL },
+ { "", KEYC_NONE, NULL },
+ { "Cancel", 'q', NULL },
+
+ { NULL, KEYC_NONE, NULL }
+};
const struct window_mode window_buffer_mode = {
.name = "buffer-mode",
@@ -315,7 +318,7 @@ window_buffer_init(struct window_mode_entry *wme, struct cmd_find_state *fs,
data->data = mode_tree_start(wp, args, window_buffer_build,
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);
mode_tree_zoom(data->data, args);
diff --git a/usr.bin/tmux/window-client.c b/usr.bin/tmux/window-client.c
index 6a6e109eeef..5969aaa8910 100644
--- a/usr.bin/tmux/window-client.c
+++ b/usr.bin/tmux/window-client.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: window-client.c,v 1.22 2019/05/12 08:58:09 nicm Exp $ */
+/* $OpenBSD: window-client.c,v 1.23 2019/05/28 07:18:42 nicm Exp $ */
/*
* Copyright (c) 2017 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -40,15 +40,18 @@ static void window_client_key(struct window_mode_entry *,
"session #{session_name} " \
"(#{client_width}x#{client_height}, #{t:client_activity})"
-#define WINDOW_CLIENT_MENU \
- "Detach,d,|" \
- "Detach Tagged,D,|" \
- "|" \
- "Tag,t,|" \
- "Tag All,C-t,|" \
- "Tag None,T,|" \
- "|" \
- "Cancel,q,"
+static const struct menu_item window_client_menu_items[] = {
+ { "Detach", 'd', NULL },
+ { "Detach Tagged", 'D', NULL },
+ { "", KEYC_NONE, NULL },
+ { "Tag", 't', NULL },
+ { "Tag All", '\024', NULL },
+ { "Tag None", 'T', NULL },
+ { "", KEYC_NONE, NULL },
+ { "Cancel", 'q', NULL },
+
+ { NULL, KEYC_NONE, NULL }
+};
const struct window_mode window_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,
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);
mode_tree_zoom(data->data, args);
diff --git a/usr.bin/tmux/window-tree.c b/usr.bin/tmux/window-tree.c
index 4082a85d1cd..e4b52c7d423 100644
--- a/usr.bin/tmux/window-tree.c
+++ b/usr.bin/tmux/window-tree.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: window-tree.c,v 1.38 2019/05/12 08:58:09 nicm Exp $ */
+/* $OpenBSD: window-tree.c,v 1.39 2019/05/28 07:18:42 nicm Exp $ */
/*
* Copyright (c) 2017 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -53,18 +53,21 @@ static void window_tree_key(struct window_mode_entry *,
"}" \
"}"
-#define WINDOW_TREE_MENU \
- "Select,Enter,|" \
- "Expand,Right,|" \
- "|" \
- "Tag,t,|" \
- "Tag All,C-t,|" \
- "Tag None,T,|" \
- "|" \
- "Kill,x,|" \
- "Kill Tagged,X,|" \
- "|" \
- "Cancel,q,"
+static const struct menu_item window_tree_menu_items[] = {
+ { "Select", 'E', NULL },
+ { "Expand", 'R', NULL },
+ { "", KEYC_NONE, NULL },
+ { "Tag", 't', NULL },
+ { "Tag All", '\024', NULL },
+ { "Tag None", 'T', NULL },
+ { "", KEYC_NONE, NULL },
+ { "Kill", 'x', NULL },
+ { "Kill Tagged", 'X', NULL },
+ { "", KEYC_NONE, NULL },
+ { "Cancel", 'q', NULL },
+
+ { NULL, KEYC_NONE, NULL }
+};
const struct window_mode window_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,
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);
mode_tree_zoom(data->data, args);