Sync OpenBSD patchset 702:

Enhance paste-buffer to allow lines to be separated by any string, from
Andrea Barisani.
This commit is contained in:
Tiago Cunha 2010-06-06 00:01:36 +00:00
parent 11cd05db27
commit e55a59eebc
2 changed files with 157 additions and 28 deletions

View File

@ -1,4 +1,4 @@
/* $Id: cmd-paste-buffer.c,v 1.26 2010-04-06 21:59:37 nicm Exp $ */ /* $Id: cmd-paste-buffer.c,v 1.27 2010-06-06 00:01:36 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -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,24 +28,106 @@
* 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;
@ -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);
}

14
tmux.1
View File

@ -1,4 +1,4 @@
.\" $Id: tmux.1,v 1.251 2010-06-05 23:56:29 tcunha Exp $ .\" $Id: tmux.1,v 1.252 2010-06-06 00:01:36 tcunha Exp $
.\" .\"
.\" Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> .\" Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
.\" .\"
@ -14,7 +14,7 @@
.\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING .\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
.\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\" .\"
.Dd $Mdocdate: May 14 2010 $ .Dd $Mdocdate: May 19 2010 $
.Dt TMUX 1 .Dt TMUX 1
.Os .Os
.Sh NAME .Sh NAME
@ -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