mirror of
				https://github.com/tmux/tmux.git
				synced 2025-10-26 12:27:15 +00:00 
			
		
		
		
	Add a choose-buffer command for easier use of the paste buffer stack.
This commit is contained in:
		
							
								
								
									
										2
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Makefile
									
									
									
									
									
								
							| @@ -6,7 +6,7 @@ SRCS=	attributes.c cfg.c client.c clock.c \ | ||||
| 	cmd-break-pane.c cmd-choose-session.c cmd-choose-window.c \ | ||||
| 	cmd-clear-history.c cmd-clock-mode.c cmd-command-prompt.c \ | ||||
| 	cmd-confirm-before.c cmd-copy-buffer.c cmd-copy-mode.c \ | ||||
| 	cmd-delete-buffer.c cmd-detach-client.c \ | ||||
| 	cmd-choose-buffer.c cmd-delete-buffer.c cmd-detach-client.c \ | ||||
| 	cmd-find-window.c cmd-generic.c cmd-has-session.c cmd-kill-pane.c \ | ||||
| 	cmd-kill-server.c cmd-kill-session.c cmd-kill-window.c \ | ||||
| 	cmd-last-window.c cmd-link-window.c cmd-list-buffers.c \ | ||||
|   | ||||
							
								
								
									
										146
									
								
								cmd-choose-buffer.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										146
									
								
								cmd-choose-buffer.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,146 @@ | ||||
