mirror of
				https://github.com/tmux/tmux.git
				synced 2025-10-26 12:27:15 +00:00 
			
		
		
		
	Drop support for popups where the content is provided directly to tmux
(which does not have many practical uses) and only support running a program in the popup. display-popup is now simpler and can accept multiple arguments to avoid escaping problems (like the other commands).
This commit is contained in:
		| @@ -18,6 +18,7 @@ | |||||||
|  |  | ||||||
| #include <sys/types.h> | #include <sys/types.h> | ||||||
|  |  | ||||||
|  | #include <paths.h> | ||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
| #include <string.h> | #include <string.h> | ||||||
|  |  | ||||||
| @@ -50,10 +51,10 @@ const struct cmd_entry cmd_display_popup_entry = { | |||||||
| 	.name = "display-popup", | 	.name = "display-popup", | ||||||
| 	.alias = "popup", | 	.alias = "popup", | ||||||
|  |  | ||||||
| 	.args = { "CEKc:d:h:R:t:w:x:y:", 0, -1 }, | 	.args = { "Cc:d:Eh:t:w:x:y:", 0, -1 }, | ||||||
| 	.usage = "[-CEK] [-c target-client] [-d start-directory] [-h height] " | 	.usage = "[-CE] [-c target-client] [-d start-directory] [-h height] " | ||||||
| 	         "[-R shell-command] " CMD_TARGET_PANE_USAGE " [-w width] " | 	         CMD_TARGET_PANE_USAGE " [-w width] " | ||||||
| 	         "[-x position] [-y position] [command line ...]", | 	         "[-x position] [-y position] [command]", | ||||||
|  |  | ||||||
| 	.target = { 't', CMD_FIND_PANE, 0 }, | 	.target = { 't', CMD_FIND_PANE, 0 }, | ||||||
|  |  | ||||||
| @@ -325,13 +326,14 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item) | |||||||
| { | { | ||||||
| 	struct args		*args = cmd_get_args(self); | 	struct args		*args = cmd_get_args(self); | ||||||
| 	struct cmd_find_state	*target = cmdq_get_target(item); | 	struct cmd_find_state	*target = cmdq_get_target(item); | ||||||
|  | 	struct session		*s = target->s; | ||||||
| 	struct client		*tc = cmdq_get_target_client(item); | 	struct client		*tc = cmdq_get_target_client(item); | ||||||
| 	struct tty		*tty = &tc->tty; | 	struct tty		*tty = &tc->tty; | ||||||
| 	const char		*value, *cmd = NULL, **lines = NULL; | 	const char		*value, *shell[] = { NULL, NULL }; | ||||||
| 	const char		*shellcmd = NULL; | 	const char		*shellcmd = NULL; | ||||||
| 	char			*cwd, *cause; | 	char			*cwd, *cause, **argv = args->argv; | ||||||
| 	int			 flags = 0; | 	int			 flags = 0, argc = args->argc; | ||||||
| 	u_int			 px, py, w, h, nlines = 0; | 	u_int			 px, py, w, h; | ||||||
|  |  | ||||||
| 	if (args_has(args, 'C')) { | 	if (args_has(args, 'C')) { | ||||||
| 		server_client_clear_overlay(tc); | 		server_client_clear_overlay(tc); | ||||||
| @@ -340,17 +342,7 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item) | |||||||
| 	if (tc->overlay_draw != NULL) | 	if (tc->overlay_draw != NULL) | ||||||
| 		return (CMD_RETURN_NORMAL); | 		return (CMD_RETURN_NORMAL); | ||||||
|  |  | ||||||
| 	if (args->argc >= 1) | 	h = tty->sy / 2; | ||||||
| 		cmd = args->argv[0]; |  | ||||||
| 	if (args->argc >= 2) { |  | ||||||
| 		lines = (const char **)args->argv + 1; |  | ||||||
| 		nlines = args->argc - 1; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if (nlines != 0) |  | ||||||
| 		h = popup_height(nlines, lines) + 2; |  | ||||||
| 	else |  | ||||||
| 		h = tty->sy / 2; |  | ||||||
| 	if (args_has(args, 'h')) { | 	if (args_has(args, 'h')) { | ||||||
| 		h = args_percentage(args, 'h', 1, tty->sy, tty->sy, &cause); | 		h = args_percentage(args, 'h', 1, tty->sy, tty->sy, &cause); | ||||||
| 		if (cause != NULL) { | 		if (cause != NULL) { | ||||||
| @@ -360,10 +352,7 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item) | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (nlines != 0) | 	w = tty->sx / 2; | ||||||
| 		w = popup_width(item, nlines, lines, tc, target) + 2; |  | ||||||
| 	else |  | ||||||
| 		w = tty->sx / 2; |  | ||||||
| 	if (args_has(args, 'w')) { | 	if (args_has(args, 'w')) { | ||||||
| 		w = args_percentage(args, 'w', 1, tty->sx, tty->sx, &cause); | 		w = args_percentage(args, 'w', 1, tty->sx, tty->sx, &cause); | ||||||
| 		if (cause != NULL) { | 		if (cause != NULL) { | ||||||
| @@ -384,20 +373,26 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item) | |||||||
| 	if (value != NULL) | 	if (value != NULL) | ||||||
| 		cwd = format_single_from_target(item, value); | 		cwd = format_single_from_target(item, value); | ||||||
| 	else | 	else | ||||||
| 		cwd = xstrdup(server_client_get_cwd(tc, target->s)); | 		cwd = xstrdup(server_client_get_cwd(tc, s)); | ||||||
|  | 	if (argc == 0) | ||||||
|  | 		shellcmd = options_get_string(s->options, "default-command"); | ||||||
|  | 	else if (argc == 1) | ||||||
|  | 		shellcmd = argv[0]; | ||||||
|  | 	if (argc <= 1 && (shellcmd == NULL || *shellcmd == '\0')) { | ||||||
|  | 		shellcmd = NULL; | ||||||
|  | 		shell[0] = options_get_string(s->options, "default-shell"); | ||||||
|  | 		if (!checkshell(shell[0])) | ||||||
|  | 			shell[0] = _PATH_BSHELL; | ||||||
|  | 		argc = 1; | ||||||
|  | 		argv = (char**)shell; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	value = args_get(args, 'R'); |  | ||||||
| 	if (value != NULL) |  | ||||||
| 		shellcmd = format_single_from_target(item, value); |  | ||||||
|  |  | ||||||
| 	if (args_has(args, 'K')) |  | ||||||
| 		flags |= POPUP_WRITEKEYS; |  | ||||||
| 	if (args_has(args, 'E') > 1) | 	if (args_has(args, 'E') > 1) | ||||||
| 		flags |= POPUP_CLOSEEXITZERO; | 		flags |= POPUP_CLOSEEXITZERO; | ||||||
| 	else if (args_has(args, 'E')) | 	else if (args_has(args, 'E')) | ||||||
| 		flags |= POPUP_CLOSEEXIT; | 		flags |= POPUP_CLOSEEXIT; | ||||||
| 	if (popup_display(flags, item, px, py, w, h, nlines, lines, shellcmd, | 	if (popup_display(flags, item, px, py, w, h, shellcmd, argc, argv, cwd, | ||||||
| 	    cmd, cwd, tc, target, NULL, NULL) != 0) | 	    tc, s, NULL, NULL) != 0) | ||||||
| 		return (CMD_RETURN_NORMAL); | 		return (CMD_RETURN_NORMAL); | ||||||
| 	return (CMD_RETURN_WAIT); | 	return (CMD_RETURN_WAIT); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -128,7 +128,7 @@ cmd_if_shell_exec(struct cmd *self, struct cmdq_item *item) | |||||||
| 		cdata->input.c->references++; | 		cdata->input.c->references++; | ||||||
| 	cmd_find_copy_state(&cdata->input.fs, target); | 	cmd_find_copy_state(&cdata->input.fs, target); | ||||||
|  |  | ||||||
| 	if (job_run(shellcmd, s, | 	if (job_run(shellcmd, 0, NULL, s, | ||||||
| 	    server_client_get_cwd(cmdq_get_client(item), s), NULL, | 	    server_client_get_cwd(cmdq_get_client(item), s), NULL, | ||||||
| 	    cmd_if_shell_callback, cmd_if_shell_free, cdata, 0, -1, | 	    cmd_if_shell_callback, cmd_if_shell_free, cdata, 0, -1, | ||||||
| 	    -1) == NULL) { | 	    -1) == NULL) { | ||||||
|   | |||||||
| @@ -174,7 +174,7 @@ cmd_run_shell_timer(__unused int fd, __unused short events, void* arg) | |||||||
| 	enum cmd_parse_status		 status; | 	enum cmd_parse_status		 status; | ||||||
|  |  | ||||||
| 	if (cmd != NULL && cdata->shell) { | 	if (cmd != NULL && cdata->shell) { | ||||||
| 		if (job_run(cmd, cdata->s, cdata->cwd, NULL, | 		if (job_run(cmd, 0, NULL, cdata->s, cdata->cwd, NULL, | ||||||
| 		    cmd_run_shell_callback, cmd_run_shell_free, cdata, | 		    cmd_run_shell_callback, cmd_run_shell_free, cdata, | ||||||
| 		    cdata->flags, -1, -1) == NULL) | 		    cdata->flags, -1, -1) == NULL) | ||||||
| 			cmd_run_shell_free(cdata); | 			cmd_run_shell_free(cdata); | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								format.c
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								format.c
									
									
									
									
									
								
							| @@ -394,7 +394,7 @@ format_job_get(struct format_expand_state *es, const char *cmd) | |||||||
| 	if (force && fj->job != NULL) | 	if (force && fj->job != NULL) | ||||||
| 	       job_free(fj->job); | 	       job_free(fj->job); | ||||||
| 	if (force || (fj->job == NULL && fj->last != t)) { | 	if (force || (fj->job == NULL && fj->last != t)) { | ||||||
| 		fj->job = job_run(expanded, NULL, | 		fj->job = job_run(expanded, 0, NULL, NULL, | ||||||
| 		    server_client_get_cwd(ft->client, NULL), format_job_update, | 		    server_client_get_cwd(ft->client, NULL), format_job_update, | ||||||
| 		    format_job_complete, NULL, fj, JOB_NOWAIT, -1, -1); | 		    format_job_complete, NULL, fj, JOB_NOWAIT, -1, -1); | ||||||
| 		if (fj->job == NULL) { | 		if (fj->job == NULL) { | ||||||
|   | |||||||
							
								
								
									
										46
									
								
								job.c
									
									
									
									
									
								
							
							
						
						
									
										46
									
								
								job.c
									
									
									
									
									
								
							| @@ -68,19 +68,20 @@ struct job { | |||||||
| /* All jobs list. */ | /* All jobs list. */ | ||||||
| static LIST_HEAD(joblist, job) all_jobs = LIST_HEAD_INITIALIZER(all_jobs); | static LIST_HEAD(joblist, job) all_jobs = LIST_HEAD_INITIALIZER(all_jobs); | ||||||
|  |  | ||||||
| /* Start a job running, if it isn't already. */ | /* Start a job running. */ | ||||||
| struct job * | struct job * | ||||||
| job_run(const char *cmd, struct session *s, const char *cwd, | job_run(const char *cmd, int argc, char **argv, struct session *s, | ||||||
|     job_update_cb updatecb, job_complete_cb completecb, job_free_cb freecb, |     const char *cwd, job_update_cb updatecb, job_complete_cb completecb, | ||||||
|     void *data, int flags, int sx, int sy) |     job_free_cb freecb, void *data, int flags, int sx, int sy) | ||||||
| { | { | ||||||
| 	struct job	*job; | 	struct job	 *job; | ||||||
| 	struct environ	*env; | 	struct environ	 *env; | ||||||
| 	pid_t		 pid; | 	pid_t		  pid; | ||||||
| 	int		 nullfd, out[2], master; | 	int		  nullfd, out[2], master; | ||||||
| 	const char	*home; | 	const char	 *home; | ||||||
| 	sigset_t	 set, oldset; | 	sigset_t	  set, oldset; | ||||||
| 	struct winsize	 ws; | 	struct winsize	  ws; | ||||||
|  | 	char		**argvp; | ||||||
|  |  | ||||||
| 	/* | 	/* | ||||||
| 	 * Do not set TERM during .tmux.conf, it is nice to be able to use | 	 * Do not set TERM during .tmux.conf, it is nice to be able to use | ||||||
| @@ -101,7 +102,13 @@ job_run(const char *cmd, struct session *s, const char *cwd, | |||||||
| 			goto fail; | 			goto fail; | ||||||
| 		pid = fork(); | 		pid = fork(); | ||||||
| 	} | 	} | ||||||
| 	log_debug("%s: cmd=%s, cwd=%s", __func__, cmd, cwd == NULL ? "" : cwd); | 	if (cmd == NULL) { | ||||||
|  | 		cmd_log_argv(argc, argv, "%s:", __func__); | ||||||
|  | 		log_debug("%s: cwd=%s", __func__, cwd == NULL ? "" : cwd); | ||||||
|  | 	} else { | ||||||
|  | 		log_debug("%s: cmd=%s, cwd=%s", __func__, cmd, | ||||||
|  | 		    cwd == NULL ? "" : cwd); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	switch (pid) { | 	switch (pid) { | ||||||
| 	case -1: | 	case -1: | ||||||
| @@ -141,8 +148,14 @@ job_run(const char *cmd, struct session *s, const char *cwd, | |||||||
| 		} | 		} | ||||||
| 		closefrom(STDERR_FILENO + 1); | 		closefrom(STDERR_FILENO + 1); | ||||||
|  |  | ||||||
| 		execl(_PATH_BSHELL, "sh", "-c", cmd, (char *) NULL); | 		if (cmd != NULL) { | ||||||
| 		fatal("execl failed"); | 			execl(_PATH_BSHELL, "sh", "-c", cmd, (char *) NULL); | ||||||
|  | 			fatal("execl failed"); | ||||||
|  | 		} else { | ||||||
|  | 			argvp = cmd_copy_argv(argc, argv); | ||||||
|  | 			execvp(argvp[0], argvp); | ||||||
|  | 			fatal("execvp failed"); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	sigprocmask(SIG_SETMASK, &oldset, NULL); | 	sigprocmask(SIG_SETMASK, &oldset, NULL); | ||||||
| @@ -152,7 +165,10 @@ job_run(const char *cmd, struct session *s, const char *cwd, | |||||||
| 	job->state = JOB_RUNNING; | 	job->state = JOB_RUNNING; | ||||||
| 	job->flags = flags; | 	job->flags = flags; | ||||||
|  |  | ||||||
| 	job->cmd = xstrdup(cmd); | 	if (cmd != NULL) | ||||||
|  | 		job->cmd = xstrdup(cmd); | ||||||
|  | 	else | ||||||
|  | 		job->cmd = cmd_stringify_argv(argc, argv); | ||||||
| 	job->pid = pid; | 	job->pid = pid; | ||||||
| 	job->status = 0; | 	job->status = 0; | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										207
									
								
								popup.c
									
									
									
									
									
								
							
							
						
						
									
										207
									
								
								popup.c
									
									
									
									
									
								
							| @@ -32,13 +32,7 @@ struct popup_data { | |||||||
| 	struct cmdq_item	 *item; | 	struct cmdq_item	 *item; | ||||||
| 	int			  flags; | 	int			  flags; | ||||||
|  |  | ||||||
| 	char			**lines; |  | ||||||
| 	u_int			  nlines; |  | ||||||
|  |  | ||||||
| 	char			 *cmd; |  | ||||||
| 	struct cmd_find_state	  fs; |  | ||||||
| 	struct screen		  s; | 	struct screen		  s; | ||||||
|  |  | ||||||
| 	struct job		 *job; | 	struct job		 *job; | ||||||
| 	struct input_ctx	 *ictx; | 	struct input_ctx	 *ictx; | ||||||
| 	int			  status; | 	int			  status; | ||||||
| @@ -105,54 +99,11 @@ popup_init_ctx_cb(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx) | |||||||
| 	ttyctx->arg = pd; | 	ttyctx->arg = pd; | ||||||
| } | } | ||||||
|  |  | ||||||
| static void |  | ||||||
| popup_write_screen(struct client *c, struct popup_data *pd) |  | ||||||
| { |  | ||||||
| 	struct cmdq_item	*item = pd->item; |  | ||||||
| 	struct screen_write_ctx	 ctx; |  | ||||||
| 	char			*copy, *next, *loop, *tmp; |  | ||||||
| 	struct format_tree	*ft; |  | ||||||
| 	u_int			 i, y; |  | ||||||
|  |  | ||||||
| 	ft = format_create(c, item, FORMAT_NONE, 0); |  | ||||||
| 	if (cmd_find_valid_state(&pd->fs)) |  | ||||||
| 		format_defaults(ft, c, pd->fs.s, pd->fs.wl, pd->fs.wp); |  | ||||||
| 	else |  | ||||||
| 		format_defaults(ft, c, NULL, NULL, NULL); |  | ||||||
|  |  | ||||||
| 	screen_write_start(&ctx, &pd->s); |  | ||||||
| 	screen_write_clearscreen(&ctx, 8); |  | ||||||
|  |  | ||||||
| 	y = 0; |  | ||||||
| 	for (i = 0; i < pd->nlines; i++) { |  | ||||||
| 		if (y == pd->sy - 2) |  | ||||||
| 			break; |  | ||||||
| 		copy = next = xstrdup(pd->lines[i]); |  | ||||||
| 		while ((loop = strsep(&next, "\n")) != NULL) { |  | ||||||
| 			if (y == pd->sy - 2) |  | ||||||
| 				break; |  | ||||||
| 			tmp = format_expand(ft, loop); |  | ||||||
| 			screen_write_cursormove(&ctx, 0, y, 0); |  | ||||||
| 			format_draw(&ctx, &grid_default_cell, pd->sx - 2, tmp, |  | ||||||
| 			    NULL); |  | ||||||
| 			free(tmp); |  | ||||||
| 			y++; |  | ||||||
| 		} |  | ||||||
| 		free(copy); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	format_free(ft); |  | ||||||
| 	screen_write_cursormove(&ctx, 0, y, 0); |  | ||||||
| 	screen_write_stop(&ctx); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static struct screen * | static struct screen * | ||||||
| popup_mode_cb(struct client *c, u_int *cx, u_int *cy) | popup_mode_cb(struct client *c, u_int *cx, u_int *cy) | ||||||
| { | { | ||||||
| 	struct popup_data	*pd = c->overlay_data; | 	struct popup_data	*pd = c->overlay_data; | ||||||
|  |  | ||||||
| 	if (pd->ictx == NULL) |  | ||||||
| 		return (0); |  | ||||||
| 	*cx = pd->px + 1 + pd->s.cx; | 	*cx = pd->px + 1 + pd->s.cx; | ||||||
| 	*cy = pd->py + 1 + pd->s.cy; | 	*cy = pd->py + 1 + pd->s.cy; | ||||||
| 	return (&pd->s); | 	return (&pd->s); | ||||||
| @@ -200,14 +151,12 @@ popup_free_cb(struct client *c) | |||||||
| { | { | ||||||
| 	struct popup_data	*pd = c->overlay_data; | 	struct popup_data	*pd = c->overlay_data; | ||||||
| 	struct cmdq_item	*item = pd->item; | 	struct cmdq_item	*item = pd->item; | ||||||
| 	u_int			 i; |  | ||||||
|  |  | ||||||
| 	if (pd->cb != NULL) | 	if (pd->cb != NULL) | ||||||
| 		pd->cb(pd->status, pd->arg); | 		pd->cb(pd->status, pd->arg); | ||||||
|  |  | ||||||
| 	if (item != NULL) { | 	if (item != NULL) { | ||||||
| 		if (pd->ictx != NULL && | 		if (cmdq_get_client(item) != NULL && | ||||||
| 		    cmdq_get_client(item) != NULL && |  | ||||||
| 		    cmdq_get_client(item)->session == NULL) | 		    cmdq_get_client(item)->session == NULL) | ||||||
| 			cmdq_get_client(item)->retval = pd->status; | 			cmdq_get_client(item)->retval = pd->status; | ||||||
| 		cmdq_continue(item); | 		cmdq_continue(item); | ||||||
| @@ -216,15 +165,9 @@ popup_free_cb(struct client *c) | |||||||
|  |  | ||||||
| 	if (pd->job != NULL) | 	if (pd->job != NULL) | ||||||
| 		job_free(pd->job); | 		job_free(pd->job); | ||||||
| 	if (pd->ictx != NULL) | 	input_free(pd->ictx); | ||||||
| 		input_free(pd->ictx); |  | ||||||
|  |  | ||||||
| 	for (i = 0; i < pd->nlines; i++) |  | ||||||
| 		free(pd->lines[i]); |  | ||||||
| 	free(pd->lines); |  | ||||||
|  |  | ||||||
| 	screen_free(&pd->s); | 	screen_free(&pd->s); | ||||||
| 	free(pd->cmd); |  | ||||||
| 	free(pd); | 	free(pd); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -263,9 +206,7 @@ popup_handle_drag(struct client *c, struct popup_data *pd, | |||||||
| 		pd->sy = m->y - pd->py; | 		pd->sy = m->y - pd->py; | ||||||
|  |  | ||||||
| 		screen_resize(&pd->s, pd->sx - 2, pd->sy - 2, 0); | 		screen_resize(&pd->s, pd->sx - 2, pd->sy - 2, 0); | ||||||
| 		if (pd->ictx == NULL) | 		if (pd->job != NULL) | ||||||
| 			popup_write_screen(c, pd); |  | ||||||
| 		else if (pd->job != NULL) |  | ||||||
| 			job_resize(pd->job, pd->sx - 2, pd->sy - 2); | 			job_resize(pd->job, pd->sx - 2, pd->sy - 2); | ||||||
| 		server_redraw_client(c); | 		server_redraw_client(c); | ||||||
| 	} | 	} | ||||||
| @@ -276,13 +217,8 @@ popup_key_cb(struct client *c, struct key_event *event) | |||||||
| { | { | ||||||
| 	struct popup_data	*pd = c->overlay_data; | 	struct popup_data	*pd = c->overlay_data; | ||||||
| 	struct mouse_event	*m = &event->m; | 	struct mouse_event	*m = &event->m; | ||||||
| 	struct cmd_find_state	*fs = &pd->fs; | 	const char		*buf; | ||||||
| 	struct format_tree	*ft; |  | ||||||
| 	const char		*cmd, *buf; |  | ||||||
| 	size_t			 len; | 	size_t			 len; | ||||||
| 	struct cmdq_state	*state; |  | ||||||
| 	enum cmd_parse_status	 status; |  | ||||||
| 	char			*error; |  | ||||||
|  |  | ||||||
| 	if (KEYC_IS_MOUSE(event->key)) { | 	if (KEYC_IS_MOUSE(event->key)) { | ||||||
| 		if (pd->dragging != OFF) { | 		if (pd->dragging != OFF) { | ||||||
| @@ -314,13 +250,11 @@ popup_key_cb(struct client *c, struct key_event *event) | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (pd->ictx != NULL && (pd->flags & POPUP_WRITEKEYS)) { | 	if ((((pd->flags & (POPUP_CLOSEEXIT|POPUP_CLOSEEXITZERO)) == 0) || | ||||||
| 		if (((pd->flags & (POPUP_CLOSEEXIT|POPUP_CLOSEEXITZERO)) == 0 || | 	    pd->job == NULL) && | ||||||
| 		    pd->job == NULL) && | 	    (event->key == '\033' || event->key == '\003')) | ||||||
| 		    (event->key == '\033' || event->key == '\003')) | 		return (1); | ||||||
| 			return (1); | 	if (pd->job != NULL) { | ||||||
| 		if (pd->job == NULL) |  | ||||||
| 			return (0); |  | ||||||
| 		if (KEYC_IS_MOUSE(event->key)) { | 		if (KEYC_IS_MOUSE(event->key)) { | ||||||
| 			/* Must be inside, checked already. */ | 			/* Must be inside, checked already. */ | ||||||
| 			if (!input_key_get_mouse(&pd->s, m, m->x - pd->px - 1, | 			if (!input_key_get_mouse(&pd->s, m, m->x - pd->px - 1, | ||||||
| @@ -330,40 +264,8 @@ popup_key_cb(struct client *c, struct key_event *event) | |||||||
| 			return (0); | 			return (0); | ||||||
| 		} | 		} | ||||||
| 		input_key(&pd->s, job_get_event(pd->job), event->key); | 		input_key(&pd->s, job_get_event(pd->job), event->key); | ||||||
| 		return (0); |  | ||||||
| 	} | 	} | ||||||
|  | 	return (0); | ||||||
| 	if (pd->cmd == NULL) |  | ||||||
| 		return (1); |  | ||||||
|  |  | ||||||
| 	ft = format_create(NULL, pd->item, FORMAT_NONE, 0); |  | ||||||
| 	if (cmd_find_valid_state(fs)) |  | ||||||
| 		format_defaults(ft, c, fs->s, fs->wl, fs->wp); |  | ||||||
| 	else |  | ||||||
| 		format_defaults(ft, c, NULL, NULL, NULL); |  | ||||||
| 	format_add(ft, "popup_key", "%s", key_string_lookup_key(event->key, 0)); |  | ||||||
| 	if (KEYC_IS_MOUSE(event->key)) { |  | ||||||
| 		format_add(ft, "popup_mouse", "1"); |  | ||||||
| 		format_add(ft, "popup_mouse_x", "%u", m->x - pd->px); |  | ||||||
| 		format_add(ft, "popup_mouse_y", "%u", m->y - pd->py); |  | ||||||
| 	} |  | ||||||
| 	cmd = format_expand(ft, pd->cmd); |  | ||||||
| 	format_free(ft); |  | ||||||
|  |  | ||||||
| 	if (pd->item != NULL) |  | ||||||
| 		event = cmdq_get_event(pd->item); |  | ||||||
| 	else |  | ||||||
| 		event = NULL; |  | ||||||
| 	state = cmdq_new_state(&pd->fs, event, 0); |  | ||||||
|  |  | ||||||
| 	status = cmd_parse_and_append(cmd, NULL, c, state, &error); |  | ||||||
| 	if (status == CMD_PARSE_ERROR) { |  | ||||||
| 		cmdq_append(c, cmdq_get_error(error)); |  | ||||||
| 		free(error); |  | ||||||
| 	} |  | ||||||
| 	cmdq_free_state(state); |  | ||||||
|  |  | ||||||
| 	return (1); |  | ||||||
|  |  | ||||||
| out: | out: | ||||||
| 	pd->lx = m->x; | 	pd->lx = m->x; | ||||||
| @@ -416,62 +318,12 @@ popup_job_complete_cb(struct job *job) | |||||||
| 		server_client_clear_overlay(pd->c); | 		server_client_clear_overlay(pd->c); | ||||||
| } | } | ||||||
|  |  | ||||||
| u_int |  | ||||||
| popup_height(u_int nlines, const char **lines) |  | ||||||
| { |  | ||||||
| 	char	*copy, *next, *loop; |  | ||||||
| 	u_int	 i, height = 0; |  | ||||||
|  |  | ||||||
| 	for (i = 0; i < nlines; i++) { |  | ||||||
| 		copy = next = xstrdup(lines[i]); |  | ||||||
| 		while ((loop = strsep(&next, "\n")) != NULL) |  | ||||||
| 			height++; |  | ||||||
| 		free(copy); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return (height); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| u_int |  | ||||||
| popup_width(struct cmdq_item *item, u_int nlines, const char **lines, |  | ||||||
|     struct client *c, struct cmd_find_state *fs) |  | ||||||
| { |  | ||||||
| 	char			*copy, *next, *loop, *tmp; |  | ||||||
| 	struct format_tree	*ft; |  | ||||||
| 	u_int			 i, width = 0, tmpwidth; |  | ||||||
|  |  | ||||||
| 	ft = format_create(cmdq_get_client(item), item, FORMAT_NONE, 0); |  | ||||||
| 	if (fs != NULL && cmd_find_valid_state(fs)) |  | ||||||
| 		format_defaults(ft, c, fs->s, fs->wl, fs->wp); |  | ||||||
| 	else |  | ||||||
| 		format_defaults(ft, c, NULL, NULL, NULL); |  | ||||||
|  |  | ||||||
| 	for (i = 0; i < nlines; i++) { |  | ||||||
| 		copy = next = xstrdup(lines[i]); |  | ||||||
| 		while ((loop = strsep(&next, "\n")) != NULL) { |  | ||||||
| 			tmp = format_expand(ft, loop); |  | ||||||
| 			tmpwidth = format_width(tmp); |  | ||||||
| 			if (tmpwidth > width) |  | ||||||
| 				width = tmpwidth; |  | ||||||
| 			free(tmp); |  | ||||||
| 		} |  | ||||||
| 		free(copy); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	format_free(ft); |  | ||||||
| 	return (width); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| int | int | ||||||
| popup_display(int flags, struct cmdq_item *item, u_int px, u_int py, u_int sx, | popup_display(int flags, struct cmdq_item *item, u_int px, u_int py, u_int sx, | ||||||
|     u_int sy, u_int nlines, const char **lines, const char *shellcmd, |     u_int sy, const char *shellcmd, int argc, char **argv, const char *cwd, | ||||||
|     const char *cmd, const char *cwd, struct client *c, |     struct client *c, struct session *s, popup_close_cb cb, void *arg) | ||||||
|     struct cmd_find_state *fs, popup_close_cb cb, void *arg) |  | ||||||
| { | { | ||||||
| 	struct popup_data	*pd; | 	struct popup_data	*pd; | ||||||
| 	u_int			 i; |  | ||||||
| 	struct session		*s; |  | ||||||
| 	int			 jobflags; |  | ||||||
|  |  | ||||||
| 	if (sx < 3 || sy < 3) | 	if (sx < 3 || sy < 3) | ||||||
| 		return (-1); | 		return (-1); | ||||||
| @@ -489,39 +341,17 @@ popup_display(int flags, struct cmdq_item *item, u_int px, u_int py, u_int sx, | |||||||
| 	pd->arg = arg; | 	pd->arg = arg; | ||||||
| 	pd->status = 128 + SIGHUP; | 	pd->status = 128 + SIGHUP; | ||||||
|  |  | ||||||
| 	if (fs != NULL) |  | ||||||
| 		cmd_find_copy_state(&pd->fs, fs); |  | ||||||
| 	screen_init(&pd->s, sx - 2, sy - 2, 0); | 	screen_init(&pd->s, sx - 2, sy - 2, 0); | ||||||
|  |  | ||||||
| 	if (cmd != NULL) |  | ||||||
| 		pd->cmd = xstrdup(cmd); |  | ||||||
|  |  | ||||||
| 	pd->px = px; | 	pd->px = px; | ||||||
| 	pd->py = py; | 	pd->py = py; | ||||||
| 	pd->sx = sx; | 	pd->sx = sx; | ||||||
| 	pd->sy = sy; | 	pd->sy = sy; | ||||||
|  |  | ||||||
| 	pd->nlines = nlines; | 	pd->job = job_run(shellcmd, argc, argv, s, cwd, | ||||||
| 	if (pd->nlines != 0) | 	    popup_job_update_cb, popup_job_complete_cb, NULL, pd, | ||||||
| 		pd->lines = xreallocarray(NULL, pd->nlines, sizeof *pd->lines); | 	    JOB_NOWAIT|JOB_PTY|JOB_KEEPWRITE, pd->sx - 2, pd->sy - 2); | ||||||
|  | 	pd->ictx = input_init(NULL, job_get_event(pd->job)); | ||||||
| 	for (i = 0; i < pd->nlines; i++) |  | ||||||
| 		pd->lines[i] = xstrdup(lines[i]); |  | ||||||
| 	popup_write_screen(c, pd); |  | ||||||
|  |  | ||||||
| 	if (shellcmd != NULL) { |  | ||||||
| 		if (fs != NULL) |  | ||||||
| 			s = fs->s; |  | ||||||
| 		else |  | ||||||
| 			s = NULL; |  | ||||||
| 		jobflags = JOB_NOWAIT|JOB_PTY; |  | ||||||
| 		if (flags & POPUP_WRITEKEYS) |  | ||||||
| 		    jobflags |= JOB_KEEPWRITE; |  | ||||||
| 		pd->job = job_run(shellcmd, s, cwd, popup_job_update_cb, |  | ||||||
| 		    popup_job_complete_cb, NULL, pd, jobflags, pd->sx - 2, |  | ||||||
| 		    pd->sy - 2); |  | ||||||
| 		pd->ictx = input_init(NULL, job_get_event(pd->job)); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	server_client_set_overlay(c, 0, popup_check_cb, popup_mode_cb, | 	server_client_set_overlay(c, 0, popup_check_cb, popup_mode_cb, | ||||||
| 	    popup_draw_cb, popup_key_cb, popup_free_cb, pd); | 	    popup_draw_cb, popup_key_cb, popup_free_cb, pd); | ||||||
| @@ -607,9 +437,8 @@ popup_editor(struct client *c, const char *buf, size_t len, | |||||||
| 	py = (c->tty.sy / 2) - (sy / 2); | 	py = (c->tty.sy / 2) - (sy / 2); | ||||||
|  |  | ||||||
| 	xasprintf(&cmd, "%s %s", editor, path); | 	xasprintf(&cmd, "%s %s", editor, path); | ||||||
| 	if (popup_display(POPUP_WRITEKEYS|POPUP_CLOSEEXIT, NULL, px, py, sx, sy, | 	if (popup_display(POPUP_CLOSEEXIT, NULL, px, py, sx, sy, cmd, 0, NULL, | ||||||
| 	    0, NULL, cmd, NULL, _PATH_TMP, c, NULL, popup_editor_close_cb, | 	    _PATH_TMP, c, NULL, popup_editor_close_cb, pe) != 0) { | ||||||
| 	    pe) != 0) { |  | ||||||
| 		popup_editor_free(pe); | 		popup_editor_free(pe); | ||||||
| 		free(cmd); | 		free(cmd); | ||||||
| 		return (-1); | 		return (-1); | ||||||
|   | |||||||
							
								
								
									
										5
									
								
								spawn.c
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								spawn.c
									
									
									
									
									
								
							| @@ -265,8 +265,9 @@ spawn_pane(struct spawn_context *sc, char **cause) | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/* | 	/* | ||||||
| 	 * Now we have a pane with nothing running in it ready for the new process. | 	 * Now we have a pane with nothing running in it ready for the new | ||||||
| 	 * Work out the command and arguments and store the working directory. | 	 * process. Work out the command and arguments and store the working | ||||||
|  | 	 * directory. | ||||||
| 	 */ | 	 */ | ||||||
| 	if (sc->argc == 0 && (~sc->flags & SPAWN_RESPAWN)) { | 	if (sc->argc == 0 && (~sc->flags & SPAWN_RESPAWN)) { | ||||||
| 		cmd = options_get_string(s->options, "default-command"); | 		cmd = options_get_string(s->options, "default-command"); | ||||||
|   | |||||||
							
								
								
									
										61
									
								
								tmux.1
									
									
									
									
									
								
							
							
						
						
									
										61
									
								
								tmux.1
									
									
									
									
									
								
							| @@ -4923,9 +4923,6 @@ The following variables are available, where appropriate: | |||||||
| .It Li "pane_tty" Ta "" Ta "Pseudo terminal of pane" | .It Li "pane_tty" Ta "" Ta "Pseudo terminal of pane" | ||||||
| .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 "popup_key" Ta "" Ta "Key pressed in popup" |  | ||||||
| .It Li "popup_mouse_x" Ta "" Ta "Mouse X position in popup" |  | ||||||
| .It Li "popup_mouse_y" Ta "" Ta "Mouse Y position in popup" |  | ||||||
| .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_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" | ||||||
| @@ -5584,58 +5581,24 @@ lists the format variables and their values. | |||||||
| forwards any input read from stdin to the empty pane given by | forwards any input read from stdin to the empty pane given by | ||||||
| .Ar target-pane . | .Ar target-pane . | ||||||
| .It Xo Ic display-popup | .It Xo Ic display-popup | ||||||
| .Op Fl CEK | .Op Fl CE | ||||||
| .Op Fl c Ar target-client | .Op Fl c Ar target-client | ||||||
| .Op Fl d Ar start-directory | .Op Fl d Ar start-directory | ||||||
| .Op Fl h Ar height | .Op Fl h Ar height | ||||||
| .Op Fl R Ar shell-command |  | ||||||
| .Op Fl t Ar target-pane | .Op Fl t Ar target-pane | ||||||
| .Op Fl w Ar width | .Op Fl w Ar width | ||||||
| .Op Fl x Ar position | .Op Fl x Ar position | ||||||
| .Op Fl y Ar position | .Op Fl y Ar position | ||||||
| .Op Ar command Ar line Ar ... | .Op Ar shell-command | ||||||
| .Xc | .Xc | ||||||
| .D1 (alias: Ic popup ) | .D1 (alias: Ic popup ) | ||||||
| Display a popup on | Display a popup running | ||||||
|  | .Ar shell-command | ||||||
|  | on | ||||||
| .Ar target-client . | .Ar target-client . | ||||||
| A popup is a rectangular box drawn over the top of any panes. | A popup is a rectangular box drawn over the top of any panes. | ||||||
| Panes are not updated while a popup is present. | Panes are not updated while a popup is present. | ||||||
| The popup content may be given in two ways: |  | ||||||
| .Bl -enum -offset Ds |  | ||||||
| .It |  | ||||||
| A set of lines as arguments. |  | ||||||
| Each line is a format which is expanded using |  | ||||||
| .Ar target-pane |  | ||||||
| as the target. |  | ||||||
| If a line contains newlines it is split into multiple lines. |  | ||||||
| Lines may use styles, see the |  | ||||||
| .Sx STYLES |  | ||||||
| section. |  | ||||||
| .It |  | ||||||
| A shell command given by |  | ||||||
| .Fl R |  | ||||||
| which is run and any output shown in the pane. |  | ||||||
| .El |  | ||||||
| .Pp | .Pp | ||||||
| The first argument, |  | ||||||
| .Ar command , |  | ||||||
| is a |  | ||||||
| .Nm |  | ||||||
| command which is run when a key is pressed. |  | ||||||
| The key is available in the |  | ||||||
| .Ql popup_key |  | ||||||
| format. |  | ||||||
| After |  | ||||||
| .Ar command |  | ||||||
| is run, the popup is closed. |  | ||||||
| It may be empty to discard any key presses. |  | ||||||
| If |  | ||||||
| .Fl K |  | ||||||
| is given together with |  | ||||||
| .Fl R , |  | ||||||
| key presses are instead passed to the |  | ||||||
| .Fl R |  | ||||||
| shell command. |  | ||||||
| .Fl E | .Fl E | ||||||
| closes the popup automatically when | closes the popup automatically when | ||||||
| .Ar shell-command | .Ar shell-command | ||||||
| @@ -5645,14 +5608,6 @@ Two | |||||||
| closes the popup only if | closes the popup only if | ||||||
| .Ar shell-command | .Ar shell-command | ||||||
| exited with success. | exited with success. | ||||||
| With |  | ||||||
| .Fl K , |  | ||||||
| .Ql Escape |  | ||||||
| and |  | ||||||
| .Ql C-c |  | ||||||
| close the popup unless |  | ||||||
| .Fl E |  | ||||||
| is also given. |  | ||||||
| .Pp | .Pp | ||||||
| .Fl x | .Fl x | ||||||
| and | and | ||||||
| @@ -5665,11 +5620,7 @@ and | |||||||
| .Fl h | .Fl h | ||||||
| give the width and height - both may be a percentage (followed by | give the width and height - both may be a percentage (followed by | ||||||
| .Ql % ) . | .Ql % ) . | ||||||
| If omitted, without | If omitted, half of the terminal size is used. | ||||||
| .Fl R |  | ||||||
| they are calculated from the given lines and with |  | ||||||
| .Fl R |  | ||||||
| they use half the terminal size. |  | ||||||
| .Pp | .Pp | ||||||
| The | The | ||||||
| .Fl C | .Fl C | ||||||
|   | |||||||
							
								
								
									
										19
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								tmux.h
									
									
									
									
									
								
							| @@ -2067,9 +2067,9 @@ typedef void (*job_free_cb) (void *); | |||||||
| #define JOB_NOWAIT 0x1 | #define JOB_NOWAIT 0x1 | ||||||
| #define JOB_KEEPWRITE 0x2 | #define JOB_KEEPWRITE 0x2 | ||||||
| #define JOB_PTY 0x4 | #define JOB_PTY 0x4 | ||||||
| struct job	*job_run(const char *, struct session *, const char *, | struct job	*job_run(const char *, int, char **, struct session *, | ||||||
| 		     job_update_cb, job_complete_cb, job_free_cb, void *, int, | 		     const char *, job_update_cb, job_complete_cb, job_free_cb, | ||||||
| 		     int, int); | 		     void *, int, int, int); | ||||||
| void		 job_free(struct job *); | void		 job_free(struct job *); | ||||||
| void		 job_resize(struct job *, u_int, u_int); | void		 job_resize(struct job *, u_int, u_int); | ||||||
| void		 job_check_died(pid_t, int); | void		 job_check_died(pid_t, int); | ||||||
| @@ -3038,18 +3038,13 @@ int		 menu_display(struct menu *, int, struct cmdq_item *, u_int, | |||||||
| 		    menu_choice_cb, void *); | 		    menu_choice_cb, void *); | ||||||
|  |  | ||||||
| /* popup.c */ | /* popup.c */ | ||||||
| #define POPUP_WRITEKEYS 0x1 | #define POPUP_CLOSEEXIT 0x1 | ||||||
| #define POPUP_CLOSEEXIT 0x2 | #define POPUP_CLOSEEXITZERO 0x2 | ||||||
| #define POPUP_CLOSEEXITZERO 0x4 |  | ||||||
| typedef void (*popup_close_cb)(int, void *); | typedef void (*popup_close_cb)(int, void *); | ||||||
| typedef void (*popup_finish_edit_cb)(char *, size_t, void *); | typedef void (*popup_finish_edit_cb)(char *, size_t, void *); | ||||||
| u_int		 popup_width(struct cmdq_item *, u_int, const char **, |  | ||||||
| 		    struct client *, struct cmd_find_state *); |  | ||||||
| u_int		 popup_height(u_int, const char **); |  | ||||||
| int		 popup_display(int, struct cmdq_item *, u_int, u_int, u_int, | int		 popup_display(int, struct cmdq_item *, u_int, u_int, u_int, | ||||||
| 		    u_int, u_int, const char **, const char *, const char *, | 		    u_int, const char *, int, char **, const char *, | ||||||
| 		    const char *, struct client *, struct cmd_find_state *, | 		    struct client *, struct session *, popup_close_cb, void *); | ||||||
| 		    popup_close_cb, void *); |  | ||||||
| int		 popup_editor(struct client *, const char *, size_t, | int		 popup_editor(struct client *, const char *, size_t, | ||||||
| 		    popup_finish_edit_cb, void *); | 		    popup_finish_edit_cb, void *); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -3963,8 +3963,8 @@ window_copy_pipe_run(struct window_mode_entry *wme, struct session *s, | |||||||
| 	if (cmd == NULL || *cmd == '\0') | 	if (cmd == NULL || *cmd == '\0') | ||||||
| 		cmd = options_get_string(global_options, "copy-command"); | 		cmd = options_get_string(global_options, "copy-command"); | ||||||
| 	if (cmd != NULL && *cmd != '\0') { | 	if (cmd != NULL && *cmd != '\0') { | ||||||
| 		job = job_run(cmd, s, NULL, NULL, NULL, NULL, NULL, JOB_NOWAIT, | 		job = job_run(cmd, 0, NULL, s, NULL, NULL, NULL, NULL, NULL, | ||||||
| 		    -1, -1); | 		    JOB_NOWAIT, -1, -1); | ||||||
| 		bufferevent_write(job_get_event(job), buf, *len); | 		bufferevent_write(job_get_event(job), buf, *len); | ||||||
| 	} | 	} | ||||||
| 	return (buf); | 	return (buf); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 nicm
					nicm