1
0
mirror of https://github.com/tmux/tmux.git synced 2025-03-25 23:38:48 +00:00

Enhance paste-buffer to allow lines to be separated by any string, from

Andrea Barisani.
This commit is contained in:
Nicholas Marriott 2010-05-19 22:28:14 +00:00
parent d91127958d
commit 0ed727a012
2 changed files with 154 additions and 25 deletions

View File

@ -18,7 +18,9 @@
#include <sys/types.h> #include <sys/types.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <vis.h>
#include "tmux.h" #include "tmux.h"
@ -26,27 +28,109 @@
* Paste paste buffer if present. * Paste paste buffer if present.
*/ */
struct cmd_paste_buffer_data {
char *target;
int buffer;
int flag_delete;
char *sepstr;
};
void cmd_paste_buffer_init(struct cmd *, int);
int cmd_paste_buffer_parse(struct cmd *, int, char **, char **);
int cmd_paste_buffer_exec(struct cmd *, struct cmd_ctx *); int cmd_paste_buffer_exec(struct cmd *, struct cmd_ctx *);
void cmd_paste_buffer_lf2cr(struct window_pane *, const char *, size_t); void cmd_paste_buffer_filter(
struct window_pane *, const char *, size_t, char *);
void cmd_paste_buffer_free(struct cmd *);
size_t cmd_paste_buffer_print(struct cmd *, char *, size_t);
const struct cmd_entry cmd_paste_buffer_entry = { const struct cmd_entry cmd_paste_buffer_entry = {
"paste-buffer", "pasteb", "paste-buffer", "pasteb",
"[-dr] " CMD_BUFFER_PANE_USAGE, "[-dr] [-s separator] [-b buffer-index] [-t target-window]",
0, "dr", 0, "",
cmd_buffer_init, cmd_paste_buffer_init,
cmd_buffer_parse, cmd_paste_buffer_parse,
cmd_paste_buffer_exec, cmd_paste_buffer_exec,
cmd_buffer_free, cmd_paste_buffer_free,
cmd_buffer_print cmd_paste_buffer_print
}; };
/* ARGSUSED */
void
cmd_paste_buffer_init(struct cmd *self, unused int arg)
{
struct cmd_paste_buffer_data *data;
self->data = data = xmalloc(sizeof *data);
data->target = NULL;
data->buffer = -1;
data->flag_delete = 0;
data->sepstr = xstrdup("\r");
}
int
cmd_paste_buffer_parse(struct cmd *self, int argc, char **argv, char **cause)
{
struct cmd_paste_buffer_data *data;
int opt, n;
const char *errstr;
cmd_paste_buffer_init(self, 0);
data = self->data;
while ((opt = getopt(argc, argv, "b:ds:t:r")) != -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 'd':
data->flag_delete = 1;
break;
case 's':
if (data->sepstr != NULL)
xfree(data->sepstr);
data->sepstr = xstrdup(optarg);
break;
case 't':
if (data->target == NULL)
data->target = xstrdup(optarg);
break;
case 'r':
if (data->sepstr != NULL)
xfree(data->sepstr);
data->sepstr = xstrdup("\n");
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_paste_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_paste_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_buffer_data *data = self->data; struct cmd_paste_buffer_data *data = self->data;
struct window_pane *wp; struct window_pane *wp;
struct session *s; struct session *s;
struct paste_buffer *pb; struct paste_buffer *pb;
if (cmd_find_pane(ctx, data->target, &s, &wp) == NULL) if (cmd_find_pane(ctx, data->target, &s, &wp) == NULL)
return (-1); return (-1);
@ -60,16 +144,11 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
} }
} }
if (pb != NULL) { if (pb != NULL)
/* -r means raw data without LF->CR conversion. */ cmd_paste_buffer_filter(wp, pb->data, pb->size, data->sepstr);
if (cmd_check_flag(data->chflags, 'r'))
bufferevent_write(wp->event, pb->data, pb->size);
else
cmd_paste_buffer_lf2cr(wp, pb->data, pb->size);
}
/* Delete the buffer if -d. */ /* Delete the buffer if -d. */
if (cmd_check_flag(data->chflags, 'd')) { if (data->flag_delete) {
if (data->buffer == -1) if (data->buffer == -1)
paste_free_top(&s->buffers); paste_free_top(&s->buffers);
else else
@ -79,20 +158,66 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
return (0); return (0);
} }
/* Add bytes to a buffer but change every '\n' to '\r'. */ /* Add bytes to a buffer and filter '\n' according to separator. */
void void
cmd_paste_buffer_lf2cr(struct window_pane *wp, const char *data, size_t size) cmd_paste_buffer_filter(
struct window_pane *wp, const char *data, size_t size, char *sep)
{ {
const char *end = data + size; const char *end = data + size;
const char *lf; const char *lf;
size_t seplen;
seplen = strlen(sep);
while ((lf = memchr(data, '\n', end - data)) != NULL) { while ((lf = memchr(data, '\n', end - data)) != NULL) {
if (lf != data) if (lf != data)
bufferevent_write(wp->event, data, lf - data); bufferevent_write(wp->event, data, lf - data);
bufferevent_write(wp->event, "\r", 1); bufferevent_write(wp->event, sep, seplen);
data = lf + 1; data = lf + 1;
} }
if (end != data) if (end != data)
bufferevent_write(wp->event, data, end - data); bufferevent_write(wp->event, data, end - data);
} }
void
cmd_paste_buffer_free(struct cmd *self)
{
struct cmd_paste_buffer_data *data = self->data;
if (data->target != NULL)
xfree(data->target);
if (data->sepstr != NULL)
xfree(data->sepstr);
xfree(data);
}
size_t
cmd_paste_buffer_print(struct cmd *self, char *buf, size_t len)
{
struct cmd_paste_buffer_data *data = self->data;
size_t off = 0;
char tmp[BUFSIZ];
int r_flag;
r_flag = 0;
if (data->sepstr != NULL)
r_flag = (data->sepstr[0] == '\n' && data->sepstr[1] == '\0');
off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL)
return (off);
if (off < len && data->flag_delete)
off += xsnprintf(buf + off, len - off, " -d");
if (off < len && r_flag)
off += xsnprintf(buf + off, len - off, " -r");
if (off < len && data->buffer != -1)
off += xsnprintf(buf + off, len - off, " -b %d", data->buffer);
if (off < len && data->sepstr != NULL && !r_flag) {
strnvis(
tmp, data->sepstr, sizeof tmp, VIS_OCTAL|VIS_TAB|VIS_NL);
off += cmd_prarg(buf + off, len - off, " -s ", tmp);
}
if (off < len && data->target != NULL)
off += cmd_prarg(buf + off, len - off, " -t ", data->target);
return (off);
}

10
tmux.1
View File

@ -2387,6 +2387,7 @@ Load the contents of the specified paste buffer from
.It Xo Ic paste-buffer .It Xo Ic paste-buffer
.Op Fl dr .Op Fl dr
.Op Fl b Ar buffer-index .Op Fl b Ar buffer-index
.Op Fl s Ar separator
.Op Fl t Ar target-pane .Op Fl t Ar target-pane
.Xc .Xc
.D1 (alias: Ic pasteb ) .D1 (alias: Ic pasteb )
@ -2396,10 +2397,13 @@ With
.Fl d , .Fl d ,
also delete the paste buffer from the stack. also delete the paste buffer from the stack.
When output, any linefeed (LF) characters in the paste buffer are replaced with When output, any linefeed (LF) characters in the paste buffer are replaced with
carriage returns (CR). a separator, by default carriage return (CR).
This translation may be disabled with the A custom separator may be specified using the
.Fl r .Fl s
flag. flag.
The
.Fl r
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