| /* $OpenBSD$ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2010 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
|  * | ||||
|  * 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 <ctype.h> | ||||
|  | ||||
| #include "tmux.h" | ||||
|  | ||||
| /* | ||||
|  * Enter choice mode to choose a buffer. | ||||
|  */ | ||||
|  | ||||
| int	cmd_choose_buffer_exec(struct cmd *, struct cmd_ctx *); | ||||
|  | ||||
| void	cmd_choose_buffer_callback(void *, int); | ||||
| void	cmd_choose_buffer_free(void *); | ||||
|  | ||||
| const struct cmd_entry cmd_choose_buffer_entry = { | ||||
| 	"choose-buffer", NULL, | ||||
| 	CMD_TARGET_WINDOW_USAGE " [template]", | ||||
| 	CMD_ARG01, "", | ||||
| 	cmd_target_init, | ||||
| 	cmd_target_parse, | ||||
| 	cmd_choose_buffer_exec, | ||||
| 	cmd_target_free, | ||||
| 	cmd_target_print | ||||
| }; | ||||
|  | ||||
| struct cmd_choose_buffer_data { | ||||
| 	struct client	*client; | ||||
| 	char   		*template; | ||||
| }; | ||||
|  | ||||
| int | ||||
| cmd_choose_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) | ||||
| { | ||||
| 	struct cmd_target_data		*data = self->data; | ||||
| 	struct cmd_choose_buffer_data	*cdata; | ||||
| 	struct session			*s; | ||||
| 	struct winlink			*wl; | ||||
| 	struct paste_buffer		*pb; | ||||
| 	u_int				 idx; | ||||
| 	char				*tmp; | ||||
|  | ||||
| 	if (ctx->curclient == NULL) { | ||||
| 		ctx->error(ctx, "must be run interactively"); | ||||
| 		return (-1); | ||||
| 	} | ||||
| 	s = ctx->curclient->session; | ||||
|  | ||||
| 	if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) | ||||
| 		return (-1); | ||||
|  | ||||
| 	if (paste_get_top(&s->buffers) == NULL) | ||||
| 		return (0); | ||||
|  | ||||
| 	if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0) | ||||
| 		return (0); | ||||
|  | ||||
| 	idx = 0; | ||||
| 	while ((pb = paste_walk_stack(&s->buffers, &idx)) != NULL) { | ||||
| 		tmp = paste_print(pb, 50); | ||||
| 		window_choose_add(wl->window->active, idx - 1, | ||||
| 		    "%u: %zu bytes: \"%s\"", idx - 1, pb->size, tmp); | ||||
| 		xfree(tmp); | ||||
| 	} | ||||
|  | ||||
| 	cdata = xmalloc(sizeof *cdata); | ||||
| 	if (data->arg != NULL) | ||||
| 		cdata->template = xstrdup(data->arg); | ||||
| 	else | ||||
| 		cdata->template = xstrdup("paste-buffer -b '%%'"); | ||||
| 	cdata->client = ctx->curclient; | ||||
| 	cdata->client->references++; | ||||
|  | ||||
| 	window_choose_ready(wl->window->active, | ||||
| 	    0, cmd_choose_buffer_callback, cmd_choose_buffer_free, cdata); | ||||
|  | ||||
| 	return (0); | ||||
| } | ||||
|  | ||||
| void | ||||
| cmd_choose_buffer_callback(void *data, int idx) | ||||
| { | ||||
| 	struct cmd_choose_buffer_data	*cdata = data; | ||||
| 	struct cmd_list			*cmdlist; | ||||
| 	struct cmd_ctx			 ctx; | ||||
| 	char				*template, *cause, tmp[16]; | ||||
|  | ||||
| 	if (idx == -1) | ||||
| 		return; | ||||
| 	if (cdata->client->flags & CLIENT_DEAD) | ||||
| 		return; | ||||
|  | ||||
| 	xsnprintf(tmp, sizeof tmp, "%u", idx); | ||||
| 	template = cmd_template_replace(cdata->template, tmp, 1); | ||||
|  | ||||
| 	if (cmd_string_parse(template, &cmdlist, &cause) != 0) { | ||||
| 		if (cause != NULL) { | ||||
| 			*cause = toupper((u_char) *cause); | ||||
| 			status_message_set(cdata->client, "%s", cause); | ||||
| 			xfree(cause); | ||||
| 		} | ||||
| 		xfree(template); | ||||
| 		return; | ||||
| 	} | ||||
| 	xfree(template); | ||||
|  | ||||
| 	ctx.msgdata = NULL; | ||||
| 	ctx.curclient = cdata->client; | ||||
|  | ||||
| 	ctx.error = key_bindings_error; | ||||
| 	ctx.print = key_bindings_print; | ||||
| 	ctx.info = key_bindings_info; | ||||
|  | ||||
| 	ctx.cmdclient = NULL; | ||||
|  | ||||
| 	cmd_list_exec(cmdlist, &ctx); | ||||
| 	cmd_list_free(cmdlist); | ||||
| } | ||||
|  | ||||
| void | ||||
| cmd_choose_buffer_free(void *data) | ||||
| { | ||||
| 	struct cmd_choose_buffer_data	*cdata = data; | ||||
|  | ||||
| 	cdata->client->references--; | ||||
| 	xfree(cdata->template); | ||||
| 	xfree(cdata); | ||||
| } | ||||
| @@ -19,7 +19,6 @@ | ||||
| #include <sys/types.h> | ||||
|  | ||||
| #include <string.h> | ||||
| #include <vis.h> | ||||
|  | ||||
| #include "tmux.h" | ||||
|  | ||||
| @@ -47,32 +46,17 @@ cmd_list_buffers_exec(struct cmd *self, struct cmd_ctx *ctx) | ||||
| 	struct session		*s; | ||||
| 	struct paste_buffer	*pb; | ||||
| 	u_int			 idx; | ||||
| 	char			 tmp[51 * 4 + 1]; | ||||
| 	size_t			 size, len; | ||||
| 	char			*tmp; | ||||
|  | ||||
| 	if ((s = cmd_find_session(ctx, data->target)) == NULL) | ||||
| 		return (-1); | ||||
|  | ||||
| 	idx = 0; | ||||
| 	while ((pb = paste_walk_stack(&s->buffers, &idx)) != NULL) { | ||||
| 		size = pb->size; | ||||
|  | ||||
| 		/* Translate the first 50 characters. */ | ||||
| 		len = size; | ||||
| 		if (len > 50) | ||||
| 			len = 50; | ||||
| 		strvisx(tmp, pb->data, len, VIS_OCTAL|VIS_TAB|VIS_NL); | ||||
|  | ||||
| 		/* | ||||
| 		 * If the first 50 characters were encoded as a longer string, | ||||
| 		 * or there is definitely more data, add "...". | ||||
| 		 */ | ||||
| 		if (size > 50 || strlen(tmp) > 50) { | ||||
| 			tmp[50 - 3] = '\0'; | ||||
| 			strlcat(tmp, "...", sizeof tmp); | ||||
| 		} | ||||
|  | ||||
| 		ctx->print(ctx, "%u: %zu bytes: \"%s\"", idx - 1, size, tmp); | ||||
| 		tmp = paste_print(pb, 50); | ||||
| 		ctx->print(ctx, | ||||
| 		    "%u: %zu bytes: \"%s\"", idx - 1, pb->size, tmp); | ||||
| 		xfree(tmp); | ||||
| 	} | ||||
|  | ||||
| 	return (0); | ||||
|   | ||||
							
								
								
									
										1
									
								
								cmd.c
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								cmd.c
									
									
									
									
									
								
							| @@ -32,6 +32,7 @@ const struct cmd_entry *cmd_table[] = { | ||||
| 	&cmd_bind_key_entry, | ||||
| 	&cmd_break_pane_entry, | ||||
| 	&cmd_capture_pane_entry, | ||||
| 	&cmd_choose_buffer_entry, | ||||
| 	&cmd_choose_client_entry, | ||||
| 	&cmd_choose_session_entry, | ||||
| 	&cmd_choose_window_entry, | ||||
|   | ||||
| @@ -122,6 +122,7 @@ key_bindings_init(void) | ||||
| 		{ '8', 			  0, &cmd_select_window_entry }, | ||||
| 		{ '9', 			  0, &cmd_select_window_entry }, | ||||
| 		{ ':', 			  0, &cmd_command_prompt_entry }, | ||||
| 		{ '=', 			  0, &cmd_choose_buffer_entry }, | ||||
| 		{ '?', 			  0, &cmd_list_keys_entry }, | ||||
| 		{ 'D',			  0, &cmd_choose_client_entry }, | ||||
| 		{ '[', 			  0, &cmd_copy_mode_entry }, | ||||
|   | ||||
							
								
								
									
										25
									
								
								paste.c
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								paste.c
									
									
									
									
									
								
							| @@ -20,6 +20,7 @@ | ||||
| #include <sys/time.h> | ||||
|  | ||||
| #include <string.h> | ||||
| #include <vis.h> | ||||
|  | ||||
| #include "tmux.h" | ||||
|  | ||||
| @@ -156,3 +157,27 @@ paste_replace(struct paste_stack *ps, u_int idx, char *data, size_t size) | ||||
|  | ||||
| 	return (0); | ||||
| } | ||||
|  | ||||
| /* Convert a buffer into a visible string. */ | ||||
| char * | ||||
| paste_print(struct paste_buffer *pb, size_t width) | ||||
| { | ||||
| 	char	*buf; | ||||
| 	size_t	 len, used; | ||||
|  | ||||
| 	if (width < 3) | ||||
| 		width = 3; | ||||
| 	buf = xmalloc(width * 4 + 1); | ||||
|  | ||||
| 	len = pb->size; | ||||
| 	if (len > width) | ||||
| 		len = width; | ||||
|  | ||||
| 	used = strvisx(buf, pb->data, len, VIS_OCTAL|VIS_TAB|VIS_NL); | ||||
| 	if (pb->size > width || used > width) { | ||||
| 		buf[width - 3] = '\0'; | ||||
| 		strlcat(buf, "...", width); | ||||
| 	} | ||||
|  | ||||
| 	return (buf); | ||||
| } | ||||
|   | ||||
							
								
								
									
										19
									
								
								tmux.1
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								tmux.1
									
									
									
									
									
								
							| @@ -248,6 +248,8 @@ Select windows 0 to 9. | ||||
