Change from a per-session stack of buffers to one global stack which is

much more convenient and also simplifies lot of code. This renders
copy-buffer useless and makes buffer-limit now a server option.

By Tiago Cunha.
pull/1/head
Nicholas Marriott 2010-12-30 23:16:18 +00:00
parent 2231e72968
commit cc42614fa9
22 changed files with 187 additions and 386 deletions

View File

@ -5,7 +5,7 @@ SRCS= attributes.c cfg.c client.c clock.c \
cmd-attach-session.c cmd-bind-key.c \ cmd-attach-session.c cmd-bind-key.c \
cmd-break-pane.c cmd-choose-session.c cmd-choose-window.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-clear-history.c cmd-clock-mode.c cmd-command-prompt.c \
cmd-confirm-before.c cmd-copy-buffer.c cmd-copy-mode.c \ cmd-confirm-before.c cmd-copy-mode.c \
cmd-choose-buffer.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-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-kill-server.c cmd-kill-session.c cmd-kill-window.c \

View File

@ -18,6 +18,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include "tmux.h" #include "tmux.h"
@ -26,31 +27,93 @@
* Write the entire contents of a pane to a buffer. * Write the entire contents of a pane to a buffer.
*/ */
int cmd_capture_pane_parse(struct cmd *, int, char **, char **);
int cmd_capture_pane_exec(struct cmd *, struct cmd_ctx *); int cmd_capture_pane_exec(struct cmd *, struct cmd_ctx *);
void cmd_capture_pane_free(struct cmd *);
void cmd_capture_pane_init(struct cmd *, int);
size_t cmd_capture_pane_print(struct cmd *, char *, size_t);
struct cmd_capture_pane_data {
char *target;
int buffer;
};
const struct cmd_entry cmd_capture_pane_entry = { const struct cmd_entry cmd_capture_pane_entry = {
"capture-pane", "capturep", "capture-pane", "capturep",
CMD_BUFFER_PANE_USAGE, CMD_BUFFER_PANE_USAGE,
0, "", 0, "",
cmd_buffer_init, cmd_capture_pane_init,
cmd_buffer_parse, cmd_capture_pane_parse,
cmd_capture_pane_exec, cmd_capture_pane_exec,
cmd_buffer_free, cmd_capture_pane_free,
cmd_buffer_print cmd_capture_pane_print
}; };
/* ARGSUSED */
void
cmd_capture_pane_init(struct cmd *self, unused int arg)
{
struct cmd_capture_pane_data *data;
self->data = data = xmalloc(sizeof *data);
data->buffer = -1;
data->target = NULL;
}
int
cmd_capture_pane_parse(struct cmd *self, int argc, char **argv, char **cause)
{
struct cmd_capture_pane_data *data;
const char *errstr;
int n, opt;
self->entry->init(self, KEYC_NONE);
data = self->data;
while ((opt = getopt(argc, argv, "b:t:")) != -1) {
switch (opt) {
case 'b':
if (data->buffer == -1) {
n = strtonum(optarg, 0, INT_MAX, &errstr);
if (errstr != NULL) {
xasprintf(cause, "buffer %s", errstr);
goto error;
}
data->buffer = n;
}
break;
case 't':
if (data->target == NULL)
data->target = xstrdup(optarg);
break;
default:
goto usage;
}
}
argc -= optind;
argv += optind;
return (0);
usage:
xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
error:
self->entry->free(self);
return (-1);
}
int int
cmd_capture_pane_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_capture_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_buffer_data *data = self->data; struct cmd_capture_pane_data *data = self->data;
struct window_pane *wp; struct window_pane *wp;
char *buf, *line; char *buf, *line;
struct screen *s; struct screen *s;
struct session *sess; u_int i, limit;
u_int i, limit; size_t len, linelen;
size_t len, linelen;
if (cmd_find_pane(ctx, data->target, &sess, &wp) == NULL) if (cmd_find_pane(ctx, data->target, NULL, &wp) == NULL)
return (-1); return (-1);
s = &wp->base; s = &wp->base;
@ -69,15 +132,41 @@ cmd_capture_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
xfree(line); xfree(line);
} }
limit = options_get_number(&sess->options, "buffer-limit"); limit = options_get_number(&global_options, "buffer-limit");
if (data->buffer == -1) { if (data->buffer == -1) {
paste_add(&sess->buffers, buf, len, limit); paste_add(&global_buffers, buf, len, limit);
return (0); return (0);
} }
if (paste_replace(&sess->buffers, data->buffer, buf, len) != 0) { if (paste_replace(&global_buffers, data->buffer, buf, len) != 0) {
ctx->error(ctx, "no buffer %d", data->buffer); ctx->error(ctx, "no buffer %d", data->buffer);
xfree(buf); xfree(buf);
return (-1); return (-1);
} }
return (0); return (0);
} }
void
cmd_capture_pane_free(struct cmd *self)
{
struct cmd_capture_pane_data *data = self->data;
if (data->target != NULL)
xfree(data->target);
xfree(data);
}
size_t
cmd_capture_pane_print(struct cmd *self, char *buf, size_t len)
{
struct cmd_capture_pane_data *data = self->data;
size_t off = 0;
off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL)
return (off);
if (off < len && data->buffer != -1)
off += xsnprintf(buf + off, len - off, " -b %d", data->buffer);
if (off < len && data->target != NULL)
off += xsnprintf(buf + off, len - off, " -t %s", data->target);
return (off);
}

View File

