-/* $OpenBSD: cmd-capture-pane.c,v 1.26 2014/04/24 09:14:43 nicm Exp $ */
+/* $OpenBSD: cmd-capture-pane.c,v 1.27 2014/05/13 07:34:35 nicm Exp $ */
/*
* Copyright (c) 2009 Jonathan Alvarado <radobobo@users.sourceforge.net>
const struct cmd_entry cmd_capture_pane_entry = {
"capture-pane", "capturep",
"ab:CeE:JpPqS:t:", 0, 0,
- "[-aCeJpPq] [-b buffer-index] [-E end-line] [-S start-line]"
+ "[-aCeJpPq] " CMD_BUFFER_USAGE " [-E end-line] [-S start-line]"
CMD_TARGET_PANE_USAGE,
0,
NULL,
struct client *c;
struct window_pane *wp;
char *buf, *cause;
- int buffer;
- u_int limit;
+ const char *bufname;
size_t len;
if (cmd_find_pane(cmdq, args_get(args, 't'), NULL, &wp) == NULL)
evbuffer_add(c->stdout_data, "\n", 1);
server_push_stdout(c);
} else {
- limit = options_get_number(&global_options, "buffer-limit");
- if (!args_has(args, 'b')) {
- paste_add(buf, len, limit);
- return (CMD_RETURN_NORMAL);
- }
- 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);
- }
+ bufname = NULL;
+ if (args_has(args, 'b'))
+ bufname = args_get(args, 'b');
- if (paste_replace(buffer, buf, len) != 0) {
- cmdq_error(cmdq, "no buffer %d", buffer);
+ if (paste_set(buf, len, bufname, &cause) != 0) {
+ cmdq_error(cmdq, "%s", cause);
free(buf);
+ free(cause);
return (CMD_RETURN_ERROR);
}
}
-/* $OpenBSD: cmd-choose-buffer.c,v 1.17 2014/04/24 09:14:43 nicm Exp $ */
+/* $OpenBSD: cmd-choose-buffer.c,v 1.18 2014/05/13 07:34:35 nicm Exp $ */
/*
* Copyright (c) 2010 Nicholas Marriott <nicm@users.sourceforge.net>
action = xstrdup("paste-buffer -b '%%'");
idx = 0;
- while ((pb = paste_walk_stack(&idx)) != NULL) {
+ pb = NULL;
+ while ((pb = paste_walk(pb)) != NULL) {
cdata = window_choose_data_create(TREE_OTHER, c, c->session);
- cdata->idx = idx - 1;
+ cdata->idx = idx;
cdata->ft_template = xstrdup(template);
- format_add(cdata->ft, "line", "%u", idx - 1);
format_paste_buffer(cdata->ft, pb, utf8flag);
- xasprintf(&action_data, "%u", idx - 1);
+ 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);
+ idx++;
}
free(action);
-/* $OpenBSD: cmd-delete-buffer.c,v 1.11 2014/04/24 09:14:43 nicm Exp $ */
+/* $OpenBSD: cmd-delete-buffer.c,v 1.12 2014/05/13 07:34:35 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
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();
return (CMD_RETURN_NORMAL);
}
+ bufname = args_get(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);
- }
-
- if (paste_free_index(buffer) != 0) {
- cmdq_error(cmdq, "no buffer %d", buffer);
+ if (paste_free_name(bufname) != 0) {
+ cmdq_error(cmdq, "no buffer %s", bufname);
return (CMD_RETURN_ERROR);
}
-/* $OpenBSD: cmd-list-buffers.c,v 1.20 2014/04/24 09:14:43 nicm Exp $ */
+/* $OpenBSD: cmd-list-buffers.c,v 1.21 2014/05/13 07:34:35 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
struct args *args = self->args;
struct paste_buffer *pb;
struct format_tree *ft;
- u_int idx;
char *line;
const char *template;
if ((template = args_get(args, 'F')) == NULL)
template = LIST_BUFFERS_TEMPLATE;
- idx = 0;
- while ((pb = paste_walk_stack(&idx)) != NULL) {
+ pb = NULL;
+ while ((pb = paste_walk(pb)) != NULL) {
ft = format_create();
- format_add(ft, "line", "%u", idx - 1);
format_paste_buffer(ft, pb, 0);
line = format_expand(ft, template);
-/* $OpenBSD: cmd-load-buffer.c,v 1.28 2014/04/24 09:14:43 nicm Exp $ */
+/* $OpenBSD: cmd-load-buffer.c,v 1.29 2014/05/13 07:34:35 nicm Exp $ */
/*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
struct client *c = cmdq->client;
struct session *s;
FILE *f;
- const char *path;
+ const char *path, *bufname;
char *pdata, *new_pdata, *cause;
size_t psize;
- u_int limit;
- int ch, error, buffer, *buffer_ptr, cwd, fd;
-
- 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);
- }
- }
+ int ch, error, cwd, fd;
+
+ bufname = NULL;
+ if (args_has(args, 'b'))
+ bufname = args_get(args, 'b');
path = args->argv[0];
if (strcmp(path, "-") == 0) {
- buffer_ptr = xmalloc(sizeof *buffer_ptr);
- *buffer_ptr = buffer;
-
error = server_set_stdin_callback(c, cmd_load_buffer_callback,
- buffer_ptr, &cause);
+ (void*)bufname, &cause);
if (error != 0) {
cmdq_error(cmdq, "%s: %s", path, cause);
free(cause);
fclose(f);
- limit = options_get_number(&global_options, "buffer-limit");
- if (buffer == -1) {
- paste_add(pdata, psize, limit);
- return (CMD_RETURN_NORMAL);
- }
- if (paste_replace(buffer, pdata, psize) != 0) {
- cmdq_error(cmdq, "no buffer %d", buffer);
+ if (paste_set(pdata, psize, bufname, &cause) != 0) {
+ cmdq_error(cmdq, "%s", cause);
free(pdata);
+ free(cause);
return (CMD_RETURN_ERROR);
}
void
cmd_load_buffer_callback(struct client *c, int closed, void *data)
{
- int *buffer = data;
- char *pdata;
- size_t psize;
- u_int limit;
+ const char *bufname = data;
+ char *pdata, *cause;
+ size_t psize;
if (!closed)
return;
return;
psize = EVBUFFER_LENGTH(c->stdin_data);
- if (psize == 0 || (pdata = malloc(psize + 1)) == NULL) {
- free(data);
+ if (psize == 0 || (pdata = malloc(psize + 1)) == NULL)
goto out;
- }
+
memcpy(pdata, EVBUFFER_DATA(c->stdin_data), psize);
pdata[psize] = '\0';
evbuffer_drain(c->stdin_data, psize);
- limit = options_get_number(&global_options, "buffer-limit");
- if (*buffer == -1)
- paste_add(pdata, psize, limit);
- else if (paste_replace(*buffer, pdata, psize) != 0) {
+ if (paste_set(pdata, psize, bufname, &cause) != 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, "%s", cause);
server_push_stderr(c);
free(pdata);
+ free(cause);
}
- free(data);
-
out:
cmdq_continue(c->cmdq);
}
-/* $OpenBSD: cmd-paste-buffer.c,v 1.24 2014/04/24 09:14:43 nicm Exp $ */
+/* $OpenBSD: cmd-paste-buffer.c,v 1.25 2014/05/13 07:34:35 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
const struct cmd_entry cmd_paste_buffer_entry = {
"paste-buffer", "pasteb",
"db:prs:t:", 0, 0,
- "[-dpr] [-s separator] [-b buffer-index] " CMD_TARGET_PANE_USAGE,
+ "[-dpr] [-s separator] " CMD_BUFFER_USAGE " " CMD_TARGET_PANE_USAGE,
0,
NULL,
cmd_paste_buffer_exec
struct window_pane *wp;
struct session *s;
struct paste_buffer *pb;
- const char *sepstr;
- char *cause;
- int buffer;
+ const char *sepstr, *bufname;
int pflag;
if (cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp) == NULL)
return (CMD_RETURN_ERROR);
- 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 = NULL;
+ if (args_has(args, 'b'))
+ bufname = args_get(args, 'b');
- if (buffer == -1)
+ if (bufname == NULL)
pb = paste_get_top();
else {
- pb = paste_get_index(buffer);
+ pb = paste_get_name(bufname);
if (pb == NULL) {
- cmdq_error(cmdq, "no buffer %d", buffer);
+ cmdq_error(cmdq, "no buffer %s", bufname);
return (CMD_RETURN_ERROR);
}
}
/* Delete the buffer if -d. */
if (args_has(args, 'd')) {
- if (buffer == -1)
+ if (bufname == NULL)
paste_free_top();
else
- paste_free_index(buffer);
+ paste_free_name(bufname);
}
return (CMD_RETURN_NORMAL);
-/* $OpenBSD: cmd-save-buffer.c,v 1.24 2014/04/24 09:14:43 nicm Exp $ */
+/* $OpenBSD: cmd-save-buffer.c,v 1.25 2014/05/13 07:34:35 nicm Exp $ */
/*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
struct client *c = cmdq->client;
struct session *s;
struct paste_buffer *pb;
- const char *path;
- char *cause, *start, *end, *msg;
+ const char *path, *bufname;
+ char *start, *end, *msg;
size_t size, used, msglen;
- int cwd, fd, buffer;
+ int cwd, fd;
FILE *f;
if (!args_has(args, 'b')) {
return (CMD_RETURN_ERROR);
}
} 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(buffer);
+ bufname = args_get(args, 'b');
+ pb = paste_get_name(bufname);
if (pb == NULL) {
- cmdq_error(cmdq, "no buffer %d", buffer);
+ cmdq_error(cmdq, "no buffer %s", bufname);
return (CMD_RETURN_ERROR);
}
}
-/* $OpenBSD: cmd-set-buffer.c,v 1.17 2014/04/24 09:14:43 nicm Exp $ */
+/* $OpenBSD: cmd-set-buffer.c,v 1.18 2014/05/13 07:34:35 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
const struct cmd_entry cmd_set_buffer_entry = {
"set-buffer", "setb",
- "ab:", 1, 1,
- "[-a] " CMD_BUFFER_USAGE " data",
+ "ab:n:", 0, 1,
+ "[-a] " CMD_BUFFER_USAGE " [-n new-buffer-name] data",
0,
NULL,
cmd_set_buffer_exec
{
struct args *args = self->args;
struct paste_buffer *pb;
- u_int limit;
char *pdata, *cause;
+ const char *bufname;
size_t psize, newsize;
- int buffer;
- limit = options_get_number(&global_options, "buffer-limit");
+ bufname = NULL;
+
+ if (args_has(args, 'n')) {
+ if (args->argc > 0) {
+ cmdq_error(cmdq, "don't provide data with n flag");
+ return (CMD_RETURN_ERROR);
+ }
+
+ if (args_has(args, 'b'))
+ bufname = args_get(args, 'b');
+
+ if (bufname == NULL) {
+ pb = paste_get_top();
+ if (pb == NULL) {
+ cmdq_error(cmdq, "no buffer");
+ return (CMD_RETURN_ERROR);
+ }
+ bufname = pb->name;
+ }
+
+ if (paste_rename(bufname, args_get(args, 'n'), &cause) != 0) {
+ cmdq_error(cmdq, "%s", cause);
+ free(cause);
+ return (CMD_RETURN_ERROR);
+ }
+
+ return (CMD_RETURN_NORMAL);
+ }
+
+ if (args->argc != 1) {
+ cmdq_error(cmdq, "no data specified");
+ return (CMD_RETURN_ERROR);
+ }
psize = 0;
pdata = NULL;
pb = NULL;
- buffer = -1;
if ((newsize = strlen(args->argv[0])) == 0)
return (CMD_RETURN_NORMAL);
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(buffer);
- if (pb == NULL) {
- cmdq_error(cmdq, "no buffer %d", buffer);
- return (CMD_RETURN_ERROR);
- }
+ bufname = args_get(args, 'b');
+ pb = paste_get_name(bufname);
} else if (args_has(args, 'a')) {
pb = paste_get_top();
if (pb != NULL)
- buffer = 0;
+ bufname = pb->name;
}
if (args_has(args, 'a') && pb != NULL) {
memcpy(pdata + psize, args->argv[0], newsize);
psize += newsize;
- if (buffer == -1)
- paste_add(pdata, psize, limit);
- else
- paste_replace(buffer, pdata, psize);
+ if (paste_set(pdata, psize, bufname, &cause) != 0) {
+ cmdq_error(cmdq, "%s", cause);
+ free(pdata);
+ free(cause);
+ return (CMD_RETURN_ERROR);
+ }
return (CMD_RETURN_NORMAL);
}
-/* $OpenBSD: format.c,v 1.44 2014/04/17 15:37:55 nicm Exp $ */
+/* $OpenBSD: format.c,v 1.45 2014/05/13 07:34:35 nicm Exp $ */
/*
* Copyright (c) 2011 Nicholas Marriott <nicm@users.sourceforge.net>
char *s;
format_add(ft, "buffer_size", "%zu", pb->size);
+ format_add(ft, "buffer_name", "%s", pb->name);
s = paste_make_sample(pb, utf8flag);
format_add(ft, "buffer_sample", "%s", s);
-/* $OpenBSD: paste.c,v 1.18 2014/04/24 09:14:43 nicm Exp $ */
+/* $OpenBSD: paste.c,v 1.19 2014/05/13 07:34:35 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
#include "tmux.h"
/*
- * Stack of paste buffers. Note that paste buffer data is not necessarily a C
+ * Set of paste buffers. Note that paste buffer data is not necessarily a C
* string!
*/
-ARRAY_DECL(, struct paste_buffer *) paste_buffers = ARRAY_INITIALIZER;
+u_int paste_next_index;
+u_int paste_next_order;
+u_int paste_num_automatic;
+RB_HEAD(paste_name_tree, paste_buffer) paste_by_name;
+RB_HEAD(paste_time_tree, paste_buffer) paste_by_time;
-/* Return each item of the stack in turn. */
-struct paste_buffer *
-paste_walk_stack(u_int *idx)
+int paste_cmp_names(const struct paste_buffer *, const struct paste_buffer *);
+RB_PROTOTYPE(paste_name_tree, paste_buffer, name_entry, paste_cmp_names);
+RB_GENERATE(paste_name_tree, paste_buffer, name_entry, paste_cmp_names);
+
+int paste_cmp_times(const struct paste_buffer *, const struct paste_buffer *);
+RB_PROTOTYPE(paste_time_tree, paste_buffer, time_entry, paste_cmp_times);
+RB_GENERATE(paste_time_tree, paste_buffer, time_entry, paste_cmp_times);
+
+int
+paste_cmp_names(const struct paste_buffer *a, const struct paste_buffer *b)
{
- struct paste_buffer *pb;
+ return (strcmp(a->name, b->name));
+}
- pb = paste_get_index(*idx);
- (*idx)++;
- return (pb);
+int
+paste_cmp_times(const struct paste_buffer *a, const struct paste_buffer *b)
+{
+ if (a->order > b->order)
+ return (-1);
+ if (a->order < b->order)
+ return (1);
+ return (0);
}
-/* Get the top item on the stack. */
+/* Walk paste buffers by name. */
struct paste_buffer *
-paste_get_top(void)
+paste_walk(struct paste_buffer *pb)
{
- if (ARRAY_LENGTH(&paste_buffers) == 0)
- return (NULL);
- return (ARRAY_FIRST(&paste_buffers));
+ if (pb == NULL)
+ return (RB_MIN(paste_time_tree, &paste_by_time));
+ return (RB_NEXT(paste_time_tree, &paste_by_time, pb));
}
-/* Get an item by its index. */
+/* Get the most recent automatic buffer */
struct paste_buffer *
-paste_get_index(u_int idx)
+paste_get_top(void)
{
- if (idx >= ARRAY_LENGTH(&paste_buffers))
+ struct paste_buffer *pb;
+
+ pb = RB_MIN(paste_time_tree, &paste_by_time);
+ if (pb == NULL)
return (NULL);
- return (ARRAY_ITEM(&paste_buffers, idx));
+ return (pb);
}
-/* Free the top item on the stack. */
+/* Free the most recent buffer */
int
paste_free_top(void)
{
struct paste_buffer *pb;
- if (ARRAY_LENGTH(&paste_buffers) == 0)
+ pb = paste_get_top();
+ if (pb == NULL)
return (-1);
+ return (paste_free_name(pb->name));
+}
- pb = ARRAY_FIRST(&paste_buffers);
- ARRAY_REMOVE(&paste_buffers, 0);
+/* Get a paste buffer by name. */
+struct paste_buffer *
+paste_get_name(const char *name)
+{
+ struct paste_buffer pbfind;
- free(pb->data);
- free(pb);
+ if (name == NULL || *name == '\0')
+ return (NULL);
- return (0);
+ pbfind.name = (char*)name;
+ return (RB_FIND(paste_name_tree, &paste_by_name, &pbfind));
}
-/* Free an item by index. */
+/* Free a paste buffer by name. */
int
-paste_free_index(u_int idx)
+paste_free_name(const char *name)
{
- struct paste_buffer *pb;
+ struct paste_buffer *pb, pbfind;
+
+ if (name == NULL || *name == '\0')
+ return (-1);
- if (idx >= ARRAY_LENGTH(&paste_buffers))
+ pbfind.name = (char*)name;
+ pb = RB_FIND(paste_name_tree, &paste_by_name, &pbfind);
+ if (pb == NULL)
return (-1);
- pb = ARRAY_ITEM(&paste_buffers, idx);
- ARRAY_REMOVE(&paste_buffers, idx);
+ RB_REMOVE(paste_name_tree, &paste_by_name, pb);
+ RB_REMOVE(paste_time_tree, &paste_by_time, pb);
+ if (pb->automatic)
+ paste_num_automatic--;
free(pb->data);
+ free(pb->name);
free(pb);
-
return (0);
}
/*
- * Add an item onto the top of the stack, freeing the bottom if at limit. Note
+ * Add an automatic buffer, freeing the oldest automatic item if at limit. Note
* that the caller is responsible for allocating data.
*/
void
-paste_add(char *data, size_t size, u_int limit)
+paste_add(char *data, size_t size)
{
- struct paste_buffer *pb;
+ struct paste_buffer *pb, *pb1;
+ u_int limit;
if (size == 0)
return;
- while (ARRAY_LENGTH(&paste_buffers) >= limit) {
- pb = ARRAY_LAST(&paste_buffers);
- free(pb->data);
- free(pb);
- ARRAY_TRUNC(&paste_buffers, 1);
+ limit = options_get_number(&global_options, "buffer-limit");
+ RB_FOREACH_REVERSE_SAFE(pb, paste_time_tree, &paste_by_time, pb1) {
+ if (paste_num_automatic < limit)
+ break;
+ if (pb->automatic)
+ paste_free_name(pb->name);
}
pb = xmalloc(sizeof *pb);
- ARRAY_INSERT(&paste_buffers, 0, pb);
+
+ pb->name = NULL;
+ do {
+ free(pb->name);
+ xasprintf(&pb->name, "buffer%04u", paste_next_index);
+ paste_next_index++;
+ } while (paste_get_name(pb->name) != NULL);
pb->data = data;
pb->size = size;
+
+ pb->automatic = 1;
+ paste_num_automatic++;
+
+ pb->order = paste_next_order++;
+ RB_INSERT(paste_name_tree, &paste_by_name, pb);
+ RB_INSERT(paste_time_tree, &paste_by_time, pb);
}
+/* Rename a paste buffer. */
+int
+paste_rename(const char *oldname, const char *newname, char **cause)
+{
+ struct paste_buffer *pb;
+
+ if (cause != NULL)
+ *cause = NULL;
+
+ if (oldname == NULL || *oldname == '\0') {
+ if (cause != NULL)
+ *cause = xstrdup("no buffer");
+ return (-1);
+ }
+ if (newname == NULL || *newname == '\0') {
+ if (cause != NULL)
+ *cause = xstrdup("new name is empty");
+ return (-1);
+ }
+
+ pb = paste_get_name(oldname);
+ if (pb == NULL) {
+ if (cause != NULL)
+ xasprintf(cause, "no buffer %s", oldname);
+ return (-1);
+ }
+
+ RB_REMOVE(paste_name_tree, &paste_by_name, pb);
+
+ free(pb->name);
+ pb->name = xstrdup(newname);
+
+ if (pb->automatic)
+ paste_num_automatic--;
+ pb->automatic = 0;
+
+ RB_INSERT(paste_name_tree, &paste_by_name, pb);
+
+ return (0);
+}
/*
- * Replace an item on the stack. Note that the caller is responsible for
+ * Add or replace an item in the store. Note that the caller is responsible for
* allocating data.
*/
int
-paste_replace(u_int idx, char *data, size_t size)
+paste_set(char *data, size_t size, const char *name, char **cause)
{
struct paste_buffer *pb;
+ if (cause != NULL)
+ *cause = NULL;
+
if (size == 0) {
free(data);
return (0);
}
+ if (name == NULL) {
+ paste_add(data, size);
+ return (0);
+ }
- if (idx >= ARRAY_LENGTH(&paste_buffers))
+ if (*name == '\0') {
+ if (cause != NULL)
+ *cause = xstrdup("empty buffer name");
return (-1);
+ }
- pb = ARRAY_ITEM(&paste_buffers, idx);
- free(pb->data);
+ pb = paste_get_name(name);
+ if (pb != NULL)
+ paste_free_name(name);
+
+ pb = xmalloc(sizeof *pb);
+
+ pb->name = xstrdup(name);
pb->data = data;
pb->size = size;
+ pb->automatic = 0;
+ pb->order = paste_next_order++;
+
+ RB_INSERT(paste_name_tree, &paste_by_name, pb);
+ RB_INSERT(paste_time_tree, &paste_by_time, pb);
+
return (0);
}
-.\" $OpenBSD: tmux.1,v 1.391 2014/04/17 15:48:02 nicm Exp $
+.\" $OpenBSD: tmux.1,v 1.392 2014/05/13 07:34:35 nicm Exp $
.\"
.\" Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
.\"
.\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
.\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: April 17 2014 $
+.Dd $Mdocdate: May 13 2014 $
.Dt TMUX 1
.Os
.Sh NAME
.Ql 10w
in vi.
.Pp
-When copying the selection, the repeat count indicates the buffer index to
-replace, if used.
-.Pp
Mode key bindings are defined in a set of named tables:
.Em vi-edit
and
.Fl F .
.It Xo Ic capture-pane
.Op Fl aepPq
-.Op Fl b Ar buffer-index
+.Op Fl b Ar buffer-name
.Op Fl E Ar end-line
.Op Fl S Ar start-line
.Op Fl t Ar target-pane
.El
.Sh BUFFERS
.Nm
-maintains a stack of
+maintains a set of named
.Em paste buffers .
-Up to the value of the
+Each buffer may be either explicitly or automatically named.
+Explicitly named buffers are named when created with the
+.Ic set-buffer
+or
+.Ic load-buffer
+commands, or by renaming an automatically named buffer with
+.Ic set-buffer
+.Fl n .
+Automatically named buffers are given a name such as
+.Ql buffer0001 ,
+.Ql buffer0002
+and so on.
+When the
+.Ic buffer-limit
+option is reached, the oldest automatically named buffer is deleted.
+Explicitly named are not subject to
.Ic buffer-limit
-option are kept; when a new buffer is added, the buffer at the bottom of the
-stack is removed.
+and may be deleted with
+.Ic delete-buffer
+command.
+.Pp
Buffers may be added using
.Ic copy-mode
or the
.Ic set-buffer
-command, and pasted into a window using the
+and
+.Ic load-buffer
+commands, and pasted into a window using the
.Ic paste-buffer
command.
+If a buffer command is used and no buffer is specified, the most
+recently added automatically named buffer is assumed.
.Pp
A configurable history buffer is also maintained for each window.
By default, up to 2000 lines are kept; this can be altered with the
interactively from a list.
After a buffer is selected,
.Ql %%
-is replaced by the buffer index in
+is replaced by the buffer name in
.Ar template
and the result executed as a command.
If
.It Ic clear-history Op Fl t Ar target-pane
.D1 (alias: Ic clearhist )
Remove and free the history for the specified pane.
-.It Ic delete-buffer Op Fl b Ar buffer-index
+.It Ic delete-buffer Op Fl b Ar buffer-name
.D1 (alias: Ic deleteb )
-Delete the buffer at
-.Ar buffer-index ,
-or the top buffer if not specified.
+Delete the buffer named
+.Ar buffer-name ,
+or the most recently added automatically named buffer if not specified.
.It Xo Ic list-buffers
.Op Fl F Ar format
.Xc
.Sx FORMATS
section.
.It Xo Ic load-buffer
-.Op Fl b Ar buffer-index
+.Op Fl b Ar buffer-name
.Ar path
.Xc
.D1 (alias: Ic loadb )
.Ar path .
.It Xo Ic paste-buffer
.Op Fl dpr
-.Op Fl b Ar buffer-index
+.Op Fl b Ar buffer-name
.Op Fl s Ar separator
.Op Fl t Ar target-pane
.Xc
If not specified, paste into the current one.
With
.Fl d ,
-also delete the paste buffer from the stack.
+also delete the paste buffer.
When output, any linefeed (LF) characters in the paste buffer are replaced with
a separator, by default carriage return (CR).
A custom separator may be specified using the
buffer if the application has requested bracketed paste mode.
.It Xo Ic save-buffer
.Op Fl a
-.Op Fl b Ar buffer-index
+.Op Fl b Ar buffer-name
.Ar path
.Xc
.D1 (alias: Ic saveb )
option appends to rather than overwriting the file.
.It Xo Ic set-buffer
.Op Fl a
-.Op Fl b Ar buffer-index
+.Op Fl b Ar buffer-name
+.Op Fl n Ar new-buffer-name
.Ar data
.Xc
.D1 (alias: Ic setb )
The
.Fl a
option appends to rather than overwriting the buffer.
+The
+.Fl n
+option renames the buffer to
+.Ar new-buffer-name .
.It Xo Ic show-buffer
-.Op Fl b Ar buffer-index
+.Op Fl b Ar buffer-name
.Xc
.D1 (alias: Ic showb )
Display the contents of the specified buffer.
-/* $OpenBSD: tmux.h,v 1.460 2014/05/09 09:11:24 nicm Exp $ */
+/* $OpenBSD: tmux.h,v 1.461 2014/05/13 07:34:35 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
/* Default template for choose-buffer. */
#define CHOOSE_BUFFER_TEMPLATE \
- "#{line}: #{buffer_size} bytes: #{buffer_sample}"
+ "#{buffer_name}: #{buffer_size} bytes: #{buffer_sample}"
/* Default template for choose-client. */
#define CHOOSE_CLIENT_TEMPLATE \
/* Default template for list-buffers. */
#define LIST_BUFFERS_TEMPLATE \
- "#{line}: #{buffer_size} bytes: \"#{buffer_sample}\""
+ "#{buffer_name}: #{buffer_size} bytes: " \
+ "\"#{buffer_sample}\""
/* Default template for list-clients. */
#define LIST_CLIENTS_TEMPLATE \
struct paste_buffer {
char *data;
size_t size;
+
+ char *name;
+ int automatic;
+ u_int order;
+
+ RB_ENTRY(paste_buffer) name_entry;
+ RB_ENTRY(paste_buffer) time_entry;
};
/* Environment variable. */
#define CMD_SRCDST_WINDOW_USAGE "[-s src-window] [-t dst-window]"
#define CMD_SRCDST_SESSION_USAGE "[-s src-session] [-t dst-session]"
#define CMD_SRCDST_CLIENT_USAGE "[-s src-client] [-t dst-client]"
-#define CMD_BUFFER_USAGE "[-b buffer-index]"
+#define CMD_BUFFER_USAGE "[-b buffer-name]"
/* tmux.c */
extern struct options global_options;
int tty_keys_next(struct tty *);
/* paste.c */
-struct paste_buffer *paste_walk_stack(u_int *);
+struct paste_buffer *paste_walk(struct paste_buffer *);
struct paste_buffer *paste_get_top(void);
-struct paste_buffer *paste_get_index(u_int);
+struct paste_buffer *paste_get_name(const char *);
int paste_free_top(void);
-int paste_free_index(u_int);
-void paste_add(char *, size_t, u_int);
-int paste_replace(u_int, char *, size_t);
+int paste_free_name(const char *);
+void paste_add(char *, size_t);
+int paste_rename(const char *, const char *, char **);
+int paste_set(char *, size_t, const char *, char **);
char *paste_make_sample(struct paste_buffer *, int);
void paste_send_pane(struct paste_buffer *, struct window_pane *,
const char *, int);
-/* $OpenBSD: window-copy.c,v 1.107 2014/04/24 09:14:43 nicm Exp $ */
+/* $OpenBSD: window-copy.c,v 1.108 2014/05/13 07:34:35 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
void window_copy_start_selection(struct window_pane *);
int window_copy_update_selection(struct window_pane *, int);
void *window_copy_get_selection(struct window_pane *, size_t *);
-void window_copy_copy_buffer(struct window_pane *, int, void *, size_t);
-void window_copy_copy_pipe(
- struct window_pane *, struct session *, int, const char *);
-void window_copy_copy_selection(struct window_pane *, int);
-void window_copy_append_selection(struct window_pane *, int);
+void window_copy_copy_buffer(struct window_pane *, const char *, void *,
+ size_t);
+void window_copy_copy_pipe(struct window_pane *, struct session *,
+ const char *, const char *);
+void window_copy_copy_selection(struct window_pane *, const char *);
+void window_copy_append_selection(struct window_pane *, const char *);
void window_copy_clear_selection(struct window_pane *);
void window_copy_copy_line(
struct window_pane *, char **, size_t *, u_int, u_int, u_int);
switch (cmd) {
case MODEKEYCOPY_APPENDSELECTION:
if (sess != NULL) {
- window_copy_append_selection(wp, data->numprefix);
+ window_copy_append_selection(wp, NULL);
window_pane_reset_mode(wp);
return;
}
if (sess != NULL &&
(cmd == MODEKEYCOPY_COPYLINE ||
cmd == MODEKEYCOPY_COPYENDOFLINE)) {
- window_copy_copy_selection(wp, -1);
+ window_copy_copy_selection(wp, NULL);
window_pane_reset_mode(wp);
return;
}
break;
case MODEKEYCOPY_COPYPIPE:
if (sess != NULL) {
- window_copy_copy_pipe(wp, sess, data->numprefix, arg);
+ window_copy_copy_pipe(wp, sess, NULL, arg);
window_pane_reset_mode(wp);
return;
}
break;
case MODEKEYCOPY_COPYSELECTION:
if (sess != NULL) {
- window_copy_copy_selection(wp, data->numprefix);
+ window_copy_copy_selection(wp, NULL);
window_pane_reset_mode(wp);
return;
}
s->mode &= ~MODE_MOUSE_BUTTON;
s->mode |= MODE_MOUSE_STANDARD;
if (sess != NULL) {
- window_copy_copy_selection(wp, -1);
+ window_copy_copy_selection(wp, NULL);
window_pane_reset_mode(wp);
}
}
}
void
-window_copy_copy_buffer(struct window_pane *wp, int idx, void *buf, size_t len)
+window_copy_copy_buffer(struct window_pane *wp, const char *bufname, void *buf,
+ size_t len)
{
- u_int limit;
struct screen_write_ctx ctx;
if (options_get_number(&global_options, "set-clipboard")) {
screen_write_stop(&ctx);
}
- if (idx == -1) {
- limit = options_get_number(&global_options, "buffer-limit");
- paste_add(buf, len, limit);
- } else if (paste_replace(idx, buf, len) != 0)
+ if (paste_set(buf, len, bufname, NULL) != 0)
free(buf);
}
void
-window_copy_copy_pipe(
- struct window_pane *wp, struct session *sess, int idx, const char *arg)
+window_copy_copy_pipe(struct window_pane *wp, struct session *sess,
+ const char *bufname, const char *arg)
{
void *buf;
size_t len;
job = job_run(arg, sess, NULL, NULL, NULL);
bufferevent_write(job->event, buf, len);
- window_copy_copy_buffer(wp, idx, buf, len);
+ window_copy_copy_buffer(wp, bufname, buf, len);
}
void
-window_copy_copy_selection(struct window_pane *wp, int idx)
+window_copy_copy_selection(struct window_pane *wp, const char *bufname)
{
void* buf;
size_t len;
if (buf == NULL)
return;
- window_copy_copy_buffer(wp, idx, buf, len);
+ window_copy_copy_buffer(wp, bufname, buf, len);
}
void
-window_copy_append_selection(struct window_pane *wp, int idx)
+window_copy_append_selection(struct window_pane *wp, const char *bufname)
{
- char *buf;
- struct paste_buffer *pb;
- size_t len;
- u_int limit;
- struct screen_write_ctx ctx;
+ char *buf;
+ struct paste_buffer *pb;
+ size_t len;
+ struct screen_write_ctx ctx;
buf = window_copy_get_selection(wp, &len);
if (buf == NULL)
screen_write_stop(&ctx);
}
- if (idx == -1)
- idx = 0;
-
- if (idx == 0 && paste_get_top() == NULL) {
- limit = options_get_number(&global_options, "buffer-limit");
- paste_add(buf, len, limit);
- return;
- }
-
- pb = paste_get_index(idx);
+ if (bufname == NULL || *bufname == '\0') {
+ pb = paste_get_top();
+ if (pb != NULL)
+ bufname = pb->name;
+ } else
+ pb = paste_get_name(bufname);
if (pb != NULL) {
buf = xrealloc(buf, 1, len + pb->size);
memmove(buf + pb->size, buf, len);
memcpy(buf, pb->data, pb->size);
len += pb->size;
}
-
- if (paste_replace(idx, buf, len) != 0)
+ if (paste_set(buf, len, bufname, NULL) != 0)
free(buf);
}