| Enter the | ||||
| .Nm | ||||
| command prompt. | ||||
| .It = | ||||
| Choose which buffer to paste interactively from a list. | ||||
| .It \&? | ||||
| List all key bindings. | ||||
| .It D | ||||
| @@ -2447,6 +2449,23 @@ command above). | ||||
| .Pp | ||||
| The buffer commands are as follows: | ||||
| .Bl -tag -width Ds | ||||
| .It Xo | ||||
| .Ic choose-buffer | ||||
| .Op Fl t Ar target-window | ||||
| .Op Ar template | ||||
| .Xc | ||||
| Put a window into buffer choice mode, where a buffer may be chosen | ||||
| interactively from a list. | ||||
| After a buffer is selected, | ||||
| .Ql %% | ||||
| is replaced by the buffer index in | ||||
| .Ar template | ||||
| and the result executed as a command. | ||||
| If | ||||
| .Ar template | ||||
| is not given, "paste-buffer -b '%%'" is used. | ||||
| This command works only from inside | ||||
| .Nm . | ||||
| .It Ic clear-history Op Fl t Ar target-pane | ||||
| .D1 (alias: Ic clearhist ) | ||||
| Remove and free the history for the specified pane. | ||||
|   | ||||
							
								
								
									
										2
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								tmux.h
									
									
									
									
									
								
							| @@ -1406,6 +1406,7 @@ int		 paste_free_top(struct paste_stack *); | ||||
| int		 paste_free_index(struct paste_stack *, u_int); | ||||
| void		 paste_add(struct paste_stack *, char *, size_t, u_int); | ||||
| int		 paste_replace(struct paste_stack *, u_int, char *, size_t); | ||||
| char		*paste_print(struct paste_buffer *, size_t); | ||||
|  | ||||
| /* clock.c */ | ||||
| extern const char clock_table[14][5][5]; | ||||
| @@ -1442,6 +1443,7 @@ extern const struct cmd_entry cmd_attach_session_entry; | ||||
| extern const struct cmd_entry cmd_bind_key_entry; | ||||
| extern const struct cmd_entry cmd_break_pane_entry; | ||||
| extern const struct cmd_entry cmd_capture_pane_entry; | ||||
| extern const struct cmd_entry cmd_choose_buffer_entry; | ||||
| extern const struct cmd_entry cmd_choose_client_entry; | ||||
| extern const struct cmd_entry cmd_choose_session_entry; | ||||
| extern const struct cmd_entry cmd_choose_window_entry; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Nicholas Marriott
					Nicholas Marriott