@ -67,14 +67,14 @@ cmd_choose_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
return (-1); return (-1);
if (paste_get_top(&s->buffers) == NULL) if (paste_get_top(&global_buffers) == NULL)
return (0); return (0);
if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0) if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0)
return (0); return (0);
idx = 0; idx = 0;
while ((pb = paste_walk_stack(&s->buffers, &idx)) != NULL) { while ((pb = paste_walk_stack(&global_buffers, &idx)) != NULL) {
tmp = paste_print(pb, 50); tmp = paste_print(pb, 50);
window_choose_add(wl->window->active, idx - 1, window_choose_add(wl->window->active, idx - 1,
"%u: %zu bytes: \"%s\"", idx - 1, pb->size, tmp); "%u: %zu bytes: \"%s\"", idx - 1, pb->size, tmp);

View File

@ -1,205 +0,0 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
*
* 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 <stdlib.h>
#include <string.h>
#include "tmux.h"
/*
* Copies a session paste buffer to another session.
*/
int cmd_copy_buffer_parse(struct cmd *, int, char **, char **);
int cmd_copy_buffer_exec(struct cmd *, struct cmd_ctx *);
void cmd_copy_buffer_free(struct cmd *);
void cmd_copy_buffer_init(struct cmd *, int);
size_t cmd_copy_buffer_print(struct cmd *, char *, size_t);
struct cmd_copy_buffer_data {
char *dst_session;
char *src_session;
int dst_idx;
int src_idx;
};
const struct cmd_entry cmd_copy_buffer_entry = {
"copy-buffer", "copyb",
"[-a src-index] [-b dst-index] [-s src-session] [-t dst-session]",
0, "",
cmd_copy_buffer_init,
cmd_copy_buffer_parse,
cmd_copy_buffer_exec,
cmd_copy_buffer_free,
cmd_copy_buffer_print
};
/* ARGSUSED */
void
cmd_copy_buffer_init(struct cmd *self, unused int arg)
{
struct cmd_copy_buffer_data *data;
self->data = data = xmalloc(sizeof *data);
data->dst_session = NULL;
data->src_session = NULL;
data->dst_idx = -1;
data->src_idx = -1;
}
int
cmd_copy_buffer_parse(struct cmd *self, int argc, char **argv, char **cause)
{
struct cmd_copy_buffer_data *data;
const char *errstr;
int n, opt;
self->entry->init(self, KEYC_NONE);
data = self->data;
while ((opt = getopt(argc, argv, "a:b:s:t:")) != -1) {
switch (opt) {
case 'a':
if (data->src_idx == -1) {
n = strtonum(optarg, 0, INT_MAX, &errstr);
if (errstr != NULL) {
xasprintf(cause, "buffer %s", errstr);
goto error;
}
data->src_idx = n;
}
break;
case 'b':
if (data->dst_idx == -1) {
n = strtonum(optarg, 0, INT_MAX, &errstr);
if (errstr != NULL) {
xasprintf(cause, "buffer %s", errstr);
goto error;
}
data->dst_idx = n;
}
break;
case 's':
if (data->src_session == NULL)
data->src_session = xstrdup(optarg);
break;
case 't':
if (data->dst_session == NULL)
data->dst_session = xstrdup(optarg);
break;
default:
goto usage;
}
}
argc -= optind;
argv += optind;
return (0);
usage:
xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
error:
self->entry->free(self);
return (-1);
}
int
cmd_copy_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_copy_buffer_data *data = self->data;
struct paste_buffer *pb;
struct paste_stack *dst_ps, *src_ps;
u_char *pdata;
struct session *dst_session, *src_session;
u_int limit;
if ((dst_session = cmd_find_session(ctx, data->dst_session)) == NULL ||
(src_session = cmd_find_session(ctx, data->src_session)) == NULL)
return (-1);
dst_ps = &dst_session->buffers;
src_ps = &src_session->buffers;
if (data->src_idx == -1) {
if ((pb = paste_get_top(src_ps)) == NULL) {
ctx->error(ctx, "no buffers");
return (-1);
}
} else {
if ((pb = paste_get_index(src_ps, data->src_idx)) == NULL) {
ctx->error(ctx, "no buffer %d", data->src_idx);
return (-1);
}
}
limit = options_get_number(&dst_session->options, "buffer-limit");
pdata = xmalloc(pb->size);
memcpy(pdata, pb->data, pb->size);
if (data->dst_idx == -1)
paste_add(dst_ps, pdata, pb->size, limit);
else if (paste_replace(dst_ps, data->dst_idx, pdata, pb->size) != 0) {
ctx->error(ctx, "no buffer %d", data->dst_idx);
xfree(pdata);
return (-1);
}
return (0);
}
void
cmd_copy_buffer_free(struct cmd *self)
{
struct cmd_copy_buffer_data *data = self->data;
if (data->dst_session != NULL)
xfree(data->dst_session);
if (data->src_session != NULL)
xfree(data->src_session);
xfree(data);
}
size_t
cmd_copy_buffer_print(struct cmd *self, char *buf, size_t len)
{
struct cmd_copy_buffer_data *data = self->data;
size_t off = 0;
off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL)
return (off);
if (off < len && data->src_idx != -1) {
off += xsnprintf(buf + off, len - off, " -a %d",
data->src_idx);
}
if (off < len && data->dst_idx != -1) {
off += xsnprintf(buf + off, len - off, " -b %d",
data->dst_idx);
}
if (off < len && data->src_session != NULL) {
off += cmd_prarg(buf + off, len - off, " -s ",
data->src_session);
}
if (off < len && data->dst_session != NULL) {
off += cmd_prarg(buf + off, len - off, " -t ",
data->dst_session);
}
return (off);
}

View File

