mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 00:56:10 +00:00 
			
		
		
		
	Merge branch 'obsd-master'
This commit is contained in:
		@@ -71,6 +71,7 @@ dist_tmux_SOURCES = \
 | 
				
			|||||||
	cmd-confirm-before.c \
 | 
						cmd-confirm-before.c \
 | 
				
			||||||
	cmd-copy-mode.c \
 | 
						cmd-copy-mode.c \
 | 
				
			||||||
	cmd-detach-client.c \
 | 
						cmd-detach-client.c \
 | 
				
			||||||
 | 
						cmd-display-menu.c \
 | 
				
			||||||
	cmd-display-message.c \
 | 
						cmd-display-message.c \
 | 
				
			||||||
	cmd-display-panes.c \
 | 
						cmd-display-panes.c \
 | 
				
			||||||
	cmd-find-window.c \
 | 
						cmd-find-window.c \
 | 
				
			||||||
@@ -143,6 +144,7 @@ dist_tmux_SOURCES = \
 | 
				
			|||||||
	layout-set.c \
 | 
						layout-set.c \
 | 
				
			||||||
	layout.c \
 | 
						layout.c \
 | 
				
			||||||
	log.c \
 | 
						log.c \
 | 
				
			||||||
 | 
						menu.c \
 | 
				
			||||||
	mode-tree.c \
 | 
						mode-tree.c \
 | 
				
			||||||
	names.c \
 | 
						names.c \
 | 
				
			||||||
	notify.c \
 | 
						notify.c \
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										163
									
								
								cmd-display-menu.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										163
									
								
								cmd-display-menu.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,163 @@
 | 
				
			|||||||
 | 
					/* $OpenBSD$ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2019 Nicholas Marriott <nicholas.marriott@gmail.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Permission to use, copy, modify, and distribute this software for any
 | 
				
			||||||
 | 
					 * purpose with or without fee is hereby granted, provided that the above
 | 
				
			||||||
 | 
					 * copyright notice and this permission notice appear in all copies.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
				
			||||||
 | 
					 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
				
			||||||
 | 
					 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
				
			||||||
 | 
					 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
				
			||||||
 | 
					 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
 | 
				
			||||||
 | 
					 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
 | 
				
			||||||
 | 
					 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <sys/types.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "tmux.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Display a menu on a client.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static enum cmd_retval	cmd_display_menu_exec(struct cmd *,
 | 
				
			||||||
 | 
								    struct cmdq_item *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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]",
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.target = { 't', CMD_FIND_PANE, 0 },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.flags = CMD_AFTERHOOK,
 | 
				
			||||||
 | 
						.exec = cmd_display_menu_exec
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static enum cmd_retval
 | 
				
			||||||
 | 
					cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct args		*args = self->args;
 | 
				
			||||||
 | 
						struct client		*c;
 | 
				
			||||||
 | 
						struct session		*s = item->target.s;
 | 
				
			||||||
 | 
						struct winlink		*wl = item->target.wl;
 | 
				
			||||||
 | 
						struct window_pane	*wp = item->target.wp;
 | 
				
			||||||
 | 
						struct cmd_find_state	*fs = &item->target;
 | 
				
			||||||
 | 
						struct menu		*menu = NULL;
 | 
				
			||||||
 | 
						struct style_range	*sr;
 | 
				
			||||||
 | 
						const char		*string, *xp, *yp;
 | 
				
			||||||
 | 
						int			 at, flags;
 | 
				
			||||||
 | 
						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);
 | 
				
			||||||
 | 
						if (c->overlay_draw != NULL)
 | 
				
			||||||
 | 
							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_from_string(string, c, fs, title);
 | 
				
			||||||
 | 
						free(title);
 | 
				
			||||||
 | 
						if (menu == NULL) {
 | 
				
			||||||
 | 
							cmdq_error(item, "invalid menu %s", string);
 | 
				
			||||||
 | 
							return (CMD_RETURN_ERROR);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (menu->count == 0) {
 | 
				
			||||||
 | 
							menu_free(menu);
 | 
				
			||||||
 | 
							return (CMD_RETURN_NORMAL);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						xp = args_get(args, 'x');
 | 
				
			||||||
 | 
						if (xp == NULL)
 | 
				
			||||||
 | 
							px = 0;
 | 
				
			||||||
 | 
						else if (strcmp(xp, "R") == 0)
 | 
				
			||||||
 | 
							px = c->tty.sx - 1;
 | 
				
			||||||
 | 
						else if (strcmp(xp, "P") == 0) {
 | 
				
			||||||
 | 
							tty_window_offset(&c->tty, &ox, &oy, &sx, &sy);
 | 
				
			||||||
 | 
							if (wp->xoff >= ox)
 | 
				
			||||||
 | 
								px = wp->xoff - ox;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								px = 0;
 | 
				
			||||||
 | 
						} else if (strcmp(xp, "M") == 0 && item->shared->mouse.valid) {
 | 
				
			||||||
 | 
							if (item->shared->mouse.x > (menu->width + 4) / 2)
 | 
				
			||||||
 | 
								px = item->shared->mouse.x - (menu->width + 4) / 2;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								px = 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if (strcmp(xp, "W") == 0) {
 | 
				
			||||||
 | 
							if (at == -1)
 | 
				
			||||||
 | 
								px = 0;
 | 
				
			||||||
 | 
							else {
 | 
				
			||||||
 | 
								TAILQ_FOREACH(sr, &c->status.entries[0].ranges, entry) {
 | 
				
			||||||
 | 
									if (sr->type != STYLE_RANGE_WINDOW)
 | 
				
			||||||
 | 
										continue;
 | 
				
			||||||
 | 
									if (sr->argument == (u_int)wl->idx)
 | 
				
			||||||
 | 
										break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if (sr != NULL)
 | 
				
			||||||
 | 
									px = sr->start;
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									px = 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else
 | 
				
			||||||
 | 
							px = strtoul(xp, NULL, 10);
 | 
				
			||||||
 | 
						if (px + menu->width + 4 >= c->tty.sx)
 | 
				
			||||||
 | 
							px = c->tty.sx - menu->width - 4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						yp = args_get(args, 'y');
 | 
				
			||||||
 | 
						if (yp == NULL)
 | 
				
			||||||
 | 
							py = 0;
 | 
				
			||||||
 | 
						else if (strcmp(yp, "P") == 0) {
 | 
				
			||||||
 | 
							tty_window_offset(&c->tty, &ox, &oy, &sx, &sy);
 | 
				
			||||||
 | 
							if (wp->yoff + wp->sy >= oy)
 | 
				
			||||||
 | 
								py = wp->yoff + wp->sy - oy;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								py = 0;
 | 
				
			||||||
 | 
						} else if (strcmp(yp, "M") == 0 && item->shared->mouse.valid)
 | 
				
			||||||
 | 
							py = item->shared->mouse.y + menu->count + 2;
 | 
				
			||||||
 | 
						else if (strcmp(yp, "S") == 0) {
 | 
				
			||||||
 | 
							if (at == -1)
 | 
				
			||||||
 | 
								py = c->tty.sy;
 | 
				
			||||||
 | 
							else if (at == 0)
 | 
				
			||||||
 | 
								py = status_line_size(c) + menu->count + 2;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								py = at;
 | 
				
			||||||
 | 
						} else
 | 
				
			||||||
 | 
							py = strtoul(yp, NULL, 10);
 | 
				
			||||||
 | 
						if (py < menu->count + 2)
 | 
				
			||||||
 | 
							py = 0;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							py -= menu->count + 2;
 | 
				
			||||||
 | 
						if (py + menu->count + 2 >= c->tty.sy)
 | 
				
			||||||
 | 
							py = c->tty.sy - menu->count - 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						flags = 0;
 | 
				
			||||||
 | 
						if (!item->shared->mouse.valid)
 | 
				
			||||||
 | 
							flags |= MENU_NOMOUSE;
 | 
				
			||||||
 | 
						if (menu_display(menu, flags, item, px, py, c, fs, NULL, NULL) != 0)
 | 
				
			||||||
 | 
							return (CMD_RETURN_NORMAL);
 | 
				
			||||||
 | 
						return (CMD_RETURN_WAIT);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										2
									
								
								cmd.c
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								cmd.c
									
									
									
									
									
								
							@@ -41,6 +41,7 @@ extern const struct cmd_entry cmd_confirm_before_entry;
 | 
				
			|||||||
extern const struct cmd_entry cmd_copy_mode_entry;
 | 
					extern const struct cmd_entry cmd_copy_mode_entry;
 | 
				
			||||||
extern const struct cmd_entry cmd_delete_buffer_entry;
 | 
					extern const struct cmd_entry cmd_delete_buffer_entry;
 | 
				
			||||||
extern const struct cmd_entry cmd_detach_client_entry;
 | 
					extern const struct cmd_entry cmd_detach_client_entry;
 | 
				
			||||||
 | 
					extern const struct cmd_entry cmd_display_menu_entry;
 | 
				
			||||||
extern const struct cmd_entry cmd_display_message_entry;
 | 
					extern const struct cmd_entry cmd_display_message_entry;
 | 
				
			||||||
extern const struct cmd_entry cmd_display_panes_entry;
 | 
					extern const struct cmd_entry cmd_display_panes_entry;
 | 
				
			||||||
extern const struct cmd_entry cmd_down_pane_entry;
 | 
					extern const struct cmd_entry cmd_down_pane_entry;
 | 
				
			||||||
@@ -129,6 +130,7 @@ const struct cmd_entry *cmd_table[] = {
 | 
				
			|||||||
	&cmd_copy_mode_entry,
 | 
						&cmd_copy_mode_entry,
 | 
				
			||||||
	&cmd_delete_buffer_entry,
 | 
						&cmd_delete_buffer_entry,
 | 
				
			||||||
	&cmd_detach_client_entry,
 | 
						&cmd_detach_client_entry,
 | 
				
			||||||
 | 
						&cmd_display_menu_entry,
 | 
				
			||||||
	&cmd_display_message_entry,
 | 
						&cmd_display_message_entry,
 | 
				
			||||||
	&cmd_display_panes_entry,
 | 
						&cmd_display_panes_entry,
 | 
				
			||||||
	&cmd_find_window_entry,
 | 
						&cmd_find_window_entry,
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										48
									
								
								format.c
									
									
									
									
									
								
							
							
						
						
									
										48
									
								
								format.c
									
									
									
									
									
								
							@@ -54,6 +54,49 @@ 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-command},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 \
 | 
				
			||||||
 | 
						"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;
 | 
				
			||||||
@@ -768,6 +811,11 @@ 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) {
 | 
				
			||||||
		if (item->cmd != NULL)
 | 
							if (item->cmd != NULL)
 | 
				
			||||||
			format_add(ft, "command", "%s", item->cmd->entry->name);
 | 
								format_add(ft, "command", "%s", item->cmd->entry->name);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -271,6 +271,7 @@ key_bindings_init(void)
 | 
				
			|||||||
		"bind -r C-Down resize-pane -D",
 | 
							"bind -r C-Down resize-pane -D",
 | 
				
			||||||
		"bind -r C-Left resize-pane -L",
 | 
							"bind -r C-Left resize-pane -L",
 | 
				
			||||||
		"bind -r C-Right resize-pane -R",
 | 
							"bind -r C-Right resize-pane -R",
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		"bind -n MouseDown1Pane select-pane -t=\\; send-keys -M",
 | 
							"bind -n MouseDown1Pane select-pane -t=\\; send-keys -M",
 | 
				
			||||||
		"bind -n MouseDrag1Border resize-pane -M",
 | 
							"bind -n MouseDrag1Border resize-pane -M",
 | 
				
			||||||
		"bind -n MouseDown1Status select-window -t=",
 | 
							"bind -n MouseDown1Status select-window -t=",
 | 
				
			||||||
@@ -279,6 +280,10 @@ 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-shell -Ft= '#{mouse_any_flag}' 'select-pane -t=; send-keys -M' 'select-pane -mt='",
 | 
							"bind -n MouseDown3Pane if-shell -Ft= '#{mouse_any_flag}' 'select-pane -t=; send-keys -M' 'select-pane -mt='",
 | 
				
			||||||
		"bind -n WheelUpPane if-shell -Ft= '#{mouse_any_flag}' 'send-keys -M' 'if -Ft= \"#{pane_in_mode}\" \"send-keys -M\" \"copy-mode -et=\"'",
 | 
							"bind -n WheelUpPane if-shell -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 -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",
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										342
									
								
								menu.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										342
									
								
								menu.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,342 @@
 | 
				
			|||||||
 | 
					/* $OpenBSD$ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2019 Nicholas Marriott <nicholas.marriott@gmail.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Permission to use, copy, modify, and distribute this software for any
 | 
				
			||||||
 | 
					 * purpose with or without fee is hereby granted, provided that the above
 | 
				
			||||||
 | 
					 * copyright notice and this permission notice appear in all copies.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
				
			||||||
 | 
					 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
				
			||||||
 | 
					 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
				
			||||||
 | 
					 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
				
			||||||
 | 
					 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
 | 
				
			||||||
 | 
					 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
 | 
				
			||||||
 | 
					 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <sys/types.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "tmux.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct menu_data {
 | 
				
			||||||
 | 
						struct cmdq_item	*item;
 | 
				
			||||||
 | 
						int			 flags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct cmd_find_state	 fs;
 | 
				
			||||||
 | 
						struct screen		 s;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						u_int			 px;
 | 
				
			||||||
 | 
						u_int			 py;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct menu		*menu;
 | 
				
			||||||
 | 
						int			 choice;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						menu_choice_cb		 cb;
 | 
				
			||||||
 | 
						void			*data;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					menu_add_item(struct menu *menu, struct menu_item *item, struct client *c,
 | 
				
			||||||
 | 
					    struct cmd_find_state *fs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct menu_item	*new_item;
 | 
				
			||||||
 | 
						const char		*key;
 | 
				
			||||||
 | 
						char			*name;
 | 
				
			||||||
 | 
						u_int			 width;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						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 */
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						name = format_single(NULL, item->name, c, fs->s, fs->wl, fs->wp);
 | 
				
			||||||
 | 
						if (*name == '\0') { /* no item if empty after format expanded */
 | 
				
			||||||
 | 
							menu->count--;
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (item->key != KEYC_UNKNOWN) {
 | 
				
			||||||
 | 
							key = key_string_lookup_key(item->key);
 | 
				
			||||||
 | 
							xasprintf(&new_item->name, "%s #[align=right](%s)", name, key);
 | 
				
			||||||
 | 
						} else
 | 
				
			||||||
 | 
							xasprintf(&new_item->name, "%s", name);
 | 
				
			||||||
 | 
						free(name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (item->command != NULL)
 | 
				
			||||||
 | 
							new_item->command = xstrdup(item->command);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							new_item->command = NULL;
 | 
				
			||||||
 | 
						new_item->key = item->key;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						width = format_width(new_item->name);
 | 
				
			||||||
 | 
						if (width > menu->width)
 | 
				
			||||||
 | 
							menu->width = width;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					menu_parse_item(struct menu *menu, const char *s, 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, c, fs);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						free(copy);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct menu *
 | 
				
			||||||
 | 
					menu_create_from_items(struct menu_item *items, u_int count, struct client *c,
 | 
				
			||||||
 | 
					    struct cmd_find_state *fs, const char *title)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct menu	*menu;
 | 
				
			||||||
 | 
						u_int		 i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						menu = xcalloc(1, sizeof *menu);
 | 
				
			||||||
 | 
						menu->title = xstrdup(title);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < count; i++)
 | 
				
			||||||
 | 
							menu_add_item(menu, &items[i], c, fs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return (menu);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct menu *
 | 
				
			||||||
 | 
					menu_create_from_string(const char *s, struct client *c,
 | 
				
			||||||
 | 
					    struct cmd_find_state *fs, 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, "|");
 | 
				
			||||||
 | 
							log_debug("XXX %s -- %s", next, string);
 | 
				
			||||||
 | 
							if (next != NULL)
 | 
				
			||||||
 | 
								*next++ = '\0';
 | 
				
			||||||
 | 
							if (*string == '\0')
 | 
				
			||||||
 | 
								menu_add_item(menu, NULL, c, fs);
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								menu_parse_item(menu, string, c, fs);
 | 
				
			||||||
 | 
							string = next;
 | 
				
			||||||
 | 
						} while (next != NULL);
 | 
				
			||||||
 | 
						free(copy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return (menu);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					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(menu->items);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						free(menu->title);
 | 
				
			||||||
 | 
						free(menu);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					menu_draw_cb(struct client *c, __unused struct screen_redraw_ctx *ctx0)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct menu_data	*md = c->overlay_data;
 | 
				
			||||||
 | 
						struct tty		*tty = &c->tty;
 | 
				
			||||||
 | 
						struct screen		*s = &md->s;
 | 
				
			||||||
 | 
						struct menu		*menu = md->menu;
 | 
				
			||||||
 | 
						struct screen_write_ctx	 ctx;
 | 
				
			||||||
 | 
						u_int			 i, px, py;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						screen_write_start(&ctx, NULL, s);
 | 
				
			||||||
 | 
						screen_write_clearscreen(&ctx, 8);
 | 
				
			||||||
 | 
						screen_write_menu(&ctx, menu, md->choice);
 | 
				
			||||||
 | 
						screen_write_stop(&ctx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						px = md->px;
 | 
				
			||||||
 | 
						py = md->py;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < screen_size_y(&md->s); i++)
 | 
				
			||||||
 | 
							tty_draw_line(tty, NULL, s, 0, i, menu->width + 4, px, py + i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (~md->flags & MENU_NOMOUSE)
 | 
				
			||||||
 | 
							tty_update_mode(tty, MODE_MOUSE_ALL, NULL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					menu_free_cb(struct client *c)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct menu_data	*md = c->overlay_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (md->item != NULL)
 | 
				
			||||||
 | 
							md->item->flags &= ~CMDQ_WAITING;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						screen_free(&md->s);
 | 
				
			||||||
 | 
						menu_free(md->menu);
 | 
				
			||||||
 | 
						free(md);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static enum cmd_retval
 | 
				
			||||||
 | 
					menu_error_cb(struct cmdq_item *item, void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						char	*error = data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cmdq_error(item, "%s", error);
 | 
				
			||||||
 | 
						free(error);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return (CMD_RETURN_NORMAL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					menu_key_cb(struct client *c, struct key_event *event)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct menu_data		*md = c->overlay_data;
 | 
				
			||||||
 | 
						struct menu			*menu = md->menu;
 | 
				
			||||||
 | 
						struct mouse_event		*m = &event->m;
 | 
				
			||||||
 | 
						u_int				 i;
 | 
				
			||||||
 | 
						int				 count = menu->count, old = md->choice;
 | 
				
			||||||
 | 
						const struct menu_item		*item;
 | 
				
			||||||
 | 
						struct cmd_list			*cmdlist;
 | 
				
			||||||
 | 
						struct cmdq_item		*new_item;
 | 
				
			||||||
 | 
						char				*cause;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (KEYC_IS_MOUSE(event->key)) {
 | 
				
			||||||
 | 
							if (md->flags & MENU_NOMOUSE)
 | 
				
			||||||
 | 
								return (0);
 | 
				
			||||||
 | 
							if (m->x < md->px ||
 | 
				
			||||||
 | 
							    m->x > md->px + 4 + menu->width ||
 | 
				
			||||||
 | 
							    m->y < md->py + 1 ||
 | 
				
			||||||
 | 
							    m->y > md->py + 1 + count - 1) {
 | 
				
			||||||
 | 
								if (MOUSE_RELEASE(m->b))
 | 
				
			||||||
 | 
									return (1);
 | 
				
			||||||
 | 
								if (md->choice != -1) {
 | 
				
			||||||
 | 
									md->choice = -1;
 | 
				
			||||||
 | 
									c->flags |= CLIENT_REDRAWOVERLAY;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return (0);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							md->choice = m->y - (md->py + 1);
 | 
				
			||||||
 | 
							if (MOUSE_RELEASE(m->b))
 | 
				
			||||||
 | 
								goto chosen;
 | 
				
			||||||
 | 
							if (md->choice != old)
 | 
				
			||||||
 | 
								c->flags |= CLIENT_REDRAWOVERLAY;
 | 
				
			||||||
 | 
							return (0);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						switch (event->key) {
 | 
				
			||||||
 | 
						case KEYC_UP:
 | 
				
			||||||
 | 
							do {
 | 
				
			||||||
 | 
								if (md->choice == -1 || md->choice == 0)
 | 
				
			||||||
 | 
									md->choice = count - 1;
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									md->choice--;
 | 
				
			||||||
 | 
							} while (menu->items[md->choice].name == NULL);
 | 
				
			||||||
 | 
							c->flags |= CLIENT_REDRAWOVERLAY;
 | 
				
			||||||
 | 
							return (0);
 | 
				
			||||||
 | 
						case KEYC_DOWN:
 | 
				
			||||||
 | 
							do {
 | 
				
			||||||
 | 
								if (md->choice == -1 || md->choice == count - 1)
 | 
				
			||||||
 | 
									md->choice = 0;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								md->choice++;
 | 
				
			||||||
 | 
							} while (menu->items[md->choice].name == NULL);
 | 
				
			||||||
 | 
							c->flags |= CLIENT_REDRAWOVERLAY;
 | 
				
			||||||
 | 
							return (0);
 | 
				
			||||||
 | 
						case '\r':
 | 
				
			||||||
 | 
							goto chosen;
 | 
				
			||||||
 | 
						case '\033': /* Escape */
 | 
				
			||||||
 | 
						case '\003': /* C-c */
 | 
				
			||||||
 | 
						case '\007': /* C-g */
 | 
				
			||||||
 | 
						case 'q':
 | 
				
			||||||
 | 
							return (1);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for (i = 0; i < (u_int)count; i++) {
 | 
				
			||||||
 | 
							if (event->key == menu->items[i].key) {
 | 
				
			||||||
 | 
								md->choice = i;
 | 
				
			||||||
 | 
								goto chosen;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return (0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					chosen:
 | 
				
			||||||
 | 
						if (md->choice == -1)
 | 
				
			||||||
 | 
							return (1);
 | 
				
			||||||
 | 
						item = &menu->items[md->choice];
 | 
				
			||||||
 | 
						if (item->name == NULL)
 | 
				
			||||||
 | 
							return (1);
 | 
				
			||||||
 | 
						if (md->cb != NULL) {
 | 
				
			||||||
 | 
						    md->cb(md->menu, md->choice, item->key, md->data);
 | 
				
			||||||
 | 
						    return (1);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						cmdlist = cmd_string_parse(item->command, NULL, 0, &cause);
 | 
				
			||||||
 | 
						if (cmdlist == NULL && cause != NULL)
 | 
				
			||||||
 | 
							new_item = cmdq_get_callback(menu_error_cb, cause);
 | 
				
			||||||
 | 
						else if (cmdlist == NULL)
 | 
				
			||||||
 | 
							new_item = NULL;
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							new_item = cmdq_get_command(cmdlist, &md->fs, NULL, 0);
 | 
				
			||||||
 | 
							cmd_list_free(cmdlist);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (new_item != NULL) {
 | 
				
			||||||
 | 
							if (md->item != NULL)
 | 
				
			||||||
 | 
								cmdq_insert_after(md->item, new_item);
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								cmdq_append(c, new_item);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return (1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					menu_display(struct menu *menu, int flags, struct cmdq_item *item, u_int px,
 | 
				
			||||||
 | 
					    u_int py, struct client *c, struct cmd_find_state *fs, menu_choice_cb cb,
 | 
				
			||||||
 | 
					    void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct menu_data	*md;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (c->tty.sx < menu->width + 4 || c->tty.sy < menu->count + 2)
 | 
				
			||||||
 | 
							return (-1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						md = xcalloc(1, sizeof *md);
 | 
				
			||||||
 | 
						md->item = item;
 | 
				
			||||||
 | 
						md->flags = flags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cmd_find_copy_state(&md->fs, fs);
 | 
				
			||||||
 | 
						screen_init(&md->s, menu->width + 4, menu->count + 2, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						md->px = px;
 | 
				
			||||||
 | 
						md->py = py;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						md->menu = menu;
 | 
				
			||||||
 | 
						md->choice = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						md->cb = cb;
 | 
				
			||||||
 | 
						md->data = data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						server_client_set_overlay(c, 0, menu_draw_cb, menu_key_cb, menu_free_cb,
 | 
				
			||||||
 | 
						    md);
 | 
				
			||||||
 | 
						return (0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										92
									
								
								tmux.1
									
									
									
									
									
								
							
							
						
						
									
										92
									
								
								tmux.1
									
									
									
									
									
								
							@@ -3914,12 +3914,13 @@ The following variables are available, where appropriate:
 | 
				
			|||||||
.It Li "buffer_sample" Ta "" Ta "Sample of start of buffer"
 | 
					.It Li "buffer_sample" Ta "" Ta "Sample of start of buffer"
 | 
				
			||||||
.It Li "buffer_size" Ta "" Ta "Size of the specified buffer in bytes"
 | 
					.It Li "buffer_size" Ta "" Ta "Size of the specified buffer in bytes"
 | 
				
			||||||
.It Li "client_activity" Ta "" Ta "Time client last had activity"
 | 
					.It Li "client_activity" Ta "" Ta "Time client last had activity"
 | 
				
			||||||
.It Li "client_created" Ta "" Ta "Time client created"
 | 
					 | 
				
			||||||
.It Li "client_control_mode" Ta "" Ta "1 if client is in control mode"
 | 
					.It Li "client_control_mode" Ta "" Ta "1 if client is in control mode"
 | 
				
			||||||
 | 
					.It Li "client_created" Ta "" Ta "Time client created"
 | 
				
			||||||
.It Li "client_discarded" Ta "" Ta "Bytes discarded when client behind"
 | 
					.It Li "client_discarded" Ta "" Ta "Bytes discarded when client behind"
 | 
				
			||||||
.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"
 | 
				
			||||||
@@ -3932,11 +3933,11 @@ The following variables are available, where appropriate:
 | 
				
			|||||||
.It Li "client_width" Ta "" Ta "Width of client"
 | 
					.It Li "client_width" Ta "" Ta "Width of client"
 | 
				
			||||||
.It Li "client_written" Ta "" Ta "Bytes written to client"
 | 
					.It Li "client_written" Ta "" Ta "Bytes written to client"
 | 
				
			||||||
.It Li "command" Ta "" Ta "Name of command in use, if any"
 | 
					.It Li "command" Ta "" Ta "Name of command in use, if any"
 | 
				
			||||||
.It Li "command_list_name" Ta "" Ta "Command name if listing commands"
 | 
					 | 
				
			||||||
.It Li "command_list_alias" Ta "" Ta "Command alias if listing commands"
 | 
					.It Li "command_list_alias" Ta "" Ta "Command alias if listing commands"
 | 
				
			||||||
 | 
					.It Li "command_list_name" Ta "" Ta "Command name if listing commands"
 | 
				
			||||||
.It Li "command_list_usage" Ta "" Ta "Command usage if listing commands"
 | 
					.It Li "command_list_usage" Ta "" Ta "Command usage if listing commands"
 | 
				
			||||||
.It Li "cursor_flag" Ta "" Ta "Pane cursor flag"
 | 
					 | 
				
			||||||
.It Li "cursor_character" Ta "" Ta "Character at cursor in pane"
 | 
					.It Li "cursor_character" Ta "" Ta "Character at cursor in pane"
 | 
				
			||||||
 | 
					.It Li "cursor_flag" Ta "" Ta "Pane cursor flag"
 | 
				
			||||||
.It Li "cursor_x" Ta "" Ta "Cursor X position in pane"
 | 
					.It Li "cursor_x" Ta "" Ta "Cursor X position in pane"
 | 
				
			||||||
.It Li "cursor_y" Ta "" Ta "Cursor Y position in pane"
 | 
					.It Li "cursor_y" Ta "" Ta "Cursor Y position in pane"
 | 
				
			||||||
.It Li "history_bytes" Ta "" Ta "Number of bytes in window history"
 | 
					.It Li "history_bytes" Ta "" Ta "Number of bytes in window history"
 | 
				
			||||||
@@ -3954,10 +3955,10 @@ The following variables are available, where appropriate:
 | 
				
			|||||||
.It Li "keypad_cursor_flag" Ta "" Ta "Pane keypad cursor flag"
 | 
					.It Li "keypad_cursor_flag" Ta "" Ta "Pane keypad cursor flag"
 | 
				
			||||||
.It Li "keypad_flag" Ta "" Ta "Pane keypad flag"
 | 
					.It Li "keypad_flag" Ta "" Ta "Pane keypad flag"
 | 
				
			||||||
.It Li "line" Ta "" Ta "Line number in the list"
 | 
					.It Li "line" Ta "" Ta "Line number in the list"
 | 
				
			||||||
 | 
					.It Li "mouse_all_flag" Ta "" Ta "Pane mouse all flag"
 | 
				
			||||||
.It Li "mouse_any_flag" Ta "" Ta "Pane mouse any flag"
 | 
					.It Li "mouse_any_flag" Ta "" Ta "Pane mouse any flag"
 | 
				
			||||||
.It Li "mouse_button_flag" Ta "" Ta "Pane mouse button flag"
 | 
					.It Li "mouse_button_flag" Ta "" Ta "Pane mouse button flag"
 | 
				
			||||||
.It Li "mouse_standard_flag" Ta "" Ta "Pane mouse standard flag"
 | 
					.It Li "mouse_standard_flag" Ta "" Ta "Pane mouse standard flag"
 | 
				
			||||||
.It Li "mouse_all_flag" Ta "" Ta "Pane mouse all flag"
 | 
					 | 
				
			||||||
.It Li "pane_active" Ta "" Ta "1 if active pane"
 | 
					.It Li "pane_active" Ta "" Ta "1 if active pane"
 | 
				
			||||||
.It Li "pane_at_bottom" Ta "" Ta "1 if pane is at the bottom of window"
 | 
					.It Li "pane_at_bottom" Ta "" Ta "1 if pane is at the bottom of window"
 | 
				
			||||||
.It Li "pane_at_left" Ta "" Ta "1 if pane is at the left of window"
 | 
					.It Li "pane_at_left" Ta "" Ta "1 if pane is at the left of window"
 | 
				
			||||||
@@ -3972,11 +3973,12 @@ The following variables are available, where appropriate:
 | 
				
			|||||||
.It Li "pane_height" Ta "" Ta "Height of pane"
 | 
					.It Li "pane_height" Ta "" Ta "Height of pane"
 | 
				
			||||||
.It Li "pane_id" Ta "#D" Ta "Unique pane ID"
 | 
					.It Li "pane_id" Ta "#D" Ta "Unique pane ID"
 | 
				
			||||||
.It Li "pane_in_mode" Ta "" Ta "If pane is in a mode"
 | 
					.It Li "pane_in_mode" Ta "" Ta "If pane is in a mode"
 | 
				
			||||||
.It Li "pane_input_off" Ta "" Ta "If input to pane is disabled"
 | 
					 | 
				
			||||||
.It Li "pane_index" Ta "#P" Ta "Index of pane"
 | 
					.It Li "pane_index" Ta "#P" Ta "Index of pane"
 | 
				
			||||||
 | 
					.It Li "pane_input_off" Ta "" Ta "If input to pane is disabled"
 | 
				
			||||||
.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 market pane is set"
 | 
					.It Li "pane_marked_set" Ta " Ta "1 if a market 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"
 | 
				
			||||||
@@ -3991,31 +3993,32 @@ The following variables are available, where appropriate:
 | 
				
			|||||||
.It Li "pane_width" Ta "" Ta "Width of pane"
 | 
					.It Li "pane_width" Ta "" Ta "Width of pane"
 | 
				
			||||||
.It Li "pid" Ta ""  Ta "Server PID"
 | 
					.It Li "pid" Ta ""  Ta "Server PID"
 | 
				
			||||||
.It Li "rectangle_toggle" Ta "" Ta "1 if rectangle selection is activated"
 | 
					.It Li "rectangle_toggle" Ta "" Ta "1 if rectangle selection is activated"
 | 
				
			||||||
 | 
					.It Li "scroll_position" Ta "" Ta "Scroll position in copy mode"
 | 
				
			||||||
.It Li "scroll_region_lower" Ta "" Ta "Bottom of scroll region in pane"
 | 
					.It Li "scroll_region_lower" Ta "" Ta "Bottom of scroll region in pane"
 | 
				
			||||||
.It Li "scroll_region_upper" Ta "" Ta "Top of scroll region in pane"
 | 
					.It Li "scroll_region_upper" Ta "" Ta "Top of scroll region in pane"
 | 
				
			||||||
.It Li "scroll_position" Ta "" Ta "Scroll position in copy mode"
 | 
					 | 
				
			||||||
.It Li "selection_present" Ta "" Ta "1 if selection started in copy mode"
 | 
					.It Li "selection_present" Ta "" Ta "1 if selection started in copy mode"
 | 
				
			||||||
 | 
					.It Li "session_activity" Ta "" Ta "Time of session last activity"
 | 
				
			||||||
.It Li "session_alerts" Ta "" Ta "List of window indexes with alerts"
 | 
					.It Li "session_alerts" Ta "" Ta "List of window indexes with alerts"
 | 
				
			||||||
.It Li "session_attached" Ta "" Ta "Number of clients session is attached to"
 | 
					.It Li "session_attached" Ta "" Ta "Number of clients session is attached to"
 | 
				
			||||||
.It Li "session_activity" Ta "" Ta "Time of session last activity"
 | 
					 | 
				
			||||||
.It Li "session_created" Ta "" Ta "Time session created"
 | 
					.It Li "session_created" Ta "" Ta "Time session created"
 | 
				
			||||||
.It Li "session_format" Ta "" Ta "1 if format is for a session (not assuming the current)"
 | 
					.It Li "session_format" Ta "" Ta "1 if format is for a session (not assuming the current)"
 | 
				
			||||||
.It Li "session_last_attached" Ta "" Ta "Time session last attached"
 | 
					 | 
				
			||||||
.It Li "session_group" Ta "" Ta "Name of session group"
 | 
					.It Li "session_group" Ta "" Ta "Name of session group"
 | 
				
			||||||
.It Li "session_group_size" Ta "" Ta "Size of session group"
 | 
					 | 
				
			||||||
.It Li "session_group_list" Ta "" Ta "List of sessions in group"
 | 
					.It Li "session_group_list" Ta "" Ta "List of sessions in group"
 | 
				
			||||||
 | 
					.It Li "session_group_size" Ta "" Ta "Size of session group"
 | 
				
			||||||
.It Li "session_grouped" Ta "" Ta "1 if session in a group"
 | 
					.It Li "session_grouped" Ta "" Ta "1 if session in a group"
 | 
				
			||||||
.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_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"
 | 
				
			||||||
.It Li "socket_path" Ta "" Ta "Server socket path"
 | 
					.It Li "socket_path" Ta "" Ta "Server socket path"
 | 
				
			||||||
.It Li "start_time" Ta "" Ta "Server start time"
 | 
					.It Li "start_time" Ta "" Ta "Server start time"
 | 
				
			||||||
.It Li "version" Ta "" Ta "Server version"
 | 
					.It Li "version" Ta "" Ta "Server version"
 | 
				
			||||||
 | 
					.It Li "window_active" Ta "" Ta "1 if window active"
 | 
				
			||||||
.It Li "window_activity" Ta "" Ta "Time of window last activity"
 | 
					.It Li "window_activity" Ta "" Ta "Time of window last activity"
 | 
				
			||||||
.It Li "window_activity_flag" Ta "" Ta "1 if window has activity"
 | 
					.It Li "window_activity_flag" Ta "" Ta "1 if window has activity"
 | 
				
			||||||
.It Li "window_active" Ta "" Ta "1 if window active"
 | 
					 | 
				
			||||||
.It Li "window_bell_flag" Ta "" Ta "1 if window has bell"
 | 
					.It Li "window_bell_flag" Ta "" Ta "1 if window has bell"
 | 
				
			||||||
.It Li "window_bigger" Ta "" Ta "1 if window is larger than client"
 | 
					.It Li "window_bigger" Ta "" Ta "1 if window is larger than client"
 | 
				
			||||||
.It Li "window_end_flag" Ta "" Ta "1 if window has the highest index"
 | 
					.It Li "window_end_flag" Ta "" Ta "1 if window has the highest index"
 | 
				
			||||||
@@ -4027,6 +4030,7 @@ 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"
 | 
				
			||||||
@@ -4443,6 +4447,74 @@ option.
 | 
				
			|||||||
.Pp
 | 
					.Pp
 | 
				
			||||||
This command works only from inside
 | 
					This command works only from inside
 | 
				
			||||||
.Nm .
 | 
					.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
 | 
				
			||||||
 | 
					.Xc
 | 
				
			||||||
 | 
					.D1 (alias: Ic menu)
 | 
				
			||||||
 | 
					Display a menu on
 | 
				
			||||||
 | 
					.Ar target-client .
 | 
				
			||||||
 | 
					.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 name
 | 
				
			||||||
 | 
					The menu item name.
 | 
				
			||||||
 | 
					This is a format and may include embedded styles, see the
 | 
				
			||||||
 | 
					.Sx FORMATS
 | 
				
			||||||
 | 
					and
 | 
				
			||||||
 | 
					.Sx STYLES
 | 
				
			||||||
 | 
					sections.
 | 
				
			||||||
 | 
					.It key
 | 
				
			||||||
 | 
					The menu item shortcut key.
 | 
				
			||||||
 | 
					If this is empty the menu item has no key shortcut.
 | 
				
			||||||
 | 
					.It command
 | 
				
			||||||
 | 
					The command run when the menu item is chosen.
 | 
				
			||||||
 | 
					.El
 | 
				
			||||||
 | 
					.Pp
 | 
				
			||||||
 | 
					An empty menu item is a separator line.
 | 
				
			||||||
 | 
					.Pp
 | 
				
			||||||
 | 
					.Fl T
 | 
				
			||||||
 | 
					is a format for the menu title (see
 | 
				
			||||||
 | 
					.Sx FORMATS ) .
 | 
				
			||||||
 | 
					.Pp
 | 
				
			||||||
 | 
					.Fl x
 | 
				
			||||||
 | 
					and
 | 
				
			||||||
 | 
					.Fl y
 | 
				
			||||||
 | 
					give the position of the menu.
 | 
				
			||||||
 | 
					Both may be a row or column number, or one of the following special values:
 | 
				
			||||||
 | 
					.Bl -column "XXXXX" "XXXX" -offset indent
 | 
				
			||||||
 | 
					.It Sy "Value" Ta Sy "Flag" Ta Sy "Meaning"
 | 
				
			||||||
 | 
					.It Li "R" Ta Fl x Ta "The right side of the terminal"
 | 
				
			||||||
 | 
					.It Li "P" Ta "Both" Ta "The bottom left of the pane"
 | 
				
			||||||
 | 
					.It Li "M" Ta "Both" Ta "The mouse position"
 | 
				
			||||||
 | 
					.It Li "W" Ta Fl x Ta "The window position on the status line"
 | 
				
			||||||
 | 
					.It Li "S" Ta Fl y Ta "The line above or below the status line"
 | 
				
			||||||
 | 
					.El
 | 
				
			||||||
 | 
					.Pp
 | 
				
			||||||
 | 
					Each menu consists of items followed by a key shortcut shown in brackets.
 | 
				
			||||||
 | 
					If the menu is too large to fit on the terminal, it is not displayed.
 | 
				
			||||||
 | 
					Pressing the key shortcut chooses the corresponding item.
 | 
				
			||||||
 | 
					If the mouse is enabled and the menu is opened from a mouse key binding, releasing
 | 
				
			||||||
 | 
					the mouse button with an item selected will choose that item.
 | 
				
			||||||
 | 
					The following keys are also available:
 | 
				
			||||||
 | 
					.Bl -column "Key" "Function" -offset indent
 | 
				
			||||||
 | 
					.It Sy "Key" Ta Sy "Function"
 | 
				
			||||||
 | 
					.It Li "Enter" Ta "Choose selected item"
 | 
				
			||||||
 | 
					.It Li "Up" Ta "Select previous item"
 | 
				
			||||||
 | 
					.It Li "Down" Ta "Select next item"
 | 
				
			||||||
 | 
					.It Li "q" Ta "Exit menu"
 | 
				
			||||||
 | 
					.El
 | 
				
			||||||
.It Xo Ic display-message
 | 
					.It Xo Ic display-message
 | 
				
			||||||
.Op Fl aIpv
 | 
					.Op Fl aIpv
 | 
				
			||||||
.Op Fl c Ar target-client
 | 
					.Op Fl c Ar target-client
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										24
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								tmux.h
									
									
									
									
									
								
							@@ -750,20 +750,20 @@ struct screen_redraw_ctx {
 | 
				
			|||||||
#define screen_hsize(s) ((s)->grid->hsize)
 | 
					#define screen_hsize(s) ((s)->grid->hsize)
 | 
				
			||||||
#define screen_hlimit(s) ((s)->grid->hlimit)
 | 
					#define screen_hlimit(s) ((s)->grid->hlimit)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Menu item. */
 | 
					 | 
				
			||||||
struct menu_item {
 | 
					 | 
				
			||||||
	char			*name;
 | 
					 | 
				
			||||||
	char			*command;
 | 
					 | 
				
			||||||
	key_code		 key;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Menu. */
 | 
					/* Menu. */
 | 
				
			||||||
 | 
					struct menu_item {
 | 
				
			||||||
 | 
						char		*name;
 | 
				
			||||||
 | 
						char		*command;
 | 
				
			||||||
 | 
						key_code	 key;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
struct menu {
 | 
					struct menu {
 | 
				
			||||||
	char			*title;
 | 
						char			*title;
 | 
				
			||||||
	struct menu_item	*items;
 | 
						struct menu_item	*items;
 | 
				
			||||||
	u_int			 count;
 | 
						u_int			 count;
 | 
				
			||||||
	u_int			 width;
 | 
						u_int			 width;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					typedef void (*menu_choice_cb)(struct menu *, u_int, key_code, void *);
 | 
				
			||||||
 | 
					#define MENU_NOMOUSE 0x1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Window mode. Windows can be in several modes and this is used to call the
 | 
					 * Window mode. Windows can be in several modes and this is used to call the
 | 
				
			||||||
@@ -2554,6 +2554,16 @@ void printflike(1, 2) log_debug(const char *, ...);
 | 
				
			|||||||
__dead void printflike(1, 2) fatal(const char *, ...);
 | 
					__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 */
 | 
				
			||||||
 | 
					struct menu	*menu_create_from_items(struct menu_item *, u_int,
 | 
				
			||||||
 | 
							    struct client *, struct cmd_find_state *, const char *);
 | 
				
			||||||
 | 
					struct menu	*menu_create_from_string(const char *, struct client *,
 | 
				
			||||||
 | 
							    struct cmd_find_state *, const char *);
 | 
				
			||||||
 | 
					void		 menu_free(struct menu *);
 | 
				
			||||||
 | 
					int		 menu_display(struct menu *, int, struct cmdq_item *, u_int,
 | 
				
			||||||
 | 
							    u_int, struct client *, struct cmd_find_state *,
 | 
				
			||||||
 | 
							    menu_choice_cb, void *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* style.c */
 | 
					/* style.c */
 | 
				
			||||||
int		 style_parse(struct style *,const struct grid_cell *,
 | 
					int		 style_parse(struct style *,const struct grid_cell *,
 | 
				
			||||||
		     const char *);
 | 
							     const char *);
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user