mirror of
				https://github.com/tmux/tmux.git
				synced 2025-10-26 12:27:15 +00:00 
			
		
		
		
	Now that copy mode copies the pane content rather than keeping a
reference to it, it isn't necessary that the pane in copy mode is the same as the one copying from. Add a -s flag to copy-mode to specify a different pane for the source content. This means it is possible to view two places in a pane's history at the same time in different panes, or copy from a pane's history into an editor or shell in the same pane. From Anindya Mukherjee.
This commit is contained in:
		
							
								
								
									
										2
									
								
								cfg.c
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								cfg.c
									
									
									
									
									
								
							| @@ -284,7 +284,7 @@ cfg_show_causes(struct session *s) | |||||||
|  |  | ||||||
| 	wme = TAILQ_FIRST(&wp->modes); | 	wme = TAILQ_FIRST(&wp->modes); | ||||||
| 	if (wme == NULL || wme->mode != &window_view_mode) | 	if (wme == NULL || wme->mode != &window_view_mode) | ||||||
| 		window_pane_set_mode(wp, &window_view_mode, NULL, NULL); | 		window_pane_set_mode(wp, NULL, &window_view_mode, NULL, NULL); | ||||||
| 	for (i = 0; i < cfg_ncauses; i++) { | 	for (i = 0; i < cfg_ncauses; i++) { | ||||||
| 		window_copy_add(wp, "%s", cfg_causes[i]); | 		window_copy_add(wp, "%s", cfg_causes[i]); | ||||||
| 		free(cfg_causes[i]); | 		free(cfg_causes[i]); | ||||||
|   | |||||||
| @@ -86,6 +86,6 @@ cmd_choose_tree_exec(struct cmd *self, struct cmdq_item *item) | |||||||
| 	} else | 	} else | ||||||
| 		mode = &window_tree_mode; | 		mode = &window_tree_mode; | ||||||
|  |  | ||||||
| 	window_pane_set_mode(wp, mode, &item->target, args); | 	window_pane_set_mode(wp, NULL, mode, &item->target, args); | ||||||
| 	return (CMD_RETURN_NORMAL); | 	return (CMD_RETURN_NORMAL); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -30,9 +30,10 @@ const struct cmd_entry cmd_copy_mode_entry = { | |||||||
| 	.name = "copy-mode", | 	.name = "copy-mode", | ||||||
| 	.alias = NULL, | 	.alias = NULL, | ||||||
|  |  | ||||||
| 	.args = { "eHMt:uq", 0, 0 }, | 	.args = { "eHMs:t:uq", 0, 0 }, | ||||||
| 	.usage = "[-eHMuq] " CMD_TARGET_PANE_USAGE, | 	.usage = "[-eHMuq] [-s src-pane] " CMD_TARGET_PANE_USAGE, | ||||||
|  |  | ||||||
|  | 	.source =  { 's', CMD_FIND_PANE, 0 }, | ||||||
| 	.target = { 't', CMD_FIND_PANE, 0 }, | 	.target = { 't', CMD_FIND_PANE, 0 }, | ||||||
|  |  | ||||||
| 	.flags = CMD_AFTERHOOK, | 	.flags = CMD_AFTERHOOK, | ||||||
| @@ -59,7 +60,7 @@ cmd_copy_mode_exec(struct cmd *self, struct cmdq_item *item) | |||||||
| 	struct cmdq_shared	*shared = item->shared; | 	struct cmdq_shared	*shared = item->shared; | ||||||
| 	struct client		*c = item->client; | 	struct client		*c = item->client; | ||||||
| 	struct session		*s; | 	struct session		*s; | ||||||
| 	struct window_pane	*wp = item->target.wp; | 	struct window_pane	*wp = item->target.wp, *swp; | ||||||
|  |  | ||||||
| 	if (args_has(args, 'q')) { | 	if (args_has(args, 'q')) { | ||||||
| 		window_pane_reset_mode_all(wp); | 		window_pane_reset_mode_all(wp); | ||||||
| @@ -74,11 +75,15 @@ cmd_copy_mode_exec(struct cmd *self, struct cmdq_item *item) | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (self->entry == &cmd_clock_mode_entry) { | 	if (self->entry == &cmd_clock_mode_entry) { | ||||||
| 		window_pane_set_mode(wp, &window_clock_mode, NULL, NULL); | 		window_pane_set_mode(wp, NULL, &window_clock_mode, NULL, NULL); | ||||||
| 		return (CMD_RETURN_NORMAL); | 		return (CMD_RETURN_NORMAL); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (!window_pane_set_mode(wp, &window_copy_mode, NULL, args)) { | 	if (args_has(args, 's')) | ||||||
|  | 		swp = item->source.wp; | ||||||
|  | 	else | ||||||
|  | 		swp = wp; | ||||||
|  | 	if (!window_pane_set_mode(wp, swp, &window_copy_mode, NULL, args)) { | ||||||
| 		if (args_has(args, 'M')) | 		if (args_has(args, 'M')) | ||||||
| 			window_copy_start_drag(c, &shared->mouse); | 			window_copy_start_drag(c, &shared->mouse); | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -116,7 +116,8 @@ cmd_find_window_exec(struct cmd *self, struct cmdq_item *item) | |||||||
| 		args_set(new_args, 'Z', NULL); | 		args_set(new_args, 'Z', NULL); | ||||||
| 	args_set(new_args, 'f', filter); | 	args_set(new_args, 'f', filter); | ||||||
|  |  | ||||||
| 	window_pane_set_mode(wp, &window_tree_mode, &item->target, new_args); | 	window_pane_set_mode(wp, NULL, &window_tree_mode, &item->target, | ||||||
|  | 	    new_args); | ||||||
|  |  | ||||||
| 	args_free(new_args); | 	args_free(new_args); | ||||||
| 	free(filter); | 	free(filter); | ||||||
|   | |||||||
| @@ -511,8 +511,10 @@ cmdq_print(struct cmdq_item *item, const char *fmt, ...) | |||||||
| 	} else { | 	} else { | ||||||
| 		wp = c->session->curw->window->active; | 		wp = c->session->curw->window->active; | ||||||
| 		wme = TAILQ_FIRST(&wp->modes); | 		wme = TAILQ_FIRST(&wp->modes); | ||||||
| 		if (wme == NULL || wme->mode != &window_view_mode) | 		if (wme == NULL || wme->mode != &window_view_mode) { | ||||||
| 			window_pane_set_mode(wp, &window_view_mode, NULL, NULL); | 			window_pane_set_mode(wp, NULL, &window_view_mode, NULL, | ||||||
|  | 			    NULL); | ||||||
|  | 		} | ||||||
| 		window_copy_add(wp, "%s", msg); | 		window_copy_add(wp, "%s", msg); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -82,7 +82,7 @@ cmd_run_shell_print(struct job *job, const char *msg) | |||||||
|  |  | ||||||
| 	wme = TAILQ_FIRST(&wp->modes); | 	wme = TAILQ_FIRST(&wp->modes); | ||||||
| 	if (wme == NULL || wme->mode != &window_view_mode) | 	if (wme == NULL || wme->mode != &window_view_mode) | ||||||
| 		window_pane_set_mode(wp, &window_view_mode, NULL, NULL); | 		window_pane_set_mode(wp, NULL, &window_view_mode, NULL, NULL); | ||||||
| 	window_copy_add(wp, "%s", msg); | 	window_copy_add(wp, "%s", msg); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										6
									
								
								tmux.1
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								tmux.1
									
									
									
									
									
								
							| @@ -1608,6 +1608,7 @@ command is: | |||||||
| .Bl -tag -width Ds | .Bl -tag -width Ds | ||||||
| .It Xo Ic copy-mode | .It Xo Ic copy-mode | ||||||
| .Op Fl eHMqu | .Op Fl eHMqu | ||||||
|  | .Op Fl s Ar src-pane | ||||||
| .Op Fl t Ar target-pane | .Op Fl t Ar target-pane | ||||||
| .Xc | .Xc | ||||||
| Enter copy mode. | Enter copy mode. | ||||||
| @@ -1621,6 +1622,11 @@ begins a mouse drag (only valid if bound to a mouse key binding, see | |||||||
| hides the position indicator in the top right. | hides the position indicator in the top right. | ||||||
| .Fl q | .Fl q | ||||||
| cancels copy mode and any other modes. | cancels copy mode and any other modes. | ||||||
|  | .Fl s | ||||||
|  | copies from | ||||||
|  | .Ar src-pane | ||||||
|  | instead of | ||||||
|  | .Ar target-pane. | ||||||
| .Pp | .Pp | ||||||
| .Fl e | .Fl e | ||||||
| specifies that scrolling to the bottom of the history (to the visible screen) | specifies that scrolling to the bottom of the history (to the visible screen) | ||||||
|   | |||||||
							
								
								
									
										5
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								tmux.h
									
									
									
									
									
								
							| @@ -848,6 +848,7 @@ struct window_mode { | |||||||
| /* Active window mode. */ | /* Active window mode. */ | ||||||
| struct window_mode_entry { | struct window_mode_entry { | ||||||
| 	struct window_pane		*wp; | 	struct window_pane		*wp; | ||||||
|  | 	struct window_pane		*swp; | ||||||
|  |  | ||||||
| 	const struct window_mode	*mode; | 	const struct window_mode	*mode; | ||||||
| 	void				*data; | 	void				*data; | ||||||
| @@ -2537,8 +2538,8 @@ void		 window_pane_unset_palette(struct window_pane *, u_int); | |||||||
| void		 window_pane_reset_palette(struct window_pane *); | void		 window_pane_reset_palette(struct window_pane *); | ||||||
| int		 window_pane_get_palette(struct window_pane *, int); | int		 window_pane_get_palette(struct window_pane *, int); | ||||||
| int		 window_pane_set_mode(struct window_pane *, | int		 window_pane_set_mode(struct window_pane *, | ||||||
| 		     const struct window_mode *, struct cmd_find_state *, | 		     struct window_pane *, const struct window_mode *, | ||||||
| 		     struct args *); | 		     struct cmd_find_state *, struct args *); | ||||||
| void		 window_pane_reset_mode(struct window_pane *); | void		 window_pane_reset_mode(struct window_pane *); | ||||||
| void		 window_pane_reset_mode_all(struct window_pane *); | void		 window_pane_reset_mode_all(struct window_pane *); | ||||||
| int		 window_pane_key(struct window_pane *, struct client *, | int		 window_pane_key(struct window_pane *, struct client *, | ||||||
|   | |||||||
| @@ -130,7 +130,7 @@ static void	window_copy_rectangle_toggle(struct window_mode_entry *); | |||||||
| static void	window_copy_move_mouse(struct mouse_event *); | static void	window_copy_move_mouse(struct mouse_event *); | ||||||
| static void	window_copy_drag_update(struct client *, struct mouse_event *); | static void	window_copy_drag_update(struct client *, struct mouse_event *); | ||||||
| static void	window_copy_drag_release(struct client *, struct mouse_event *); | static void	window_copy_drag_release(struct client *, struct mouse_event *); | ||||||
| static struct screen* window_copy_clone_screen(struct screen *src); | static struct screen* window_copy_clone_screen(struct screen *, struct screen*); | ||||||
|  |  | ||||||
| const struct window_mode window_copy_mode = { | const struct window_mode window_copy_mode = { | ||||||
| 	.name = "copy-mode", | 	.name = "copy-mode", | ||||||
| @@ -299,21 +299,29 @@ window_copy_scroll_timer(__unused int fd, __unused short events, void *arg) | |||||||
| } | } | ||||||
|  |  | ||||||
| static struct screen * | static struct screen * | ||||||
| window_copy_clone_screen(struct screen *src) | window_copy_clone_screen(struct screen *src, struct screen *hint) | ||||||
| { | { | ||||||
| 	struct screen			*dst; | 	struct screen			*dst; | ||||||
| 	struct screen_write_ctx		 ctx; | 	struct screen_write_ctx		 ctx; | ||||||
|  | 	u_int				 dy, sy; | ||||||
|  |  | ||||||
| 	dst = xcalloc(1, sizeof *dst); | 	dst = xcalloc(1, sizeof *dst); | ||||||
| 	screen_init(dst, screen_size_x(src), |  | ||||||
| 	    screen_hsize(src) + screen_size_y(src), src->grid->hlimit); | 	sy = screen_hsize(src) + screen_size_y(src); | ||||||
| 	grid_duplicate_lines(dst->grid, 0, src->grid, 0, | 	if (screen_size_y(hint) > sy) | ||||||
| 	    screen_hsize(src) + screen_size_y(src)); | 		dy = screen_size_y(hint); | ||||||
| 	dst->grid->sy = screen_size_y(src); | 	else | ||||||
| 	dst->grid->hsize = screen_hsize(src); | 		dy = sy; | ||||||
|  | 	screen_init(dst, screen_size_x(src), dy, src->grid->hlimit); | ||||||
|  |  | ||||||
|  | 	grid_duplicate_lines(dst->grid, 0, src->grid, 0, sy); | ||||||
|  | 	if (screen_size_y(hint) < sy) { | ||||||
|  | 		dst->grid->sy = screen_size_y(hint); | ||||||
|  | 		dst->grid->hsize = sy - screen_size_y(hint); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	screen_write_start(&ctx, NULL, dst); | 	screen_write_start(&ctx, NULL, dst); | ||||||
| 	screen_write_cursormove(&ctx, src->cx, src->cy, 0); | 	screen_write_cursormove(&ctx, 0, dst->grid->sy - 1, 0); | ||||||
| 	screen_write_stop(&ctx); | 	screen_write_stop(&ctx); | ||||||
|  |  | ||||||
| 	return (dst); | 	return (dst); | ||||||
| @@ -361,14 +369,14 @@ static struct screen * | |||||||
| window_copy_init(struct window_mode_entry *wme, | window_copy_init(struct window_mode_entry *wme, | ||||||
|     __unused struct cmd_find_state *fs, struct args *args) |     __unused struct cmd_find_state *fs, struct args *args) | ||||||
| { | { | ||||||
| 	struct window_pane		*wp = wme->wp; | 	struct window_pane		*wp = wme->swp; | ||||||
| 	struct window_copy_mode_data	*data; | 	struct window_copy_mode_data	*data; | ||||||
| 	struct screen_write_ctx		 ctx; | 	struct screen_write_ctx		 ctx; | ||||||
| 	u_int				 i; | 	u_int				 i; | ||||||
|  |  | ||||||
| 	data = window_copy_common_init(wme); | 	data = window_copy_common_init(wme); | ||||||
|  |  | ||||||
| 	data->backing = window_copy_clone_screen(&wp->base); | 	data->backing = window_copy_clone_screen(&wp->base, &data->screen); | ||||||
| 	data->cx = data->backing->cx; | 	data->cx = data->backing->cx; | ||||||
| 	data->cy = data->backing->cy; | 	data->cy = data->backing->cy; | ||||||
|  |  | ||||||
| @@ -2001,7 +2009,7 @@ static enum window_copy_cmd_action | |||||||
| window_copy_cmd_refresh_from_pane(struct window_copy_cmd_state *cs) | window_copy_cmd_refresh_from_pane(struct window_copy_cmd_state *cs) | ||||||
| { | { | ||||||
| 	struct window_mode_entry	*wme = cs->wme; | 	struct window_mode_entry	*wme = cs->wme; | ||||||
| 	struct window_pane		*wp = wme->wp; | 	struct window_pane		*wp = wme->swp; | ||||||
| 	struct window_copy_mode_data	*data = wme->data; | 	struct window_copy_mode_data	*data = wme->data; | ||||||
|  |  | ||||||
| 	if (data->viewmode) | 	if (data->viewmode) | ||||||
| @@ -2009,7 +2017,7 @@ window_copy_cmd_refresh_from_pane(struct window_copy_cmd_state *cs) | |||||||
|  |  | ||||||
| 	screen_free(data->backing); | 	screen_free(data->backing); | ||||||
| 	free(data->backing); | 	free(data->backing); | ||||||
| 	data->backing = window_copy_clone_screen(&wp->base); | 	data->backing = window_copy_clone_screen(&wp->base, &data->screen); | ||||||
|  |  | ||||||
| 	return (WINDOW_COPY_CMD_REDRAW); | 	return (WINDOW_COPY_CMD_REDRAW); | ||||||
| } | } | ||||||
| @@ -2964,6 +2972,7 @@ window_copy_write_line(struct window_mode_entry *wme, | |||||||
| 	struct grid_cell		 gc; | 	struct grid_cell		 gc; | ||||||
| 	char				 hdr[512]; | 	char				 hdr[512]; | ||||||
| 	size_t				 size = 0; | 	size_t				 size = 0; | ||||||
|  | 	u_int				 hsize = screen_hsize(data->backing); | ||||||
|  |  | ||||||
| 	style_apply(&gc, oo, "mode-style"); | 	style_apply(&gc, oo, "mode-style"); | ||||||
| 	gc.flags |= GRID_FLAG_NOPALETTE; | 	gc.flags |= GRID_FLAG_NOPALETTE; | ||||||
| @@ -2972,23 +2981,20 @@ window_copy_write_line(struct window_mode_entry *wme, | |||||||
| 		if (data->searchmark == NULL) { | 		if (data->searchmark == NULL) { | ||||||
| 			if (data->timeout) { | 			if (data->timeout) { | ||||||
| 				size = xsnprintf(hdr, sizeof hdr, | 				size = xsnprintf(hdr, sizeof hdr, | ||||||
| 			    		"(timed out) [%u/%u]", data->oy, | 				    "(timed out) [%u/%u]", data->oy, hsize); | ||||||
| 					screen_hsize(data->backing)); |  | ||||||
| 			} else { | 			} else { | ||||||
| 				size = xsnprintf(hdr, sizeof hdr, | 				size = xsnprintf(hdr, sizeof hdr, | ||||||
| 					"[%u/%u]", data->oy, | 				    "[%u/%u]", data->oy, hsize); | ||||||
| 					screen_hsize(data->backing)); |  | ||||||
| 			} | 			} | ||||||
| 		} else { | 		} else { | ||||||
| 			if (data->searchthis == -1) { | 			if (data->searchthis == -1) { | ||||||
| 				size = xsnprintf(hdr, sizeof hdr, | 				size = xsnprintf(hdr, sizeof hdr, | ||||||
| 				    "(%u results) [%d/%u]", data->searchcount, | 				    "(%u results) [%d/%u]", data->searchcount, | ||||||
| 				    data->oy, screen_hsize(data->backing)); | 				    data->oy, hsize); | ||||||
| 			} else { | 			} else { | ||||||
| 				size = xsnprintf(hdr, sizeof hdr, | 				size = xsnprintf(hdr, sizeof hdr, | ||||||
| 				    "(%u/%u results) [%d/%u]", data->searchthis, | 				    "(%u/%u results) [%d/%u]", data->searchthis, | ||||||
| 				    data->searchcount, data->oy, | 				    data->searchcount, data->oy, hsize); | ||||||
| 				    screen_hsize(data->backing)); |  | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		if (size > screen_size_x(s)) | 		if (size > screen_size_x(s)) | ||||||
| @@ -3000,8 +3006,7 @@ window_copy_write_line(struct window_mode_entry *wme, | |||||||
|  |  | ||||||
| 	if (size < screen_size_x(s)) { | 	if (size < screen_size_x(s)) { | ||||||
| 		screen_write_cursormove(ctx, 0, py, 0); | 		screen_write_cursormove(ctx, 0, py, 0); | ||||||
| 		screen_write_copy(ctx, data->backing, 0, | 		screen_write_copy(ctx, data->backing, 0, hsize - data->oy + py, | ||||||
| 		    (screen_hsize(data->backing) - data->oy) + py, |  | ||||||
| 		    screen_size_x(s) - size, 1, data->searchmark, &gc); | 		    screen_size_x(s) - size, 1, data->searchmark, &gc); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										6
									
								
								window.c
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								window.c
									
									
									
									
									
								
							| @@ -1067,8 +1067,9 @@ window_pane_get_palette(struct window_pane *wp, int c) | |||||||
| } | } | ||||||
|  |  | ||||||
| int | int | ||||||
| window_pane_set_mode(struct window_pane *wp, const struct window_mode *mode, | window_pane_set_mode(struct window_pane *wp, struct window_pane *swp, | ||||||
|     struct cmd_find_state *fs, struct args *args) |     const struct window_mode *mode, struct cmd_find_state *fs, | ||||||
|  |     struct args *args) | ||||||
| { | { | ||||||
| 	struct window_mode_entry	*wme; | 	struct window_mode_entry	*wme; | ||||||
|  |  | ||||||
| @@ -1085,6 +1086,7 @@ window_pane_set_mode(struct window_pane *wp, const struct window_mode *mode, | |||||||
| 	} else { | 	} else { | ||||||
| 		wme = xcalloc(1, sizeof *wme); | 		wme = xcalloc(1, sizeof *wme); | ||||||
| 		wme->wp = wp; | 		wme->wp = wp; | ||||||
|  | 		wme->swp = swp; | ||||||
| 		wme->mode = mode; | 		wme->mode = mode; | ||||||
| 		wme->prefix = 1; | 		wme->prefix = 1; | ||||||
| 		TAILQ_INSERT_HEAD(&wp->modes, wme, entry); | 		TAILQ_INSERT_HEAD(&wp->modes, wme, entry); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 nicm
					nicm