@ -30,7 +30,7 @@ int cmd_delete_buffer_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_delete_buffer_entry = { const struct cmd_entry cmd_delete_buffer_entry = {
"delete-buffer", "deleteb", "delete-buffer", "deleteb",
CMD_BUFFER_SESSION_USAGE, CMD_BUFFER_USAGE,
0, "", 0, "",
cmd_buffer_init, cmd_buffer_init,
cmd_buffer_parse, cmd_buffer_parse,
@ -43,14 +43,10 @@ int
cmd_delete_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_delete_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_buffer_data *data = self->data; struct cmd_buffer_data *data = self->data;
struct session *s;
if ((s = cmd_find_session(ctx, data->target)) == NULL)
return (-1);
if (data->buffer == -1) if (data->buffer == -1)
paste_free_top(&s->buffers); paste_free_top(&global_buffers);
else if (paste_free_index(&s->buffers, data->buffer) != 0) { else if (paste_free_index(&global_buffers, data->buffer) != 0) {
ctx->error(ctx, "no buffer %d", data->buffer); ctx->error(ctx, "no buffer %d", data->buffer);
return (-1); return (-1);
} }

View File

@ -332,7 +332,6 @@ cmd_buffer_init(struct cmd *self, unused int key)
self->data = data = xmalloc(sizeof *data); self->data = data = xmalloc(sizeof *data);
data->chflags = 0; data->chflags = 0;
data->target = NULL;
data->buffer = -1; data->buffer = -1;
data->arg = NULL; data->arg = NULL;
data->arg2 = NULL; data->arg2 = NULL;
@ -349,7 +348,7 @@ cmd_buffer_parse(struct cmd *self, int argc, char **argv, char **cause)
cmd_buffer_init(self, 0); cmd_buffer_init(self, 0);
data = self->data; data = self->data;
while ((opt = cmd_getopt(argc, argv, "b:t:", entry->chflags)) != -1) { while ((opt = cmd_getopt(argc, argv, "b:", entry->chflags)) != -1) {
if (cmd_parse_flags(opt, entry->chflags, &data->chflags) == 0) if (cmd_parse_flags(opt, entry->chflags, &data->chflags) == 0)
continue; continue;
switch (opt) { switch (opt) {
@ -363,10 +362,6 @@ cmd_buffer_parse(struct cmd *self, int argc, char **argv, char **cause)
data->buffer = n; data->buffer = n;
} }
break; break;
case 't':
if (data->target == NULL)
data->target = xstrdup(optarg);
break;
default: default:
goto usage; goto usage;
} }
@ -392,8 +387,6 @@ cmd_buffer_free(struct cmd *self)
{ {
struct cmd_buffer_data *data = self->data; struct cmd_buffer_data *data = self->data;
if (data->target != NULL)
xfree(data->target);
if (data->arg != NULL) if (data->arg != NULL)
xfree(data->arg); xfree(data->arg);
if (data->arg2 != NULL) if (data->arg2 != NULL)
@ -413,8 +406,6 @@ cmd_buffer_print(struct cmd *self, char *buf, size_t len)
off += cmd_print_flags(buf, len, off, data->chflags); off += cmd_print_flags(buf, len, off, data->chflags);
if (off < len && data->buffer != -1) if (off < len && data->buffer != -1)
off += xsnprintf(buf + off, len - off, " -b %d", data->buffer); off += xsnprintf(buf + off, len - off, " -b %d", data->buffer);
if (off < len && data->target != NULL)
off += cmd_prarg(buf + off, len - off, " -t ", data->target);
if (off < len && data->arg != NULL) if (off < len && data->arg != NULL)
off += cmd_prarg(buf + off, len - off, " ", data->arg); off += cmd_prarg(buf + off, len - off, " ", data->arg);
if (off < len && data->arg2 != NULL) if (off < len && data->arg2 != NULL)

View File

@ -30,29 +30,25 @@ int cmd_list_buffers_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_list_buffers_entry = { const struct cmd_entry cmd_list_buffers_entry = {
"list-buffers", "lsb", "list-buffers", "lsb",
CMD_TARGET_SESSION_USAGE, "",
0, "", 0, "",
cmd_target_init, NULL,
cmd_target_parse, NULL,
cmd_list_buffers_exec, cmd_list_buffers_exec,
cmd_target_free, NULL,
cmd_target_print NULL
}; };
/* ARGSUSED */
int int
cmd_list_buffers_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_list_buffers_exec(unused struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data;
struct session *s;
struct paste_buffer *pb; struct paste_buffer *pb;
u_int idx; u_int idx;
char *tmp; char *tmp;
if ((s = cmd_find_session(ctx, data->target)) == NULL)
return (-1);
idx = 0; idx = 0;
while ((pb = paste_walk_stack(&s->buffers, &idx)) != NULL) { while ((pb = paste_walk_stack(&global_buffers, &idx)) != NULL) {
tmp = paste_print(pb, 50); tmp = paste_print(pb, 50);
ctx->print(ctx, ctx->print(ctx,
"%u: %zu bytes: \"%s\"", idx - 1, pb->size, tmp); "%u: %zu bytes: \"%s\"", idx - 1, pb->size, tmp);

View File

@ -35,7 +35,7 @@ void cmd_load_buffer_callback(struct client *, void *);
const struct cmd_entry cmd_load_buffer_entry = { const struct cmd_entry cmd_load_buffer_entry = {
"load-buffer", "loadb", "load-buffer", "loadb",
CMD_BUFFER_SESSION_USAGE " path", CMD_BUFFER_USAGE " path",
CMD_ARG1, "", CMD_ARG1, "",
cmd_buffer_init, cmd_buffer_init,
cmd_buffer_parse, cmd_buffer_parse,
@ -44,26 +44,16 @@ const struct cmd_entry cmd_load_buffer_entry = {
cmd_buffer_print cmd_buffer_print
}; };
struct cmd_load_buffer_cdata {
struct session *session;
int buffer;
};
int int
cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_buffer_data *data = self->data; struct cmd_buffer_data *data = self->data;
struct cmd_load_buffer_cdata *cdata; struct client *c = ctx->cmdclient;
struct session *s; FILE *f;
struct client *c = ctx->cmdclient; char *pdata, *new_pdata;
FILE *f; size_t psize;
char *pdata, *new_pdata; u_int limit;
size_t psize; int ch;
u_int limit;
int ch;
if ((s = cmd_find_session(ctx, data->target)) == NULL)
return (-1);
if (strcmp(data->arg, "-") == 0) { if (strcmp(data->arg, "-") == 0) {
if (c == NULL) { if (c == NULL) {
@ -79,11 +69,7 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
return (-1); return (-1);
} }
cdata = xmalloc(sizeof *cdata); c->stdin_data = &data->buffer;
cdata->session = s;
cdata->session->references++;
cdata->buffer = data->buffer;
c->stdin_data = cdata;
c->stdin_callback = cmd_load_buffer_callback; c->stdin_callback = cmd_load_buffer_callback;
c->references++; c->references++;
@ -115,14 +101,13 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
pdata[psize] = '\0'; pdata[psize] = '\0';
fclose(f); fclose(f);
f = NULL;
limit = options_get_number(&s->options, "buffer-limit"); limit = options_get_number(&global_options, "buffer-limit");
if (data->buffer == -1) { if (data->buffer == -1) {
paste_add(&s->buffers, pdata, psize, limit); paste_add(&global_buffers, pdata, psize, limit);
return (0); return (0);
} }
if (paste_replace(&s->buffers, data->buffer, pdata, psize) != 0) { if (paste_replace(&global_buffers, data->buffer, pdata, psize) != 0) {
ctx->error(ctx, "no buffer %d", data->buffer); ctx->error(ctx, "no buffer %d", data->buffer);
return (-1); return (-1);
} }
@ -140,11 +125,10 @@ error:
void void
cmd_load_buffer_callback(struct client *c, void *data) cmd_load_buffer_callback(struct client *c, void *data)
{ {
struct cmd_load_buffer_cdata *cdata = data; char *pdata;
struct session *s = cdata->session; size_t psize;
char *pdata; u_int limit;
size_t psize; int *buffer = data;
u_int limit;
/* /*
* Event callback has already checked client is not dead and reduced * Event callback has already checked client is not dead and reduced
@ -152,34 +136,23 @@ cmd_load_buffer_callback(struct client *c, void *data)
*/ */
c->flags |= CLIENT_EXIT; c->flags |= CLIENT_EXIT;
/* Does the target session still exist? */
if (!session_alive(s))
goto out;
psize = EVBUFFER_LENGTH(c->stdin_event->input); psize = EVBUFFER_LENGTH(c->stdin_event->input);
if (psize == 0) if (psize == 0)
goto out; return;
pdata = malloc(psize + 1); pdata = malloc(psize + 1);
if (pdata == NULL) if (pdata == NULL)
goto out; return;
bufferevent_read(c->stdin_event, pdata, psize); bufferevent_read(c->stdin_event, pdata, psize);
pdata[psize] = '\0'; pdata[psize] = '\0';
limit = options_get_number(&s->options, "buffer-limit"); limit = options_get_number(&global_options, "buffer-limit");
if (cdata->buffer == -1) { if (*buffer == -1)
paste_add(&s->buffers, pdata, psize, limit); paste_add(&global_buffers, pdata, psize, limit);
goto out; else if (paste_replace(&global_buffers, *buffer, pdata, psize) != 0) {
}
if (paste_replace(&s->buffers, cdata->buffer, pdata, psize) != 0) {
/* No context so can't use server_client_msg_error. */ /* No context so can't use server_client_msg_error. */
evbuffer_add_printf( evbuffer_add_printf(
c->stderr_event->output, "no buffer %d\n", cdata->buffer); c->stderr_event->output, "no buffer %d\n", *buffer);
bufferevent_enable(c->stderr_event, EV_WRITE); bufferevent_enable(c->stderr_event, EV_WRITE);
goto out;
} }
out:
cdata->session->references--;
xfree(cdata);
} }

View File

@ -136,9 +136,10 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
return (-1); return (-1);
if (data->buffer == -1) if (data->buffer == -1)
pb = paste_get_top(&s->buffers); pb = paste_get_top(&global_buffers);
else { else {
if ((pb = paste_get_index(&s->buffers, data->buffer)) == NULL) { pb = paste_get_index(&global_buffers, data->buffer);
if (pb == NULL) {
ctx->error(ctx, "no buffer %d", data->buffer); ctx->error(ctx, "no buffer %d", data->buffer);
return (-1); return (-1);
} }
@ -150,9 +151,9 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
/* Delete the buffer if -d. */ /* Delete the buffer if -d. */
if (data->flag_delete) { if (data->flag_delete) {
if (data->buffer == -1) if (data->buffer == -1)
paste_free_top(&s->buffers); paste_free_top(&global_buffers);
else else
paste_free_index(&s->buffers, data->buffer); paste_free_index(&global_buffers, data->buffer);
} }
return (0); return (0);

View File

@ -32,7 +32,7 @@ int cmd_save_buffer_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_save_buffer_entry = { const struct cmd_entry cmd_save_buffer_entry = {
"save-buffer", "saveb", "save-buffer", "saveb",
"[-a] " CMD_BUFFER_SESSION_USAGE " path", "[-a] " CMD_BUFFER_USAGE " path",
CMD_ARG1, "a", CMD_ARG1, "a",
cmd_buffer_init, cmd_buffer_init,
cmd_buffer_parse, cmd_buffer_parse,
@ -45,21 +45,18 @@ int
cmd_save_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_save_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_buffer_data *data = self->data; struct cmd_buffer_data *data = self->data;
struct session *s;
struct paste_buffer *pb; struct paste_buffer *pb;
mode_t mask; mode_t mask;
FILE *f; FILE *f;
if ((s = cmd_find_session(ctx, data->target)) == NULL)
return (-1);
if (data->buffer == -1) { if (data->buffer == -1) {
if ((pb = paste_get_top(&s->buffers)) == NULL) { if ((pb = paste_get_top(&global_buffers)) == NULL) {
ctx->error(ctx, "no buffers"); ctx->error(ctx, "no buffers");
return (-1); return (-1);
} }
} else { } else {
if ((pb = paste_get_index(&s->buffers, data->buffer)) == NULL) { pb = paste_get_index(&global_buffers, data->buffer);
if (pb == NULL) {
ctx->error(ctx, "no buffer %d", data->buffer); ctx->error(ctx, "no buffer %d", data->buffer);
return (-1); return (-1);
} }

View File

@ -30,7 +30,7 @@ int cmd_set_buffer_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_set_buffer_entry = { const struct cmd_entry cmd_set_buffer_entry = {
"set-buffer", "setb", "set-buffer", "setb",
CMD_BUFFER_SESSION_USAGE " data", CMD_BUFFER_USAGE " data",
CMD_ARG1, "", CMD_ARG1, "",
cmd_buffer_init, cmd_buffer_init,
cmd_buffer_parse, cmd_buffer_parse,
@ -43,23 +43,20 @@ int
cmd_set_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_set_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_buffer_data *data = self->data; struct cmd_buffer_data *data = self->data;
struct session *s;
u_int limit; u_int limit;
char *pdata; char *pdata;
size_t psize; size_t psize;
if ((s = cmd_find_session(ctx, data->target)) == NULL) limit = options_get_number(&global_options, "buffer-limit");
return (-1);
limit = options_get_number(&s->options, "buffer-limit");
pdata = xstrdup(data->arg); pdata = xstrdup(data->arg);
psize = strlen(pdata); psize = strlen(pdata);
if (data->buffer == -1) { if (data->buffer == -1) {
paste_add(&s->buffers, pdata, psize, limit); paste_add(&global_buffers, pdata, psize, limit);
return (0); return (0);
} }
if (paste_replace(&s->buffers, data->buffer, pdata, psize) != 0) { if (paste_replace(&global_buffers, data->buffer, pdata, psize) != 0) {
ctx->error(ctx, "no buffer %d", data->buffer); ctx->error(ctx, "no buffer %d", data->buffer);
xfree(pdata); xfree(pdata);
return (-1); return (-1);

View File

@ -74,6 +74,7 @@ const char *set_option_bell_action_list[] = {
}; };
const struct set_option_entry set_option_table[] = { const struct set_option_entry set_option_table[] = {
{ "buffer-limit", SET_OPTION_NUMBER, 1, INT_MAX, NULL },
{ "escape-time", SET_OPTION_NUMBER, 0, INT_MAX, NULL }, { "escape-time", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
{ "exit-unattached", SET_OPTION_FLAG, 0, 0, NULL }, { "exit-unattached", SET_OPTION_FLAG, 0, 0, NULL },
{ "quiet", SET_OPTION_FLAG, 0, 0, NULL }, { "quiet", SET_OPTION_FLAG, 0, 0, NULL },
@ -83,15 +84,14 @@ const struct set_option_entry set_option_table[] = {
const struct set_option_entry set_session_option_table[] = { const struct set_option_entry set_session_option_table[] = {
{ "base-index", SET_OPTION_NUMBER, 0, INT_MAX, NULL }, { "base-index", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
{ "bell-action", SET_OPTION_CHOICE, 0, 0, set_option_bell_action_list }, { "bell-action", SET_OPTION_CHOICE, 0, 0, set_option_bell_action_list },
{ "buffer-limit", SET_OPTION_NUMBER, 1, INT_MAX, NULL },
{ "default-command", SET_OPTION_STRING, 0, 0, NULL }, { "default-command", SET_OPTION_STRING, 0, 0, NULL },
{ "default-path", SET_OPTION_STRING, 0, 0, NULL }, { "default-path", SET_OPTION_STRING, 0, 0, NULL },
{ "default-shell", SET_OPTION_STRING, 0, 0, NULL }, { "default-shell", SET_OPTION_STRING, 0, 0, NULL },
{ "default-terminal", SET_OPTION_STRING, 0, 0, NULL }, { "default-terminal", SET_OPTION_STRING, 0, 0, NULL },
{ "destroy-unattached", SET_OPTION_FLAG, 0, 0, NULL }, { "destroy-unattached", SET_OPTION_FLAG, 0, 0, NULL },
{ "detach-on-destroy", SET_OPTION_FLAG, 0, 0, NULL }, { "detach-on-destroy", SET_OPTION_FLAG, 0, 0, NULL },
{ "display-panes-colour", SET_OPTION_COLOUR, 0, 0, NULL },
{ "display-panes-active-colour", SET_OPTION_COLOUR, 0, 0, NULL }, { "display-panes-active-colour", SET_OPTION_COLOUR, 0, 0, NULL },
{ "display-panes-colour", SET_OPTION_COLOUR, 0, 0, NULL },
{ "display-panes-time", SET_OPTION_NUMBER, 1, INT_MAX, NULL }, { "display-panes-time", SET_OPTION_NUMBER, 1, INT_MAX, NULL },
{ "display-time", SET_OPTION_NUMBER, 1, INT_MAX, NULL }, { "display-time", SET_OPTION_NUMBER, 1, INT_MAX, NULL },
{ "history-limit", SET_OPTION_NUMBER, 0, INT_MAX, NULL }, { "history-limit", SET_OPTION_NUMBER, 0, INT_MAX, NULL },

View File

@ -30,7 +30,7 @@ int cmd_show_buffer_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_show_buffer_entry = { const struct cmd_entry cmd_show_buffer_entry = {
"show-buffer", "showb", "show-buffer", "showb",
CMD_BUFFER_SESSION_USAGE, CMD_BUFFER_USAGE,
0, "", 0, "",
cmd_buffer_init, cmd_buffer_init,
cmd_buffer_parse, cmd_buffer_parse,
@ -49,20 +49,21 @@ cmd_show_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
size_t size, len; size_t size, len;
u_int width; u_int width;
if ((s = cmd_find_session(ctx, data->target)) == NULL) if ((s = cmd_find_session(ctx, NULL)) == NULL)
return (-1); return (-1);
if (data->buffer == -1) { if (data->buffer == -1) {
if ((pb = paste_get_top(&s->buffers)) == NULL) { if ((pb = paste_get_top(&global_buffers)) == NULL) {
ctx->error(ctx, "no buffers"); ctx->error(ctx, "no buffers");
return (-1); return (-1);
} }
} else if ((pb = paste_get_index(&s->buffers, data->buffer)) == NULL) { } else {
ctx->error(ctx, "no buffer %d", data->buffer); pb = paste_get_index(&global_buffers, data->buffer);
return (-1); if (pb == NULL) {
ctx->error(ctx, "no buffer %d", data->buffer);
return (-1);
}
} }
if (pb == NULL)
return (0);
size = pb->size; size = pb->size;
if (size > SIZE_MAX / 4 - 1) if (size > SIZE_MAX / 4 - 1)

1
cmd.c
View File

@ -40,7 +40,6 @@ const struct cmd_entry *cmd_table[] = {
&cmd_clock_mode_entry, &cmd_clock_mode_entry,
&cmd_command_prompt_entry, &cmd_command_prompt_entry,
&cmd_confirm_before_entry, &cmd_confirm_before_entry,
&cmd_copy_buffer_entry,
&cmd_copy_mode_entry, &cmd_copy_mode_entry,
&cmd_delete_buffer_entry, &cmd_delete_buffer_entry,
&cmd_detach_client_entry, &cmd_detach_client_entry,

13
paste.c
View File

@ -29,19 +29,6 @@
* string! * string!
*/ */
void
paste_init_stack(struct paste_stack *ps)
{
ARRAY_INIT(ps);
}
void
paste_free_stack(struct paste_stack *ps)
{
while (paste_free_top(ps) == 0)
;
}
/* Return each item of the stack in turn. */ /* Return each item of the stack in turn. */
struct paste_buffer * struct paste_buffer *
paste_walk_stack(struct paste_stack *ps, uint *idx) paste_walk_stack(struct paste_stack *ps, uint *idx)

View File

@ -51,6 +51,8 @@ int server_shutdown;
struct event server_ev_accept; struct event server_ev_accept;
struct event server_ev_second; struct event server_ev_second;
struct paste_stack global_buffers;
int server_create_socket(void); int server_create_socket(void);
void server_loop(void); void server_loop(void);
int server_should_shutdown(void); int server_should_shutdown(void);
@ -150,6 +152,7 @@ server_start(void)
RB_INIT(&sessions); RB_INIT(&sessions);
RB_INIT(&dead_sessions); RB_INIT(&dead_sessions);
TAILQ_INIT(&session_groups); TAILQ_INIT(&session_groups);
ARRAY_INIT(&global_buffers);
mode_key_init_trees(); mode_key_init_trees();
key_bindings_init(); key_bindings_init();
utf8_build(); utf8_build();

View File

@ -105,8 +105,6 @@ session_create(const char *name, const char *cmd, const char *cwd,
TAILQ_INIT(&s->lastw); TAILQ_INIT(&s->lastw);
RB_INIT(&s->windows); RB_INIT(&s->windows);
paste_init_stack(&s->buffers);
options_init(&s->options, &global_s_options); options_init(&s->options, &global_s_options);
environ_init(&s->environ); environ_init(&s->environ);
if (env != NULL) if (env != NULL)
@ -155,7 +153,6 @@ session_destroy(struct session *s)
session_group_remove(s); session_group_remove(s);
environ_free(&s->environ); environ_free(&s->environ);
options_free(&s->options); options_free(&s->options);
paste_free_stack(&s->buffers);
while (!TAILQ_EMPTY(&s->lastw)) while (!TAILQ_EMPTY(&s->lastw))
winlink_stack_remove(&s->lastw, TAILQ_FIRST(&s->lastw)); winlink_stack_remove(&s->lastw, TAILQ_FIRST(&s->lastw));

View File

@ -983,7 +983,7 @@ status_prompt_key(struct client *c, int key)
c->flags |= CLIENT_STATUS; c->flags |= CLIENT_STATUS;
break; break;
case MODEKEYEDIT_PASTE: case MODEKEYEDIT_PASTE:
if ((pb = paste_get_top(&c->session->buffers)) == NULL) if ((pb = paste_get_top(&global_buffers)) == NULL)
break; break;
for (n = 0; n < pb->size; n++) { for (n = 0; n < pb->size; n++) {
ch = (u_char) pb->data[n]; ch = (u_char) pb->data[n];

32
tmux.1
View File

@ -1594,6 +1594,10 @@ Available window options are listed under
.Pp .Pp
Available server options are: Available server options are:
.Bl -tag -width Ds .Bl -tag -width Ds
.It Ic buffer-limit Ar number
Set the number of buffers; as new buffers are added to the top of the stack,
old ones are removed from the bottom if necessary to maintain this maximum
length.
.It Ic escape-time .It Ic escape-time
Set the time in milliseconds for which Set the time in milliseconds for which
.Nm .Nm
@ -1626,10 +1630,6 @@ window of that session,
means all bells are ignored and means all bells are ignored and
.Ic current .Ic current
means only bell in windows other than the current window are ignored. means only bell in windows other than the current window are ignored.
.It Ic buffer-limit Ar number
Set the number of buffers kept for each session; as new buffers are added to
the top of the stack, old ones are removed from the bottom if necessary to
maintain this maximum length.
.It Ic default-command Ar shell-command .It Ic default-command Ar shell-command
Set the command used for new windows (if not specified when the window is Set the command used for new windows (if not specified when the window is
created) to created) to
@ -2567,29 +2567,16 @@ This command works only from inside
.It Ic clear-history Op Fl t Ar target-pane .It Ic clear-history Op Fl t Ar target-pane
.D1 (alias: Ic clearhist ) .D1 (alias: Ic clearhist )
Remove and free the history for the specified pane. Remove and free the history for the specified pane.
.It Xo Ic copy-buffer .It Ic delete-buffer Op Fl b Ar buffer-index
.Op Fl a Ar src-index
.Op Fl b Ar dst-index
.Op Fl s Ar src-session
.Op Fl t Ar dst-session
.Xc
.D1 (alias: Ic copyb )
Copy a session paste buffer to another session.
If no sessions are specified, the current one is used instead.
.It Xo Ic delete-buffer
.Op Fl b Ar buffer-index
.Op Fl t Ar target-session
.Xc
.D1 (alias: Ic deleteb ) .D1 (alias: Ic deleteb )
Delete the buffer at Delete the buffer at
.Ar buffer-index , .Ar buffer-index ,
or the top buffer if not specified. or the top buffer if not specified.
.It Ic list-buffers Op Fl t Ar target-session .It Ic list-buffers
.D1 (alias: Ic lsb ) .D1 (alias: Ic lsb )
List the buffers in the given session. List the global buffers.
.It Xo Ic load-buffer .It Xo Ic load-buffer
.Op Fl b Ar buffer-index .Op Fl b Ar buffer-index
.Op Fl t Ar target-session
.Ar path .Ar path
.Xc .Xc
.D1 (alias: Ic loadb ) .D1 (alias: Ic loadb )
@ -2618,7 +2605,6 @@ flag means to do no replacement (equivalent to a separator of LF).
.It Xo Ic save-buffer .It Xo Ic save-buffer
.Op Fl a .Op Fl a
.Op Fl b Ar buffer-index .Op Fl b Ar buffer-index
.Op Fl t Ar target-session
.Ar path .Ar path
.Xc .Xc
.D1 (alias: Ic saveb ) .D1 (alias: Ic saveb )
@ -2629,7 +2615,6 @@ The
option appends to rather than overwriting the file. option appends to rather than overwriting the file.
.It Xo Ic set-buffer .It Xo Ic set-buffer
.Op Fl b Ar buffer-index .Op Fl b Ar buffer-index
.Op Fl t Ar target-session
.Ar data .Ar data
.Xc .Xc
.D1 (alias: Ic setb ) .D1 (alias: Ic setb )
@ -2637,7 +2622,6 @@ Set the contents of the specified buffer to
.Ar data . .Ar data .
.It Xo Ic show-buffer .It Xo Ic show-buffer
.Op Fl b Ar buffer-index .Op Fl b Ar buffer-index
.Op Fl t Ar target-session
.Xc .Xc
.D1 (alias: Ic showb ) .D1 (alias: Ic showb )
Display the contents of the specified buffer. Display the contents of the specified buffer.

2
tmux.c
View File

@ -320,12 +320,12 @@ main(int argc, char **argv)
options_set_number(oo, "quiet", quiet); options_set_number(oo, "quiet", quiet);
options_set_number(oo, "escape-time", 500); options_set_number(oo, "escape-time", 500);
options_set_number(oo, "exit-unattached", 0); options_set_number(oo, "exit-unattached", 0);
options_set_number(oo, "buffer-limit", 9);
options_init(&global_s_options, NULL); options_init(&global_s_options, NULL);
so = &global_s_options; so = &global_s_options;
options_set_number(so, "base-index", 0); options_set_number(so, "base-index", 0);
options_set_number(so, "bell-action", BELL_ANY); options_set_number(so, "bell-action", BELL_ANY);
options_set_number(so, "buffer-limit", 9);
options_set_string(so, "default-command", "%s", ""); options_set_string(so, "default-command", "%s", "");
options_set_string(so, "default-path", "%s", ""); options_set_string(so, "default-path", "%s", "");
options_set_string(so, "default-shell", "%s", getshell()); options_set_string(so, "default-shell", "%s", getshell());

9
tmux.h
View File

@ -952,8 +952,6 @@ struct session {
struct options options; struct options options;
struct paste_stack buffers;
#define SESSION_UNATTACHED 0x1 /* not attached to any clients */ #define SESSION_UNATTACHED 0x1 /* not attached to any clients */
int flags; int flags;
@ -1256,7 +1254,6 @@ struct cmd_srcdst_data {
struct cmd_buffer_data { struct cmd_buffer_data {
uint64_t chflags; uint64_t chflags;
char *target;
int buffer; int buffer;
char *arg; char *arg;
@ -1449,8 +1446,6 @@ void tty_keys_free(struct tty *);
int tty_keys_next(struct tty *); int tty_keys_next(struct tty *);
/* paste.c */ /* paste.c */
void paste_init_stack(struct paste_stack *);
void paste_free_stack(struct paste_stack *);
struct paste_buffer *paste_walk_stack(struct paste_stack *, uint *); struct paste_buffer *paste_walk_stack(struct paste_stack *, uint *);
struct paste_buffer *paste_get_top(struct paste_stack *); 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_index(struct paste_stack *, u_int);
@ -1504,7 +1499,6 @@ extern const struct cmd_entry cmd_clear_history_entry;
extern const struct cmd_entry cmd_clock_mode_entry; extern const struct cmd_entry cmd_clock_mode_entry;
extern const struct cmd_entry cmd_command_prompt_entry; extern const struct cmd_entry cmd_command_prompt_entry;
extern const struct cmd_entry cmd_confirm_before_entry; extern const struct cmd_entry cmd_confirm_before_entry;
extern const struct cmd_entry cmd_copy_buffer_entry;
extern const struct cmd_entry cmd_copy_mode_entry; extern const struct cmd_entry cmd_copy_mode_entry;
extern const struct cmd_entry cmd_delete_buffer_entry; extern const struct cmd_entry cmd_delete_buffer_entry;
extern const struct cmd_entry cmd_detach_client_entry; extern const struct cmd_entry cmd_detach_client_entry;
@ -1607,8 +1601,8 @@ void cmd_srcdst_free(struct cmd *);
size_t cmd_srcdst_print(struct cmd *, char *, size_t); size_t cmd_srcdst_print(struct cmd *, char *, size_t);
#define CMD_BUFFER_PANE_USAGE "[-b buffer-index] [-t target-pane]" #define CMD_BUFFER_PANE_USAGE "[-b buffer-index] [-t target-pane]"
#define CMD_BUFFER_WINDOW_USAGE "[-b buffer-index] [-t target-window]" #define CMD_BUFFER_WINDOW_USAGE "[-b buffer-index] [-t target-window]"
#define CMD_BUFFER_SESSION_USAGE "[-b buffer-index] [-t target-session]"
#define CMD_BUFFER_CLIENT_USAGE "[-b buffer-index] [-t target-client]" #define CMD_BUFFER_CLIENT_USAGE "[-b buffer-index] [-t target-client]"
#define CMD_BUFFER_USAGE "[-b buffer-index]"
void cmd_buffer_init(struct cmd *, int); void cmd_buffer_init(struct cmd *, int);
int cmd_buffer_parse(struct cmd *, int, char **, char **); int cmd_buffer_parse(struct cmd *, int, char **, char **);
void cmd_buffer_free(struct cmd *); void cmd_buffer_free(struct cmd *);
@ -1638,6 +1632,7 @@ const char *key_string_lookup_key(int);
/* server.c */ /* server.c */
extern struct clients clients; extern struct clients clients;
extern struct clients dead_clients; extern struct clients dead_clients;
extern struct paste_stack global_buffers;
int server_start(void); int server_start(void);
void server_update_socket(void); void server_update_socket(void);

View File

@ -52,7 +52,7 @@ void window_copy_goto_line(struct window_pane *, const char *);
void window_copy_update_cursor(struct window_pane *, u_int, u_int); void window_copy_update_cursor(struct window_pane *, u_int, u_int);
void window_copy_start_selection(struct window_pane *); void window_copy_start_selection(struct window_pane *);
int window_copy_update_selection(struct window_pane *); int window_copy_update_selection(struct window_pane *);
void window_copy_copy_selection(struct window_pane *, struct session *); void window_copy_copy_selection(struct window_pane *);
void window_copy_clear_selection(struct window_pane *); void window_copy_clear_selection(struct window_pane *);
void window_copy_copy_line( void window_copy_copy_line(
struct window_pane *, char **, size_t *, u_int, u_int, u_int); struct window_pane *, char **, size_t *, u_int, u_int, u_int);
@ -506,7 +506,7 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key)
break; break;
case MODEKEYCOPY_COPYSELECTION: case MODEKEYCOPY_COPYSELECTION:
if (sess != NULL) { if (sess != NULL) {
window_copy_copy_selection(wp, sess); window_copy_copy_selection(wp);
window_pane_reset_mode(wp); window_pane_reset_mode(wp);
return; return;
} }
@ -796,7 +796,7 @@ window_copy_mouse(
s->mode &= ~MODE_MOUSE_ANY; s->mode &= ~MODE_MOUSE_ANY;
s->mode |= MODE_MOUSE_STANDARD; s->mode |= MODE_MOUSE_STANDARD;
if (sess != NULL) { if (sess != NULL) {
window_copy_copy_selection(wp, sess); window_copy_copy_selection(wp);
window_pane_reset_mode(wp); window_pane_reset_mode(wp);
} }
} }
@ -1210,7 +1210,7 @@ window_copy_update_selection(struct window_pane *wp)
} }
void void
window_copy_copy_selection(struct window_pane *wp, struct session *sess) window_copy_copy_selection(struct window_pane *wp)
{ {
struct window_copy_mode_data *data = wp->modedata; struct window_copy_mode_data *data = wp->modedata;
struct screen *s = &data->screen; struct screen *s = &data->screen;
@ -1305,8 +1305,8 @@ window_copy_copy_selection(struct window_pane *wp, struct session *sess)
off--; /* remove final \n */ off--; /* remove final \n */
/* Add the buffer to the stack. */ /* Add the buffer to the stack. */
limit = options_get_number(&sess->options, "buffer-limit"); limit = options_get_number(&global_options, "buffer-limit");
paste_add(&sess->buffers, buf, off, limit); paste_add(&global_buffers, buf, off, limit);
} }
void void