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:
		
							
								
								
									
										5
									
								
								cfg.c
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								cfg.c
									
									
									
									
									
								
							@@ -301,9 +301,10 @@ load_cfg(const char *path, struct client *c, struct cmdq_item *item, int quiet)
 | 
			
		||||
		free(buf);
 | 
			
		||||
 | 
			
		||||
		new_item = cmdq_get_command(cmdlist, NULL, NULL, 0);
 | 
			
		||||
		if (item != NULL)
 | 
			
		||||
		if (item != NULL) {
 | 
			
		||||
			cmdq_insert_after(item, new_item);
 | 
			
		||||
		else
 | 
			
		||||
			item = new_item;
 | 
			
		||||
		} else
 | 
			
		||||
			cmdq_append(c, new_item);
 | 
			
		||||
		cmd_list_free(cmdlist);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -39,8 +39,8 @@ const struct cmd_entry cmd_display_message_entry = {
 | 
			
		||||
	.name = "display-message",
 | 
			
		||||
	.alias = "display",
 | 
			
		||||
 | 
			
		||||
	.args = { "ac:pt:F:v", 0, 1 },
 | 
			
		||||
	.usage = "[-apv] [-c target-client] [-F format] "
 | 
			
		||||
	.args = { "ac:Ipt:F:v", 0, 1 },
 | 
			
		||||
	.usage = "[-aIpv] [-c target-client] [-F format] "
 | 
			
		||||
		 CMD_TARGET_PANE_USAGE " [message]",
 | 
			
		||||
 | 
			
		||||
	.target = { 't', CMD_FIND_PANE, 0 },
 | 
			
		||||
@@ -66,10 +66,19 @@ cmd_display_message_exec(struct cmd *self, struct cmdq_item *item)
 | 
			
		||||
	struct winlink		*wl = item->target.wl;
 | 
			
		||||
	struct window_pane	*wp = item->target.wp;
 | 
			
		||||
	const char		*template;
 | 
			
		||||
	char			*msg;
 | 
			
		||||
	char			*msg, *cause;
 | 
			
		||||
	struct format_tree	*ft;
 | 
			
		||||
	int			 flags;
 | 
			
		||||
 | 
			
		||||
	if (args_has(args, 'I')) {
 | 
			
		||||
		if (window_pane_start_input(wp, item, &cause) != 0) {
 | 
			
		||||
			cmdq_error(item, "%s", cause);
 | 
			
		||||
			free(cause);
 | 
			
		||||
			return (CMD_RETURN_ERROR);
 | 
			
		||||
		}
 | 
			
		||||
		return (CMD_RETURN_WAIT);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (args_has(args, 'F') && args->argc != 0) {
 | 
			
		||||
		cmdq_error(item, "only one of -F or argument must be given");
 | 
			
		||||
		return (CMD_RETURN_ERROR);
 | 
			
		||||
 
 | 
			
		||||
@@ -39,9 +39,10 @@ const struct cmd_entry cmd_split_window_entry = {
 | 
			
		||||
	.name = "split-window",
 | 
			
		||||
	.alias = "splitw",
 | 
			
		||||
 | 
			
		||||
	.args = { "bc:de:fF:l:hp:Pt:v", 0, -1 },
 | 
			
		||||
	.usage = "[-bdefhvP] [-c start-directory] [-e environment] [-F format] "
 | 
			
		||||
		 "[-p percentage|-l size] " CMD_TARGET_PANE_USAGE " [command]",
 | 
			
		||||
	.args = { "bc:de:fF:hIl:p:Pt:v", 0, -1 },
 | 
			
		||||
	.usage = "[-bdefhIPv] [-c start-directory] [-e environment] "
 | 
			
		||||
		 "[-F format] [-p percentage|-l size] " CMD_TARGET_PANE_USAGE
 | 
			
		||||
		 " [command]",
 | 
			
		||||
 | 
			
		||||
	.target = { 't', CMD_FIND_PANE, 0 },
 | 
			
		||||
 | 
			
		||||
@@ -62,7 +63,7 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
 | 
			
		||||
	enum layout_type	 type;
 | 
			
		||||
	struct layout_cell	*lc;
 | 
			
		||||
	struct cmd_find_state	 fs;
 | 
			
		||||
	int			 size, percentage, flags;
 | 
			
		||||
	int			 size, percentage, flags, input;
 | 
			
		||||
	const char		*template, *add;
 | 
			
		||||
	char			*cause, *cp;
 | 
			
		||||
	struct args_value	*value;
 | 
			
		||||
@@ -93,12 +94,15 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
 | 
			
		||||
		size = -1;
 | 
			
		||||
 | 
			
		||||
	server_unzoom_window(wp->window);
 | 
			
		||||
	input = (args_has(args, 'I') && args->argc == 0);
 | 
			
		||||
 | 
			
		||||
	flags = 0;
 | 
			
		||||
	if (args_has(args, 'b'))
 | 
			
		||||
		flags |= SPAWN_BEFORE;
 | 
			
		||||
	if (args_has(args, 'f'))
 | 
			
		||||
		flags |= SPAWN_FULLSIZE;
 | 
			
		||||
	if (input || (args->argc == 1 && *args->argv[0] == '\0'))
 | 
			
		||||
		flags |= SPAWN_EMPTY;
 | 
			
		||||
 | 
			
		||||
	lc = layout_split_pane(wp, type, size, flags);
 | 
			
		||||
	if (lc == NULL) {
 | 
			
		||||
@@ -133,10 +137,18 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
 | 
			
		||||
		sc.flags |= SPAWN_DETACHED;
 | 
			
		||||
 | 
			
		||||
	if ((new_wp = spawn_pane(&sc, &cause)) == NULL) {
 | 
			
		||||
		layout_close_pane(new_wp);
 | 
			
		||||
		cmdq_error(item, "create pane failed: %s", cause);
 | 
			
		||||
		free(cause);
 | 
			
		||||
		return (CMD_RETURN_ERROR);
 | 
			
		||||
	}
 | 
			
		||||
	if (input && window_pane_start_input(new_wp, item, &cause) != 0) {
 | 
			
		||||
		layout_close_pane(new_wp);
 | 
			
		||||
		window_remove_pane(wp->window, new_wp);
 | 
			
		||||
		cmdq_error(item, "%s", cause);
 | 
			
		||||
		free(cause);
 | 
			
		||||
		return (CMD_RETURN_ERROR);
 | 
			
		||||
	}
 | 
			
		||||
	if (!args_has(args, 'd'))
 | 
			
		||||
		cmd_find_from_winlink_pane(current, wl, new_wp, 0);
 | 
			
		||||
	server_redraw_window(wp->window);
 | 
			
		||||
@@ -154,5 +166,7 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
 | 
			
		||||
	cmdq_insert_hook(s, item, &fs, "after-split-window");
 | 
			
		||||
 | 
			
		||||
	environ_free(sc.environ);
 | 
			
		||||
	if (input)
 | 
			
		||||
		return (CMD_RETURN_WAIT);
 | 
			
		||||
	return (CMD_RETURN_NORMAL);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										5
									
								
								format.c
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								format.c
									
									
									
									
									
								
							@@ -2047,7 +2047,10 @@ format_defaults_pane(struct format_tree *ft, struct window_pane *wp)
 | 
			
		||||
 | 
			
		||||
	if ((wp->flags & PANE_STATUSREADY) && WIFEXITED(status))
 | 
			
		||||
		format_add(ft, "pane_dead_status", "%d", WEXITSTATUS(status));
 | 
			
		||||
	format_add(ft, "pane_dead", "%d", wp->fd == -1);
 | 
			
		||||
	if (~wp->flags & PANE_EMPTY)
 | 
			
		||||
		format_add(ft, "pane_dead", "%d", wp->fd == -1);
 | 
			
		||||
	else
 | 
			
		||||
		format_add(ft, "pane_dead", "0");
 | 
			
		||||
 | 
			
		||||
	format_add(ft, "pane_left", "%u", wp->xoff);
 | 
			
		||||
	format_add(ft, "pane_top", "%u", wp->yoff);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								input.c
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								input.c
									
									
									
									
									
								
							@@ -1185,6 +1185,8 @@ input_c0_dispatch(struct input_ctx *ictx)
 | 
			
		||||
	case '\013':	/* VT */
 | 
			
		||||
	case '\014':	/* FF */
 | 
			
		||||
		screen_write_linefeed(sctx, 0, ictx->cell.cell.bg);
 | 
			
		||||
		if (s->mode & MODE_CRLF)
 | 
			
		||||
			screen_write_carriagereturn(sctx);
 | 
			
		||||
		break;
 | 
			
		||||
	case '\015':	/* CR */
 | 
			
		||||
		screen_write_carriagereturn(sctx);
 | 
			
		||||
 
 | 
			
		||||
@@ -1681,8 +1681,7 @@ server_client_dispatch(struct imsg *imsg, void *arg)
 | 
			
		||||
			evbuffer_add(c->stdin_data, stdindata.data,
 | 
			
		||||
			    stdindata.size);
 | 
			
		||||
		}
 | 
			
		||||
		c->stdin_callback(c, c->stdin_closed,
 | 
			
		||||
		    c->stdin_callback_data);
 | 
			
		||||
		c->stdin_callback(c, c->stdin_closed, c->stdin_callback_data);
 | 
			
		||||
		break;
 | 
			
		||||
	case MSG_RESIZE:
 | 
			
		||||
		if (datalen != 0)
 | 
			
		||||
 
 | 
			
		||||
@@ -440,7 +440,6 @@ server_check_unattached(void)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Set stdin callback. */
 | 
			
		||||
int
 | 
			
		||||
server_set_stdin_callback(struct client *c, void (*cb)(struct client *, int,
 | 
			
		||||
    void *), void *cb_data, char **cause)
 | 
			
		||||
@@ -454,7 +453,7 @@ server_set_stdin_callback(struct client *c, void (*cb)(struct client *, int,
 | 
			
		||||
		return (-1);
 | 
			
		||||
	}
 | 
			
		||||
	if (c->stdin_callback != NULL) {
 | 
			
		||||
		*cause = xstrdup("stdin in use");
 | 
			
		||||
		*cause = xstrdup("stdin is in use");
 | 
			
		||||
		return (-1);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										48
									
								
								spawn.c
									
									
									
									
									
								
							
							
						
						
									
										48
									
								
								spawn.c
									
									
									
									
									
								
							@@ -330,6 +330,14 @@ spawn_pane(struct spawn_context *sc, char **cause)
 | 
			
		||||
	cmd_log_argv(new_wp->argc, new_wp->argv, __func__);
 | 
			
		||||
	environ_log(child, "%s: environment ", __func__);
 | 
			
		||||
 | 
			
		||||
	/* If the command is empty, don't fork a child process. */
 | 
			
		||||
	if (sc->flags & SPAWN_EMPTY) {
 | 
			
		||||
		new_wp->flags |= PANE_EMPTY;
 | 
			
		||||
		new_wp->base.mode &= ~MODE_CURSOR;
 | 
			
		||||
		new_wp->base.mode |= MODE_CRLF;
 | 
			
		||||
		goto complete;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Initialize the window size. */
 | 
			
		||||
	memset(&ws, 0, sizeof ws);
 | 
			
		||||
	ws.ws_col = screen_size_x(&new_wp->base);
 | 
			
		||||
@@ -353,25 +361,8 @@ spawn_pane(struct spawn_context *sc, char **cause)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* In the parent process, everything is done now. */
 | 
			
		||||
	if (new_wp->pid != 0) {
 | 
			
		||||
		new_wp->pipe_off = 0;
 | 
			
		||||
		new_wp->flags &= ~PANE_EXITED;
 | 
			
		||||
 | 
			
		||||
		sigprocmask(SIG_SETMASK, &oldset, NULL);
 | 
			
		||||
		window_pane_set_event(new_wp);
 | 
			
		||||
 | 
			
		||||
		if (sc->flags & SPAWN_RESPAWN)
 | 
			
		||||
			return (new_wp);
 | 
			
		||||
		if ((~sc->flags & SPAWN_DETACHED) || w->active == NULL) {
 | 
			
		||||
			if (sc->flags & SPAWN_NONOTIFY)
 | 
			
		||||
				window_set_active_pane(w, new_wp, 0);
 | 
			
		||||
			else
 | 
			
		||||
				window_set_active_pane(w, new_wp, 1);
 | 
			
		||||
		}
 | 
			
		||||
		if (~sc->flags & SPAWN_NONOTIFY)
 | 
			
		||||
			notify_window("window-layout-changed", w);
 | 
			
		||||
		return (new_wp);
 | 
			
		||||
	}
 | 
			
		||||
	if (new_wp->pid != 0)
 | 
			
		||||
		goto complete;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Child process. Change to the working directory or home if that
 | 
			
		||||
@@ -431,4 +422,23 @@ spawn_pane(struct spawn_context *sc, char **cause)
 | 
			
		||||
		xasprintf(&argv0, "-%s", new_wp->shell);
 | 
			
		||||
	execl(new_wp->shell, argv0, (char *)NULL);
 | 
			
		||||
	_exit(1);
 | 
			
		||||
 | 
			
		||||
complete:
 | 
			
		||||
	new_wp->pipe_off = 0;
 | 
			
		||||
	new_wp->flags &= ~PANE_EXITED;
 | 
			
		||||
 | 
			
		||||
	sigprocmask(SIG_SETMASK, &oldset, NULL);
 | 
			
		||||
	window_pane_set_event(new_wp);
 | 
			
		||||
 | 
			
		||||
	if (sc->flags & SPAWN_RESPAWN)
 | 
			
		||||
		return (new_wp);
 | 
			
		||||
	if ((~sc->flags & SPAWN_DETACHED) || w->active == NULL) {
 | 
			
		||||
		if (sc->flags & SPAWN_NONOTIFY)
 | 
			
		||||
			window_set_active_pane(w, new_wp, 0);
 | 
			
		||||
		else
 | 
			
		||||
			window_set_active_pane(w, new_wp, 1);
 | 
			
		||||
	}
 | 
			
		||||
	if (~sc->flags & SPAWN_NONOTIFY)
 | 
			
		||||
		notify_window("window-layout-changed", w);
 | 
			
		||||
	return (new_wp);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										26
									
								
								tmux.1
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								tmux.1
									
									
									
									
									
								
							@@ -2209,7 +2209,7 @@ is given and the selected window is already the current window,
 | 
			
		||||
the command behaves like
 | 
			
		||||
.Ic last-window .
 | 
			
		||||
.It Xo Ic split-window
 | 
			
		||||
.Op Fl bdfhvP
 | 
			
		||||
.Op Fl bdfhIvP
 | 
			
		||||
.Op Fl c Ar start-directory
 | 
			
		||||
.Op Fl e Ar environment
 | 
			
		||||
.Oo Fl l
 | 
			
		||||
@@ -2245,6 +2245,24 @@ option creates a new pane spanning the full window height (with
 | 
			
		||||
or full window width (with
 | 
			
		||||
.Fl v ) ,
 | 
			
		||||
instead of splitting the active pane.
 | 
			
		||||
.Pp
 | 
			
		||||
An empty
 | 
			
		||||
.Ar shell-command
 | 
			
		||||
('') will create a pane with no command running in it.
 | 
			
		||||
Output can be sent to such a pane with the
 | 
			
		||||
.Ic display-message
 | 
			
		||||
command.
 | 
			
		||||
The
 | 
			
		||||
.Fl I
 | 
			
		||||
flag (if
 | 
			
		||||
.Ar shell-command
 | 
			
		||||
is not specified or empty)
 | 
			
		||||
will create an empty pane and forward any output from stdin to it.
 | 
			
		||||
For example:
 | 
			
		||||
.Bd -literal -offset indent
 | 
			
		||||
$ make 2>&1|tmux splitw -dI &
 | 
			
		||||
.Ed
 | 
			
		||||
.Pp
 | 
			
		||||
All other options have the same meaning as for the
 | 
			
		||||
.Ic new-window
 | 
			
		||||
command.
 | 
			
		||||
@@ -4435,7 +4453,7 @@ option.
 | 
			
		||||
This command works only from inside
 | 
			
		||||
.Nm .
 | 
			
		||||
.It Xo Ic display-message
 | 
			
		||||
.Op Fl apv
 | 
			
		||||
.Op Fl aIpv
 | 
			
		||||
.Op Fl c Ar target-client
 | 
			
		||||
.Op Fl t Ar target-pane
 | 
			
		||||
.Op Ar message
 | 
			
		||||
@@ -4462,6 +4480,10 @@ is given, otherwise the active pane for the session attached to
 | 
			
		||||
prints verbose logging as the format is parsed and
 | 
			
		||||
.Fl a
 | 
			
		||||
lists the format variables and their values.
 | 
			
		||||
.Pp
 | 
			
		||||
.Fl I
 | 
			
		||||
forwards any input read from stdin to the empty pane given by
 | 
			
		||||
.Ar target-pane .
 | 
			
		||||
.El
 | 
			
		||||
.Sh BUFFERS
 | 
			
		||||
.Nm
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										5
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								tmux.h
									
									
									
									
									
								
							@@ -524,6 +524,7 @@ struct msg_stderr_data {
 | 
			
		||||
#define MODE_FOCUSON 0x800
 | 
			
		||||
#define MODE_MOUSE_ALL 0x1000
 | 
			
		||||
#define MODE_ORIGIN 0x2000
 | 
			
		||||
#define MODE_CRLF 0x4000
 | 
			
		||||
 | 
			
		||||
#define ALL_MODES 0xffffff
 | 
			
		||||
#define ALL_MOUSE_MODES (MODE_MOUSE_STANDARD|MODE_MOUSE_BUTTON|MODE_MOUSE_ALL)
 | 
			
		||||
@@ -804,6 +805,7 @@ struct window_pane {
 | 
			
		||||
#define PANE_EXITED 0x100
 | 
			
		||||
#define PANE_STATUSREADY 0x200
 | 
			
		||||
#define PANE_STATUSDRAWN 0x400
 | 
			
		||||
#define PANE_EMPTY 0x800
 | 
			
		||||
 | 
			
		||||
	int		 argc;
 | 
			
		||||
	char	       **argv;
 | 
			
		||||
@@ -1600,6 +1602,7 @@ struct spawn_context {
 | 
			
		||||
#define SPAWN_BEFORE 0x8
 | 
			
		||||
#define SPAWN_NONOTIFY 0x10
 | 
			
		||||
#define SPAWN_FULLSIZE 0x20
 | 
			
		||||
#define SPAWN_EMPTY 0x40
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* tmux.c */
 | 
			
		||||
@@ -2319,6 +2322,8 @@ void		 window_add_ref(struct window *, const char *);
 | 
			
		||||
void		 window_remove_ref(struct window *, const char *);
 | 
			
		||||
void		 winlink_clear_flags(struct winlink *);
 | 
			
		||||
int		 winlink_shuffle_up(struct session *, struct winlink *);
 | 
			
		||||
int		 window_pane_start_input(struct window_pane *,
 | 
			
		||||
		     struct cmdq_item *, char **);
 | 
			
		||||
 | 
			
		||||
/* layout.c */
 | 
			
		||||
u_int		 layout_count_cells(struct layout_cell *);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										47
									
								
								window.c
									
									
									
									
									
								
							
							
						
						
									
										47
									
								
								window.c
									
									
									
									
									
								
							@@ -70,6 +70,11 @@ const struct window_mode *all_window_modes[] = {
 | 
			
		||||
	NULL
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct window_pane_input_data {
 | 
			
		||||
	struct cmdq_item	*item;
 | 
			
		||||
	u_int			 wp;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct window_pane *window_pane_create(struct window *, u_int, u_int,
 | 
			
		||||
		    u_int);
 | 
			
		||||
static void	window_pane_destroy(struct window_pane *);
 | 
			
		||||
@@ -1467,3 +1472,45 @@ winlink_shuffle_up(struct session *s, struct winlink *wl)
 | 
			
		||||
 | 
			
		||||
	return (idx);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
window_pane_input_callback(struct client *c, int closed, void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct window_pane_input_data	*cdata = data;
 | 
			
		||||
	struct window_pane		*wp;
 | 
			
		||||
 | 
			
		||||
	wp = window_pane_find_by_id(cdata->wp);
 | 
			
		||||
	if (wp == NULL || closed || c->flags & CLIENT_DEAD) {
 | 
			
		||||
		c->stdin_callback = NULL;
 | 
			
		||||
		server_client_unref(c);
 | 
			
		||||
 | 
			
		||||
		cdata->item->flags &= ~CMDQ_WAITING;
 | 
			
		||||
		free(cdata);
 | 
			
		||||
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (evbuffer_add_buffer(wp->event->input, c->stdin_data) != 0)
 | 
			
		||||
		evbuffer_drain(c->stdin_data, EVBUFFER_LENGTH(c->stdin_data));
 | 
			
		||||
	input_parse(wp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
window_pane_start_input(struct window_pane *wp, struct cmdq_item *item,
 | 
			
		||||
    char **cause)
 | 
			
		||||
{
 | 
			
		||||
	struct client			*c = item->client;
 | 
			
		||||
	struct window_pane_input_data	*cdata;
 | 
			
		||||
 | 
			
		||||
	if (~wp->flags & PANE_EMPTY) {
 | 
			
		||||
		*cause = xstrdup("pane is not empty");
 | 
			
		||||
		return (-1);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cdata = xmalloc(sizeof *cdata);
 | 
			
		||||
	cdata->item = item;
 | 
			
		||||
	cdata->wp = wp->id;
 | 
			
		||||
 | 
			
		||||
	return (server_set_stdin_callback(c, window_pane_input_callback, cdata,
 | 
			
		||||
	    cause));
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user