I've attached a patch which implements named buffers. Commands that take a buffer arg, like save-buffer and paste-buffer, have been modified so that -b can take a number or a name. So, you can do "setb -b myBuf someData".
buffer-limit applies to both the paste stack and the named buffers. So if buffer-limit is set to 20, you can have 20 items in the paste stack, and 20 named buffer items. Named buffers have to be explicitly deleted. If you try to add a new named buffer and you're at the buffer limit, it will fail to add a new named buffer. This is unlike the paste stack which removes the oldest item. When in copy mode, pressing the double-quote character allows you to enter a buffer name. Once you've made a selection, typing "myBuf and then hitting Enter will save your selection to the buffer named myBuf. You can hit Ctrl-a instead of Enter to append. Both of these key bindings are only set by default in vi mode. list-buffer and choose-buffer display the items in the paste stack first, and then the named buffers, which are sorted alphabetically. I added the ability to do prefix-P to more quickly enter a buffer name (or number) for pasting.
diff --git a/cmd-capture-pane.c b/cmd-capture-pane.c index e157e3c..d801daa 100644 --- a/cmd-capture-pane.c +++ b/cmd-capture-pane.c @@ -164,7 +164,7 @@ cmd_capture_pane_exec(struct cmd *self, struct cmd_q *cmdq) struct args *args = self->args; struct client *c; struct window_pane *wp; - char *buf, *cause; + char *buf, *cause, *bufname; int buffer; u_int limit; size_t len; @@ -200,13 +200,17 @@ cmd_capture_pane_exec(struct cmd *self, struct cmd_q *cmdq) buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause); if (cause != NULL) { - cmdq_error(cmdq, "buffer %s", cause); - free(buf); free(cause); - return (CMD_RETURN_ERROR); - } - - if (paste_replace(&global_buffers, buffer, buf, len) != 0) { + bufname = xstrdup(args_get(args, 'b')); + if (paste_set_named_buffer(&named_buffers, + buf, len, limit, bufname, &cause) != 0) { + cmdq_error(cmdq, "%s", cause); + free(buf); + free(cause); + free(bufname); + return (CMD_RETURN_ERROR); + } + } else if (paste_replace(&global_buffers, buffer, buf, len) != 0) { cmdq_error(cmdq, "no buffer %d", buffer); free(buf); return (CMD_RETURN_ERROR); diff --git a/cmd-choose-buffer.c b/cmd-choose-buffer.c index d79f6fd..a96fae1 100644 --- a/cmd-choose-buffer.c +++ b/cmd-choose-buffer.c @@ -87,6 +87,22 @@ cmd_choose_buffer_exec(struct cmd *self, struct cmd_q *cmdq) window_choose_add(wl->window->active, cdata); } + + idx = 0; + while ((pb = paste_walk_stack(&named_buffers, &idx)) != NULL) { + cdata = window_choose_data_create(TREE_OTHER, c, c->session); + cdata->idx = idx - 1; + + cdata->ft_template = xstrdup(template); + format_add(cdata->ft, "line", "%s", pb->name); + format_paste_buffer(cdata->ft, pb); + + xasprintf(&action_data, "%s", pb->name); + cdata->command = cmd_template_replace(action, action_data, 1); + free(action_data); + + window_choose_add(wl->window->active, cdata); + } free(action); window_choose_ready(wl->window->active, 0, NULL); diff --git a/cmd-command-prompt.c b/cmd-command-prompt.c index 759d578..0acecc5 100644 --- a/cmd-command-prompt.c +++ b/cmd-command-prompt.c @@ -76,6 +76,9 @@ cmd_command_prompt_key_binding(struct cmd *self, int key) self->args = args_create(1, "select-window -t ':%%'"); args_set(self->args, 'p', "index"); break; + case 'P': + self->args = args_create(1, "paste-buffer -b '%%'"); + break; default: self->args = args_create(0); break; diff --git a/cmd-delete-buffer.c b/cmd-delete-buffer.c index b8f55db..d4f97c1 100644 --- a/cmd-delete-buffer.c +++ b/cmd-delete-buffer.c @@ -43,6 +43,7 @@ cmd_delete_buffer_exec(struct cmd *self, struct cmd_q *cmdq) struct args *args = self->args; char *cause; int buffer; + const char *bufname; if (!args_has(args, 'b')) { paste_free_top(&global_buffers); @@ -51,9 +52,14 @@ cmd_delete_buffer_exec(struct cmd *self, struct cmd_q *cmdq) buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause); if (cause != NULL) { - cmdq_error(cmdq, "buffer %s", cause); free(cause); - return (CMD_RETURN_ERROR); + bufname = args_get(args, 'b'); + if (paste_free_name(&named_buffers, bufname) != 0) { + cmdq_error(cmdq, "no buffer %s", bufname); + return (CMD_RETURN_ERROR); + } + + return (CMD_RETURN_NORMAL); } if (paste_free_index(&global_buffers, buffer) != 0) { diff --git a/cmd-list-buffers.c b/cmd-list-buffers.c index 02a4183..98d013f 100644 --- a/cmd-list-buffers.c +++ b/cmd-list-buffers.c @@ -64,5 +64,18 @@ cmd_list_buffers_exec(unused struct cmd *self, struct cmd_q *cmdq) format_free(ft); } + idx = 0; + while ((pb = paste_walk_stack(&named_buffers, &idx)) != NULL) { + ft = format_create(); + format_add(ft, "line", "%s", pb->name); + format_paste_buffer(ft, pb); + + line = format_expand(ft, template); + cmdq_print(cmdq, "%s", line); + free(line); + + format_free(ft); + } + return (CMD_RETURN_NORMAL); } diff --git a/cmd-load-buffer.c b/cmd-load-buffer.c index 2cb01b9..9093fa1 100644 --- a/cmd-load-buffer.c +++ b/cmd-load-buffer.c @@ -51,29 +51,29 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_q *cmdq) struct session *s; FILE *f; const char *path; - char *pdata, *new_pdata, *cause; + char *pdata, *new_pdata, *cause, *bufname; size_t psize; u_int limit; - int ch, error, buffer, *buffer_ptr, cwd, fd; + int ch, error, buffer, cwd, fd; + bufname = NULL; if (!args_has(args, 'b')) buffer = -1; else { buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause); if (cause != NULL) { - cmdq_error(cmdq, "buffer %s", cause); free(cause); - return (CMD_RETURN_ERROR); + bufname = xstrdup(args_get(args, 'b')); } } path = args->argv[0]; if (strcmp(path, "-") == 0) { - buffer_ptr = xmalloc(sizeof *buffer_ptr); - *buffer_ptr = buffer; + if (bufname == NULL && args_has(args, 'b')) + bufname = xstrdup(args_get(args, 'b')); error = server_set_stdin_callback(c, cmd_load_buffer_callback, - buffer_ptr, &cause); + bufname, &cause); if (error != 0) { cmdq_error(cmdq, "%s: %s", path, cause); free(cause); @@ -118,6 +118,19 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_q *cmdq) fclose(f); limit = options_get_number(&global_options, "buffer-limit"); + + if (bufname != NULL) { + if(paste_set_named_buffer(&named_buffers, + pdata, psize, limit, bufname, &cause) != 0) { + cmdq_error(cmdq, "%s", cause); + free(pdata); + free(cause); + free(bufname); + return (CMD_RETURN_ERROR); + } + return (CMD_RETURN_NORMAL); + } + if (buffer == -1) { paste_add(&global_buffers, pdata, psize, limit); return (CMD_RETURN_NORMAL); @@ -140,8 +153,8 @@ error: void cmd_load_buffer_callback(struct client *c, int closed, void *data) { - int *buffer = data; - char *pdata; + int buffer; + char *pdata, *cause, *bufname, *bufarg = data; size_t psize; u_int limit; @@ -163,11 +176,28 @@ cmd_load_buffer_callback(struct client *c, int closed, void *data) evbuffer_drain(c->stdin_data, psize); limit = options_get_number(&global_options, "buffer-limit"); - if (*buffer == -1) + bufname = NULL; + if (bufarg == NULL) + buffer = -1; + else { + buffer = strtonum(bufarg, 0, INT_MAX, &cause); + if (cause != NULL) + bufname = xstrdup(bufarg); + } + + if (bufname != NULL) { + if (paste_set_named_buffer(&named_buffers, + pdata, psize, limit, bufname, &cause) != 0) { + evbuffer_add_printf(c->stderr_data, "%s", cause); + server_push_stderr(c); + free(pdata); + free(cause); + } + } else if (buffer == -1) paste_add(&global_buffers, pdata, psize, limit); - else if (paste_replace(&global_buffers, *buffer, pdata, psize) != 0) { + else if (paste_replace(&global_buffers, buffer, pdata, psize) != 0) { /* No context so can't use server_client_msg_error. */ - evbuffer_add_printf(c->stderr_data, "no buffer %d\n", *buffer); + evbuffer_add_printf(c->stderr_data, "no buffer %d\n", buffer); server_push_stderr(c); free(pdata); } diff --git a/cmd-paste-buffer.c b/cmd-paste-buffer.c index 5305b7e..14434d1 100644 --- a/cmd-paste-buffer.c +++ b/cmd-paste-buffer.c @@ -48,7 +48,7 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmd_q *cmdq) struct window_pane *wp; struct session *s; struct paste_buffer *pb; - const char *sepstr; + const char *sepstr, *bufname; char *cause; int buffer; int pflag; @@ -56,18 +56,24 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmd_q *cmdq) if (cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp) == NULL) return (CMD_RETURN_ERROR); + bufname = NULL; if (!args_has(args, 'b')) buffer = -1; else { buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause); if (cause != NULL) { - cmdq_error(cmdq, "buffer %s", cause); free(cause); - return (CMD_RETURN_ERROR); + bufname = args_get(args, 'b'); } } - if (buffer == -1) + if (bufname != NULL) { + pb = paste_get_name(&named_buffers, bufname); + if (pb == NULL) { + cmdq_error(cmdq, "no buffer %s", bufname); + return (CMD_RETURN_ERROR); + } + } else if (buffer == -1) pb = paste_get_top(&global_buffers); else { pb = paste_get_index(&global_buffers, buffer); @@ -91,7 +97,9 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmd_q *cmdq) /* Delete the buffer if -d. */ if (args_has(args, 'd')) { - if (buffer == -1) + if (bufname != NULL) + paste_free_name(&named_buffers, bufname); + else if (buffer == -1) paste_free_top(&global_buffers); else paste_free_index(&global_buffers, buffer); diff --git a/cmd-save-buffer.c b/cmd-save-buffer.c index 3788fc2..9933f60 100644 --- a/cmd-save-buffer.c +++ b/cmd-save-buffer.c @@ -58,7 +58,7 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_q *cmdq) struct client *c = cmdq->client; struct session *s; struct paste_buffer *pb; - const char *path; + const char *path, *bufname; char *cause, *start, *end, *msg; size_t size, used, msglen; int cwd, fd, buffer; @@ -72,15 +72,19 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_q *cmdq) } else { buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause); if (cause != NULL) { - cmdq_error(cmdq, "buffer %s", cause); free(cause); - return (CMD_RETURN_ERROR); - } - - pb = paste_get_index(&global_buffers, buffer); - if (pb == NULL) { - cmdq_error(cmdq, "no buffer %d", buffer); - return (CMD_RETURN_ERROR); + bufname = args_get(args, 'b'); + pb = paste_get_name(&named_buffers, bufname); + if (pb == NULL) { + cmdq_error(cmdq, "no buffer %s", bufname); + return (CMD_RETURN_ERROR); + } + } else { + pb = paste_get_index(&global_buffers, buffer); + if (pb == NULL) { + cmdq_error(cmdq, "no buffer %d", buffer); + return (CMD_RETURN_ERROR); + } } } diff --git a/cmd-set-buffer.c b/cmd-set-buffer.c index e7f9b95..63fc076 100644 --- a/cmd-set-buffer.c +++ b/cmd-set-buffer.c @@ -44,7 +44,7 @@ cmd_set_buffer_exec(struct cmd *self, struct cmd_q *cmdq) struct args *args = self->args; struct paste_buffer *pb; u_int limit; - char *pdata, *cause; + char *pdata, *cause, *bufname; size_t psize, newsize; int buffer; @@ -55,6 +55,7 @@ cmd_set_buffer_exec(struct cmd *self, struct cmd_q *cmdq) pb = NULL; buffer = -1; + bufname = NULL; if ((newsize = strlen(args->argv[0])) == 0) return (CMD_RETURN_NORMAL); @@ -62,14 +63,15 @@ cmd_set_buffer_exec(struct cmd *self, struct cmd_q *cmdq) if (args_has(args, 'b')) { buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause); if (cause != NULL) { - cmdq_error(cmdq, "buffer %s", cause); free(cause); - return (CMD_RETURN_ERROR); - } - pb = paste_get_index(&global_buffers, buffer); - if (pb == NULL) { - cmdq_error(cmdq, "no buffer %d", buffer); - return (CMD_RETURN_ERROR); + bufname = xstrdup(args_get(args, 'b')); + pb = paste_get_name(&named_buffers, bufname); + } else { + pb = paste_get_index(&global_buffers, buffer); + if (pb == NULL) { + cmdq_error(cmdq, "no buffer %d", buffer); + return (CMD_RETURN_ERROR); + } } } else if (args_has(args, 'a')) { pb = paste_get_top(&global_buffers); @@ -87,7 +89,16 @@ cmd_set_buffer_exec(struct cmd *self, struct cmd_q *cmdq) memcpy(pdata + psize, args->argv[0], newsize); psize += newsize; - if (buffer == -1) + if (bufname != NULL) { + if (paste_set_named_buffer(&named_buffers, + pdata, psize, limit, bufname, &cause) != 0) { + cmdq_error(cmdq, "%s", cause); + free(pdata); + free(cause); + free(bufname); + return (CMD_RETURN_ERROR); + } + } else if (buffer == -1) paste_add(&global_buffers, pdata, psize, limit); else paste_replace(&global_buffers, buffer, pdata, psize); diff --git a/key-bindings.c b/key-bindings.c index 86048ea..93fbaa8 100644 --- a/key-bindings.c +++ b/key-bindings.c @@ -130,6 +130,7 @@ key_bindings_init(void) { '?', 0, &cmd_list_keys_entry }, { 'D', 0, &cmd_choose_client_entry }, { 'L', 0, &cmd_switch_client_entry }, + { 'P', 0, &cmd_command_prompt_entry }, { '[', 0, &cmd_copy_mode_entry }, { '\'', 0, &cmd_command_prompt_entry }, { '\002', /* C-b */ 0, &cmd_send_prefix_entry }, diff --git a/mode-key.c b/mode-key.c index 57be2d8..b9ad8e4 100644 --- a/mode-key.c +++ b/mode-key.c @@ -51,6 +51,7 @@ const struct mode_key_cmdstr mode_key_cmdstr_edit[] = { { MODEKEYEDIT_DELETEWORD, "delete-word" }, { MODEKEYEDIT_ENDOFLINE, "end-of-line" }, { MODEKEYEDIT_ENTER, "enter" }, + { MODEKEYEDIT_ENTERAPPEND, "enter-append" }, { MODEKEYEDIT_HISTORYDOWN, "history-down" }, { MODEKEYEDIT_HISTORYUP, "history-up" }, { MODEKEYEDIT_NEXTSPACE, "next-space" }, @@ -141,6 +142,7 @@ const struct mode_key_cmdstr mode_key_cmdstr_copy[] = { { MODEKEYCOPY_SEARCHREVERSE, "search-reverse" }, { MODEKEYCOPY_SEARCHUP, "search-backward" }, { MODEKEYCOPY_SELECTLINE, "select-line" }, + { MODEKEYCOPY_STARTNAMEDBUFFER, "start-named-buffer" }, { MODEKEYCOPY_STARTNUMBERPREFIX, "start-number-prefix" }, { MODEKEYCOPY_STARTOFLINE, "start-of-line" }, { MODEKEYCOPY_STARTSELECTION, "begin-selection" }, @@ -160,6 +162,7 @@ const struct mode_key_entry mode_key_vi_edit[] = { { '\033' /* Escape */, 0, MODEKEYEDIT_SWITCHMODE }, { '\n', 0, MODEKEYEDIT_ENTER }, { '\r', 0, MODEKEYEDIT_ENTER }, + { '\001' /* C-a */, 0, MODEKEYEDIT_ENTERAPPEND }, { KEYC_BSPACE, 0, MODEKEYEDIT_BACKSPACE }, { KEYC_DC, 0, MODEKEYEDIT_DELETE }, { KEYC_DOWN, 0, MODEKEYEDIT_HISTORYDOWN }, @@ -257,6 +260,7 @@ struct mode_key_tree mode_key_tree_vi_choice; /* vi copy mode keys. */ const struct mode_key_entry mode_key_vi_copy[] = { { ' ', 0, MODEKEYCOPY_STARTSELECTION }, + { '"', 0, MODEKEYCOPY_STARTNAMEDBUFFER }, { '$', 0, MODEKEYCOPY_ENDOFLINE }, { ',', 0, MODEKEYCOPY_JUMPREVERSE }, { ';', 0, MODEKEYCOPY_JUMPAGAIN }, diff --git a/paste.c b/paste.c index 28f1230..f294bad 100644 --- a/paste.c +++ b/paste.c @@ -21,6 +21,7 @@ #include <stdlib.h> #include <string.h> +#include <ctype.h> #include "tmux.h" @@ -29,6 +30,8 @@ * string! */ +int compare_named_buffer_names(const void *, const void *); + /* Return each item of the stack in turn. */ struct paste_buffer * paste_walk_stack(struct paste_stack *ps, u_int *idx) @@ -89,11 +92,31 @@ paste_free_index(struct paste_stack *ps, u_int idx) ARRAY_REMOVE(ps, idx); free(pb->data); + free(pb->name); free(pb); return (0); } +/* Free an item by name. */ +int +paste_free_name(struct paste_stack *ps, const char *name) +{ + struct paste_buffer *pb; + u_int idx; + + if (name == NULL || *name == '\0') + return (-1); + + idx = 0; + while ((pb = paste_walk_stack(ps, &idx)) != NULL) + if (pb->name != NULL && strcmp(name, pb->name) == 0) + return (paste_free_index(ps, idx - 1)); + + + return (-1); +} + /* * Add an item onto the top of the stack, freeing the bottom if at limit. Note * that the caller is responsible for allocating data. @@ -109,6 +132,7 @@ paste_add(struct paste_stack *ps, char *data, size_t size, u_int limit) while (ARRAY_LENGTH(ps) >= limit) { pb = ARRAY_LAST(ps); free(pb->data); + free(pb->name); free(pb); ARRAY_TRUNC(ps, 1); } @@ -118,6 +142,7 @@ paste_add(struct paste_stack *ps, char *data, size_t size, u_int limit) pb->data = data; pb->size = size; + pb->name = NULL; } @@ -194,3 +219,105 @@ paste_send_pane(struct paste_buffer *pb, struct window_pane *wp, if (bracket) bufferevent_write(wp->event, "\033[201~", 6); } + +int +compare_named_buffer_names(const void *a, const void *b) +{ + struct paste_buffer *x, *y; + + x = *(struct paste_buffer **)a; + y = *(struct paste_buffer **)b; + + return (strcmp(x->name, y->name)); +} + +/* Get an item by its name. */ +struct paste_buffer * +paste_get_name(struct paste_stack *ps, const char *name) +{ + struct paste_buffer *pb; + u_int idx = 0; + + if (name == NULL || *name == '\0') + return (NULL); + + while ((pb = paste_walk_stack(ps, &idx)) != NULL) + if (pb->name != NULL && strcmp(name, pb->name) == 0) + break; + + return (pb); +} + +int +paste_set_named_buffer(struct paste_stack *ps, char *data, size_t size, + u_int limit, char *name, char **cause) +{ + struct paste_buffer *pb, **psdata; + char *c, *errstr; + + if (cause != NULL) + *cause = NULL; + + if (name == NULL || *name == '\0') { + if (cause != NULL) + *cause = xstrdup("empty buffer name"); + return (-1); + } + + + + if (size == 0) { + free(data); + free(name); + return (0); + } + + pb = paste_get_name(ps, name); + + if (pb != NULL) { + free(name); + free(pb->data); + pb->data = data; + pb->size = size; + return (0); + } + + if (ARRAY_LENGTH(ps) >= limit) { + if (cause != NULL) + *cause = xstrdup("buffer-limit reached"); + return (-1); + } + + if (strlen(name) > 16) { + if (cause != NULL) + *cause = xstrdup("buffer name too long"); + return (-1); + } + + strtonum(name, 0, INT_MAX, &errstr); + if (errstr == NULL) { + if (cause != NULL) + *cause = xstrdup("buffer name can't be a number"); + return (-1); + } + + for (c = name; *c != '\0'; c++) { + if (!isprint(*c) || isspace(*c)) { + if (cause != NULL) + *cause = xstrdup("bad characters in buffer name"); + return (-1); + } + } + + pb = xmalloc(sizeof *pb); + ARRAY_INSERT(ps, 0, pb); + + pb->data = data; + pb->size = size; + pb->name = name; + + psdata = ARRAY_DATA(ps); + qsort(psdata, ARRAY_LENGTH(ps), sizeof pb, &compare_named_buffer_names); + return (0); +} + diff --git a/server.c b/server.c index f372de4..0bb11b4 100644 --- a/server.c +++ b/server.c @@ -51,6 +51,7 @@ struct event server_ev_accept; struct event server_ev_second; struct paste_stack global_buffers; +struct paste_stack named_buffers; int server_create_socket(void); void server_loop(void); @@ -147,6 +148,7 @@ server_start(int lockfd, char *lockfile) RB_INIT(&dead_sessions); TAILQ_INIT(&session_groups); ARRAY_INIT(&global_buffers); + ARRAY_INIT(&named_buffers); mode_key_init_trees(); key_bindings_init(); utf8_build(); diff --git a/tmux.h b/tmux.h index 5aac390..e3980c5 100644 --- a/tmux.h +++ b/tmux.h @@ -496,6 +496,7 @@ enum mode_key_cmd { MODEKEYEDIT_DELETEWORD, MODEKEYEDIT_ENDOFLINE, MODEKEYEDIT_ENTER, + MODEKEYEDIT_ENTERAPPEND, MODEKEYEDIT_HISTORYDOWN, MODEKEYEDIT_HISTORYUP, MODEKEYEDIT_NEXTSPACE, @@ -579,6 +580,7 @@ enum mode_key_cmd { MODEKEYCOPY_SEARCHREVERSE, MODEKEYCOPY_SEARCHUP, MODEKEYCOPY_SELECTLINE, + MODEKEYCOPY_STARTNAMEDBUFFER, MODEKEYCOPY_STARTNUMBERPREFIX, MODEKEYCOPY_STARTOFLINE, MODEKEYCOPY_STARTSELECTION, @@ -1031,6 +1033,7 @@ struct layout_cell { /* Paste buffer. */ struct paste_buffer { char *data; + char *name; size_t size; }; ARRAY_DECL(paste_stack, struct paste_buffer *); @@ -1707,9 +1710,13 @@ int tty_keys_next(struct tty *); struct paste_buffer *paste_walk_stack(struct paste_stack *, u_int *); struct paste_buffer *paste_get_top(struct paste_stack *); struct paste_buffer *paste_get_index(struct paste_stack *, u_int); +struct paste_buffer *paste_get_name(struct paste_stack *, const char *); int paste_free_top(struct paste_stack *); int paste_free_index(struct paste_stack *, u_int); +int paste_free_name(struct paste_stack *, const char *); void paste_add(struct paste_stack *, char *, size_t, u_int); +int paste_set_named_buffer(struct paste_stack *, char *, size_t, + u_int, char *, char **); int paste_replace(struct paste_stack *, u_int, char *, size_t); char *paste_print(struct paste_buffer *, size_t); void paste_send_pane(struct paste_buffer *, struct window_pane *, @@ -1884,6 +1891,7 @@ const char *key_string_lookup_key(int); extern struct clients clients; extern struct clients dead_clients; extern struct paste_stack global_buffers; +extern struct paste_stack named_buffers; int server_start(int, char *); void server_update_socket(void); void server_add_accept(int); diff --git a/window-copy.c b/window-copy.c index e3164f6..f7dac03 100644 --- a/window-copy.c +++ b/window-copy.c @@ -94,6 +94,7 @@ const struct window_mode window_copy_mode = { enum window_copy_input_type { WINDOW_COPY_OFF, + WINDOW_COPY_NAMEDBUFFER, WINDOW_COPY_NUMERICPREFIX, WINDOW_COPY_SEARCHUP, WINDOW_COPY_SEARCHDOWN, @@ -676,6 +677,7 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key) case WINDOW_COPY_JUMPBACK: case WINDOW_COPY_JUMPTOFORWARD: case WINDOW_COPY_JUMPTOBACK: + case WINDOW_COPY_NAMEDBUFFER: case WINDOW_COPY_NUMERICPREFIX: break; case WINDOW_COPY_SEARCHUP: @@ -711,6 +713,11 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key) data->inputprompt = "Goto Line"; *data->inputstr = '\0'; goto input_on; + case MODEKEYCOPY_STARTNAMEDBUFFER: + data->inputtype = WINDOW_COPY_NAMEDBUFFER; + data->inputprompt = "Buffer"; + *data->inputstr = '\0'; + goto input_on; case MODEKEYCOPY_STARTNUMBERPREFIX: key &= KEYC_MASK_KEY; if (key >= '0' && key <= '9') { @@ -814,6 +821,11 @@ window_copy_key_input(struct window_pane *wp, int key) data->searchtype = data->inputtype; data->searchstr = xstrdup(data->inputstr); break; + case WINDOW_COPY_NAMEDBUFFER: + window_copy_copy_selection(wp, -1); + *data->inputstr = '\0'; + window_pane_reset_mode(wp); + return (0); case WINDOW_COPY_GOTOLINE: window_copy_goto_line(wp, data->inputstr); *data->inputstr = '\0'; @@ -821,6 +833,17 @@ window_copy_key_input(struct window_pane *wp, int key) } data->numprefix = -1; return (1); + case MODEKEYEDIT_ENTERAPPEND: + switch (data->inputtype) { + case WINDOW_COPY_NAMEDBUFFER: + window_copy_append_selection(wp, -1); + *data->inputstr = '\0'; + window_pane_reset_mode(wp); + return (0); + default: + break; + } + break; case MODEKEY_OTHER: if (key < 32 || key > 126) break; @@ -1451,8 +1474,10 @@ window_copy_get_selection(struct window_pane *wp, size_t *len) void window_copy_copy_buffer(struct window_pane *wp, int idx, void *buf, size_t len) { - u_int limit; - struct screen_write_ctx ctx; + u_int limit; + char *bufname; + struct screen_write_ctx ctx; + struct window_copy_mode_data *data = wp->modedata; if (options_get_number(&global_options, "set-clipboard")) { screen_write_start(&ctx, wp, NULL); @@ -1460,10 +1485,21 @@ window_copy_copy_buffer(struct window_pane *wp, int idx, void *buf, size_t len) screen_write_stop(&ctx); } - if (idx == -1) { - limit = options_get_number(&global_options, "buffer-limit"); + limit = options_get_number(&global_options, "buffer-limit"); + + if (data->inputstr != NULL && *data->inputstr != '\0') { + bufname = xstrdup(data->inputstr); + if (paste_set_named_buffer(&named_buffers, + buf, len, limit, bufname, NULL) != 0) { + free(buf); + free(bufname); + } + return; + } + + if (idx == -1) paste_add(&global_buffers, buf, len, limit); - } else if (paste_replace(&global_buffers, idx, buf, len) != 0) + else if (paste_replace(&global_buffers, idx, buf, len) != 0) free(buf); } @@ -1502,11 +1538,12 @@ window_copy_copy_selection(struct window_pane *wp, int idx) void window_copy_append_selection(struct window_pane *wp, int idx) { - char *buf; - struct paste_buffer *pb; - size_t len; - u_int limit; - struct screen_write_ctx ctx; + char *buf, *bufname; + struct paste_buffer *pb; + size_t len; + u_int limit; + struct screen_write_ctx ctx; + struct window_copy_mode_data *data = wp->modedata; buf = window_copy_get_selection(wp, &len); if (buf == NULL) @@ -1521,13 +1558,21 @@ window_copy_append_selection(struct window_pane *wp, int idx) if (idx == -1) idx = 0; - if (idx == 0 && paste_get_top(&global_buffers) == NULL) { - limit = options_get_number(&global_options, "buffer-limit"); - paste_add(&global_buffers, buf, len, limit); - return; - } + limit = options_get_number(&global_options, "buffer-limit"); + + bufname = NULL; + if (data->inputstr != NULL && *data->inputstr != '\0') + bufname = xstrdup(data->inputstr); + + if (bufname == NULL) { + if (idx == 0 && paste_get_top(&global_buffers) == NULL) { + paste_add(&global_buffers, buf, len, limit); + return; + } else + pb = paste_get_index(&global_buffers, idx); + } else + pb = paste_get_name(&named_buffers, bufname); - pb = paste_get_index(&global_buffers, idx); if (pb != NULL) { buf = xrealloc(buf, 1, len + pb->size); memmove(buf + pb->size, buf, len); @@ -1535,8 +1580,17 @@ window_copy_append_selection(struct window_pane *wp, int idx) len += pb->size; } - if (paste_replace(&global_buffers, idx, buf, len) != 0) - free(buf); + if (bufname == NULL) { + if (paste_replace(&global_buffers, idx, buf, len) != 0) + free(buf); + } else { + if (paste_set_named_buffer(&named_buffers, + buf, len, limit, bufname, NULL) != 0) { + free(buf); + free(bufname); + } + } + } void
------------------------------------------------------------------------------
_______________________________________________ tmux-users mailing list tmux-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/tmux-users