Merge branch 'obsd-master'

pull/3358/head
Thomas Adam 2022-09-28 12:01:09 +01:00
commit 9ef854f5a9
6 changed files with 129 additions and 55 deletions

View File

@ -40,7 +40,7 @@ const struct cmd_entry cmd_capture_pane_entry = {
.alias = "capturep", .alias = "capturep",
.args = { "ab:CeE:JNpPqS:t:", 0, 0, NULL }, .args = { "ab:CeE:JNpPqS:t:", 0, 0, NULL },
.usage = "[-aCeJNpPq] " CMD_BUFFER_USAGE " [-E end-line] " .usage = "[-aCeJNpPqT] " CMD_BUFFER_USAGE " [-E end-line] "
"[-S start-line] " CMD_TARGET_PANE_USAGE, "[-S start-line] " CMD_TARGET_PANE_USAGE,
.target = { 't', CMD_FIND_PANE, 0 }, .target = { 't', CMD_FIND_PANE, 0 },
@ -110,7 +110,7 @@ cmd_capture_pane_history(struct args *args, struct cmdq_item *item,
struct grid *gd; struct grid *gd;
const struct grid_line *gl; const struct grid_line *gl;
struct grid_cell *gc = NULL; struct grid_cell *gc = NULL;
int n, with_codes, escape_c0, join_lines, no_trim; int n, join_lines, flags = 0;
u_int i, sx, top, bottom, tmp; u_int i, sx, top, bottom, tmp;
char *cause, *buf, *line; char *cause, *buf, *line;
const char *Sflag, *Eflag; const char *Sflag, *Eflag;
@ -169,15 +169,19 @@ cmd_capture_pane_history(struct args *args, struct cmdq_item *item,
top = tmp; top = tmp;
} }
with_codes = args_has(args, 'e');
escape_c0 = args_has(args, 'C');
join_lines = args_has(args, 'J'); join_lines = args_has(args, 'J');
no_trim = args_has(args, 'N'); if (args_has(args, 'e'))
flags |= GRID_STRING_WITH_SEQUENCES;
if (args_has(args, 'C'))
flags |= GRID_STRING_ESCAPE_SEQUENCES;
if (!join_lines && !args_has(args, 'T'))
flags |= GRID_STRING_EMPTY_CELLS;
if (!join_lines && !args_has(args, 'N'))
flags |= GRID_STRING_TRIM_SPACES;
buf = NULL; buf = NULL;
for (i = top; i <= bottom; i++) { for (i = top; i <= bottom; i++) {
line = grid_string_cells(gd, 0, i, sx, &gc, with_codes, line = grid_string_cells(gd, 0, i, sx, &gc, flags, wp->screen);
escape_c0, !join_lines && !no_trim, wp->screen);
linelen = strlen(line); linelen = strlen(line);
buf = cmd_capture_pane_append(buf, len, line, linelen); buf = cmd_capture_pane_append(buf, len, line, linelen);

View File

@ -231,5 +231,5 @@ grid_view_string_cells(struct grid *gd, u_int px, u_int py, u_int nx)
px = grid_view_x(gd, px); px = grid_view_x(gd, px);
py = grid_view_y(gd, py); py = grid_view_y(gd, py);
return (grid_string_cells(gd, px, py, nx, NULL, 0, 0, 0, NULL)); return (grid_string_cells(gd, px, py, nx, NULL, 0, NULL));
} }

86
grid.c
View File

@ -861,40 +861,45 @@ grid_string_cells_us(const struct grid_cell *gc, int *values)
/* Add on SGR code. */ /* Add on SGR code. */
static void static void
grid_string_cells_add_code(char *buf, size_t len, u_int n, int *s, int *newc, grid_string_cells_add_code(char *buf, size_t len, u_int n, int *s, int *newc,
int *oldc, size_t nnewc, size_t noldc, int escape_c0) int *oldc, size_t nnewc, size_t noldc, int flags)
{ {
u_int i; u_int i;
char tmp[64]; char tmp[64];
int reset = (n != 0 && s[0] == 0);
if (nnewc != 0 && if (nnewc == 0)
(nnewc != noldc || return; /* no code to add */
memcmp(newc, oldc, nnewc * sizeof newc[0]) != 0 || if (!reset &&
(n != 0 && s[0] == 0))) { nnewc == noldc &&
if (escape_c0) memcmp(newc, oldc, nnewc * sizeof newc[0]) == 0)
strlcat(buf, "\\033[", len); return; /* no reset and colour unchanged */
if (reset && (newc[0] == 49 || newc[0] == 39))
return; /* reset and colour default */
if (flags & GRID_STRING_ESCAPE_SEQUENCES)
strlcat(buf, "\\033[", len);
else
strlcat(buf, "\033[", len);
for (i = 0; i < nnewc; i++) {
if (i + 1 < nnewc)
xsnprintf(tmp, sizeof tmp, "%d;", newc[i]);
else else
strlcat(buf, "\033[", len); xsnprintf(tmp, sizeof tmp, "%d", newc[i]);
for (i = 0; i < nnewc; i++) { strlcat(buf, tmp, len);
if (i + 1 < nnewc)
xsnprintf(tmp, sizeof tmp, "%d;", newc[i]);
else
xsnprintf(tmp, sizeof tmp, "%d", newc[i]);
strlcat(buf, tmp, len);
}
strlcat(buf, "m", len);
} }
strlcat(buf, "m", len);
} }
static int static int
grid_string_cells_add_hyperlink(char *buf, size_t len, const char *id, grid_string_cells_add_hyperlink(char *buf, size_t len, const char *id,
const char *uri, int escape_c0) const char *uri, int flags)
{ {
char *tmp; char *tmp;
if (strlen(uri) + strlen(id) + 17 >= len) if (strlen(uri) + strlen(id) + 17 >= len)
return (0); return (0);
if (escape_c0) if (flags & GRID_STRING_ESCAPE_SEQUENCES)
strlcat(buf, "\\033]8;", len); strlcat(buf, "\\033]8;", len);
else else
strlcat(buf, "\033]8;", len); strlcat(buf, "\033]8;", len);
@ -905,7 +910,7 @@ grid_string_cells_add_hyperlink(char *buf, size_t len, const char *id,
} else } else
strlcat(buf, ";", len); strlcat(buf, ";", len);
strlcat(buf, uri, len); strlcat(buf, uri, len);
if (escape_c0) if (flags & GRID_STRING_ESCAPE_SEQUENCES)
strlcat(buf, "\\033\\\\", len); strlcat(buf, "\\033\\\\", len);
else else
strlcat(buf, "\033\\", len); strlcat(buf, "\033\\", len);
@ -918,7 +923,7 @@ grid_string_cells_add_hyperlink(char *buf, size_t len, const char *id,
*/ */
static void static void
grid_string_cells_code(const struct grid_cell *lastgc, grid_string_cells_code(const struct grid_cell *lastgc,
const struct grid_cell *gc, char *buf, size_t len, int escape_c0, const struct grid_cell *gc, char *buf, size_t len, int flags,
struct screen *sc, int *has_link) struct screen *sc, int *has_link)
{ {
int oldc[64], newc[64], s[128]; int oldc[64], newc[64], s[128];
@ -927,7 +932,7 @@ grid_string_cells_code(const struct grid_cell *lastgc,
char tmp[64]; char tmp[64];
const char *uri, *id; const char *uri, *id;
struct { static const struct {
u_int mask; u_int mask;
u_int code; u_int code;
} attrs[] = { } attrs[] = {
@ -966,7 +971,7 @@ grid_string_cells_code(const struct grid_cell *lastgc,
/* Write the attributes. */ /* Write the attributes. */
*buf = '\0'; *buf = '\0';
if (n > 0) { if (n > 0) {
if (escape_c0) if (flags & GRID_STRING_ESCAPE_SEQUENCES)
strlcat(buf, "\\033[", len); strlcat(buf, "\\033[", len);
else else
strlcat(buf, "\033[", len); strlcat(buf, "\033[", len);
@ -988,29 +993,29 @@ grid_string_cells_code(const struct grid_cell *lastgc,
nnewc = grid_string_cells_fg(gc, newc); nnewc = grid_string_cells_fg(gc, newc);
noldc = grid_string_cells_fg(lastgc, oldc); noldc = grid_string_cells_fg(lastgc, oldc);
grid_string_cells_add_code(buf, len, n, s, newc, oldc, nnewc, noldc, grid_string_cells_add_code(buf, len, n, s, newc, oldc, nnewc, noldc,
escape_c0); flags);
/* If the background colour changed, append its parameters. */ /* If the background colour changed, append its parameters. */
nnewc = grid_string_cells_bg(gc, newc); nnewc = grid_string_cells_bg(gc, newc);
noldc = grid_string_cells_bg(lastgc, oldc); noldc = grid_string_cells_bg(lastgc, oldc);
grid_string_cells_add_code(buf, len, n, s, newc, oldc, nnewc, noldc, grid_string_cells_add_code(buf, len, n, s, newc, oldc, nnewc, noldc,
escape_c0); flags);
/* If the underscore colour changed, append its parameters. */ /* If the underscore colour changed, append its parameters. */
nnewc = grid_string_cells_us(gc, newc); nnewc = grid_string_cells_us(gc, newc);
noldc = grid_string_cells_us(lastgc, oldc); noldc = grid_string_cells_us(lastgc, oldc);
grid_string_cells_add_code(buf, len, n, s, newc, oldc, nnewc, noldc, grid_string_cells_add_code(buf, len, n, s, newc, oldc, nnewc, noldc,
escape_c0); flags);
/* Append shift in/shift out if needed. */ /* Append shift in/shift out if needed. */
if ((attr & GRID_ATTR_CHARSET) && !(lastattr & GRID_ATTR_CHARSET)) { if ((attr & GRID_ATTR_CHARSET) && !(lastattr & GRID_ATTR_CHARSET)) {
if (escape_c0) if (flags & GRID_STRING_ESCAPE_SEQUENCES)
strlcat(buf, "\\016", len); /* SO */ strlcat(buf, "\\016", len); /* SO */
else else
strlcat(buf, "\016", len); /* SO */ strlcat(buf, "\016", len); /* SO */
} }
if (!(attr & GRID_ATTR_CHARSET) && (lastattr & GRID_ATTR_CHARSET)) { if (!(attr & GRID_ATTR_CHARSET) && (lastattr & GRID_ATTR_CHARSET)) {
if (escape_c0) if (flags & GRID_STRING_ESCAPE_SEQUENCES)
strlcat(buf, "\\017", len); /* SI */ strlcat(buf, "\\017", len); /* SI */
else else
strlcat(buf, "\017", len); /* SI */ strlcat(buf, "\017", len); /* SI */
@ -1020,10 +1025,10 @@ grid_string_cells_code(const struct grid_cell *lastgc,
if (sc != NULL && sc->hyperlinks != NULL && lastgc->link != gc->link) { if (sc != NULL && sc->hyperlinks != NULL && lastgc->link != gc->link) {
if (hyperlinks_get(sc->hyperlinks, gc->link, &uri, &id, NULL)) { if (hyperlinks_get(sc->hyperlinks, gc->link, &uri, &id, NULL)) {
*has_link = grid_string_cells_add_hyperlink(buf, len, *has_link = grid_string_cells_add_hyperlink(buf, len,
id, uri, escape_c0); id, uri, flags);
} else if (*has_link) { } else if (*has_link) {
grid_string_cells_add_hyperlink(buf, len, "", "", grid_string_cells_add_hyperlink(buf, len, "", "",
escape_c0); flags);
*has_link = 0; *has_link = 0;
} }
} }
@ -1032,15 +1037,14 @@ grid_string_cells_code(const struct grid_cell *lastgc,
/* Convert cells into a string. */ /* Convert cells into a string. */
char * char *
grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx, grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx,
struct grid_cell **lastgc, int with_codes, int escape_c0, int trim, struct grid_cell **lastgc, int flags, struct screen *s)
struct screen *s)
{ {
struct grid_cell gc; struct grid_cell gc;
static struct grid_cell lastgc1; static struct grid_cell lastgc1;
const char *data; const char *data;
char *buf, code[8192]; char *buf, code[8192];
size_t len, off, size, codelen; size_t len, off, size, codelen;
u_int xx, has_link = 0; u_int xx, has_link = 0, end;
const struct grid_line *gl; const struct grid_line *gl;
if (lastgc != NULL && *lastgc == NULL) { if (lastgc != NULL && *lastgc == NULL) {
@ -1053,16 +1057,20 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx,
off = 0; off = 0;
gl = grid_peek_line(gd, py); gl = grid_peek_line(gd, py);
if (flags & GRID_STRING_EMPTY_CELLS)
end = gl->cellsize;
else
end = gl->cellused;
for (xx = px; xx < px + nx; xx++) { for (xx = px; xx < px + nx; xx++) {
if (gl == NULL || xx >= gl->cellused) if (gl == NULL || xx >= end)
break; break;
grid_get_cell(gd, xx, py, &gc); grid_get_cell(gd, xx, py, &gc);
if (gc.flags & GRID_FLAG_PADDING) if (gc.flags & GRID_FLAG_PADDING)
continue; continue;
if (with_codes) { if (flags & GRID_STRING_WITH_SEQUENCES) {
grid_string_cells_code(*lastgc, &gc, code, sizeof code, grid_string_cells_code(*lastgc, &gc, code, sizeof code,
escape_c0, s, &has_link); flags, s, &has_link);
codelen = strlen(code); codelen = strlen(code);
memcpy(*lastgc, &gc, sizeof **lastgc); memcpy(*lastgc, &gc, sizeof **lastgc);
} else } else
@ -1070,7 +1078,9 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx,
data = gc.data.data; data = gc.data.data;
size = gc.data.size; size = gc.data.size;
if (escape_c0 && size == 1 && *data == '\\') { if ((flags & GRID_STRING_ESCAPE_SEQUENCES) &&
size == 1 &&
*data == '\\') {
data = "\\\\"; data = "\\\\";
size = 2; size = 2;
} }
@ -1090,7 +1100,7 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx,
if (has_link) { if (has_link) {
grid_string_cells_add_hyperlink(code, sizeof code, "", "", grid_string_cells_add_hyperlink(code, sizeof code, "", "",
escape_c0); flags);
codelen = strlen(code); codelen = strlen(code);
while (len < off + size + codelen + 1) { while (len < off + size + codelen + 1) {
buf = xreallocarray(buf, 2, len); buf = xreallocarray(buf, 2, len);
@ -1100,7 +1110,7 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx,
off += codelen; off += codelen;
} }
if (trim) { if (flags & GRID_STRING_TRIM_SPACES) {
while (off > 0 && buf[off - 1] == ' ') while (off > 0 && buf[off - 1] == ' ')
off--; off--;
} }

11
tmux.1
View File

@ -1811,7 +1811,9 @@ The following commands are supported in copy mode:
.It Li "search-forward <for>" Ta "/" Ta "" .It Li "search-forward <for>" Ta "/" Ta ""
.It Li "search-forward-incremental <for>" Ta "" Ta "C-s" .It Li "search-forward-incremental <for>" Ta "" Ta "C-s"
.It Li "search-forward-text <for>" Ta "" Ta "" .It Li "search-forward-text <for>" Ta "" Ta ""
.It Li "scroll-bottom" Ta "" Ta ""
.It Li "scroll-middle" Ta "z" Ta "" .It Li "scroll-middle" Ta "z" Ta ""
.It Li "scroll-top" Ta "" Ta ""
.It Li "search-reverse" Ta "N" Ta "N" .It Li "search-reverse" Ta "N" Ta "N"
.It Li "select-line" Ta "V" Ta "" .It Li "select-line" Ta "V" Ta ""
.It Li "select-word" Ta "" Ta "" .It Li "select-word" Ta "" Ta ""
@ -2014,7 +2016,7 @@ but a different format may be specified with
.Fl F . .Fl F .
.Tg capturep .Tg capturep
.It Xo Ic capture-pane .It Xo Ic capture-pane
.Op Fl aepPqCJN .Op Fl aAepPqCJN
.Op Fl b Ar buffer-name .Op Fl b Ar buffer-name
.Op Fl E Ar end-line .Op Fl E Ar end-line
.Op Fl S Ar start-line .Op Fl S Ar start-line
@ -2039,10 +2041,15 @@ is given, the output includes escape sequences for text and background
attributes. attributes.
.Fl C .Fl C
also escapes non-printable characters as octal \exxx. also escapes non-printable characters as octal \exxx.
.Fl T
ignores trailing positions that do not contain a character.
.Fl N .Fl N
preserves trailing spaces at each line's end and preserves trailing spaces at each line's end and
.Fl J .Fl J
preserves trailing spaces and joins any wrapped lines. preserves trailing spaces and joins any wrapped lines;
.Fl J
implies
.Fl T .
.Fl P .Fl P
captures only any output that the pane has received that is the beginning of an captures only any output that the pane has received that is the beginning of an
as-yet incomplete escape sequence. as-yet incomplete escape sequence.

11
tmux.h
View File

@ -668,6 +668,14 @@ struct colour_palette {
#define GRID_LINE_EXTENDED 0x2 #define GRID_LINE_EXTENDED 0x2
#define GRID_LINE_DEAD 0x4 #define GRID_LINE_DEAD 0x4
/* Grid string flags. */
#define GRID_STRING_WITH_SEQUENCES 0x1
#define GRID_STRING_ESCAPE_SEQUENCES 0x2
#define GRID_STRING_TRIM_SPACES 0x4
#define GRID_STRING_USED_ONLY 0x8
#define GRID_STRING_EMPTY_CELLS 0x10
/* Cell positions. */
#define CELL_INSIDE 0 #define CELL_INSIDE 0
#define CELL_TOPBOTTOM 1 #define CELL_TOPBOTTOM 1
#define CELL_LEFTRIGHT 2 #define CELL_LEFTRIGHT 2
@ -682,6 +690,7 @@ struct colour_palette {
#define CELL_JOIN 11 #define CELL_JOIN 11
#define CELL_OUTSIDE 12 #define CELL_OUTSIDE 12
/* Cell borders. */
#define CELL_BORDERS " xqlkmjwvtun~" #define CELL_BORDERS " xqlkmjwvtun~"
#define SIMPLE_BORDERS " |-+++++++++." #define SIMPLE_BORDERS " |-+++++++++."
#define PADDED_BORDERS " " #define PADDED_BORDERS " "
@ -2785,7 +2794,7 @@ void grid_clear_lines(struct grid *, u_int, u_int, u_int);
void grid_move_lines(struct grid *, u_int, u_int, u_int, u_int); void grid_move_lines(struct grid *, u_int, u_int, u_int, u_int);
void grid_move_cells(struct grid *, u_int, u_int, u_int, u_int, u_int); void grid_move_cells(struct grid *, u_int, u_int, u_int, u_int, u_int);
char *grid_string_cells(struct grid *, u_int, u_int, u_int, char *grid_string_cells(struct grid *, u_int, u_int, u_int,
struct grid_cell **, int, int, int, struct screen *); struct grid_cell **, int, struct screen *);
void grid_duplicate_lines(struct grid *, u_int, struct grid *, u_int, void grid_duplicate_lines(struct grid *, u_int, struct grid *, u_int,
u_int); u_int);
void grid_reflow(struct grid *, u_int); void grid_reflow(struct grid *, u_int);

View File

@ -1250,20 +1250,23 @@ window_copy_cmd_cursor_right(struct window_copy_cmd_state *cs)
return (WINDOW_COPY_CMD_NOTHING); return (WINDOW_COPY_CMD_NOTHING);
} }
/* Scroll line containing the cursor to the given position. */
static enum window_copy_cmd_action static enum window_copy_cmd_action
window_copy_cmd_scroll_middle(struct window_copy_cmd_state *cs) window_copy_cmd_scroll_to(struct window_copy_cmd_state *cs, u_int to)
{ {
struct window_mode_entry *wme = cs->wme; struct window_mode_entry *wme = cs->wme;
struct window_copy_mode_data *data = wme->data; struct window_copy_mode_data *data = wme->data;
u_int mid_value, oy, delta; u_int oy, delta;
int scroll_up; /* >0 up, <0 down */ int scroll_up; /* >0 up, <0 down */
mid_value = (screen_size_y(&data->screen) - 1) / 2; scroll_up = data->cy - to;
scroll_up = data->cy - mid_value;
delta = abs(scroll_up); delta = abs(scroll_up);
oy = screen_hsize(data->backing) + data->cy - data->oy; oy = screen_hsize(data->backing) - data->oy;
log_debug ("XXX %u %u %u %d %u", mid_value, oy, delta, scroll_up, data->oy); /*
* oy is the maximum scroll down amount, while data->oy is the maximum
* scroll up amount.
*/
if (scroll_up > 0 && data->oy >= delta) { if (scroll_up > 0 && data->oy >= delta) {
window_copy_scroll_up(wme, delta); window_copy_scroll_up(wme, delta);
data->cy -= delta; data->cy -= delta;
@ -1276,6 +1279,35 @@ window_copy_cmd_scroll_middle(struct window_copy_cmd_state *cs)
return (WINDOW_COPY_CMD_REDRAW); return (WINDOW_COPY_CMD_REDRAW);
} }
/* Scroll line containing the cursor to the bottom. */
static enum window_copy_cmd_action
window_copy_cmd_scroll_bottom(struct window_copy_cmd_state *cs)
{
struct window_copy_mode_data *data = cs->wme->data;
u_int bottom;
bottom = screen_size_y(&data->screen) - 1;
return (window_copy_cmd_scroll_to(cs, bottom));
}
/* Scroll line containing the cursor to the middle. */
static enum window_copy_cmd_action
window_copy_cmd_scroll_middle(struct window_copy_cmd_state *cs)
{
struct window_copy_mode_data *data = cs->wme->data;
u_int mid_value;
mid_value = (screen_size_y(&data->screen) - 1) / 2;
return (window_copy_cmd_scroll_to(cs, mid_value));
}
/* Scroll line containing the cursor to the top. */
static enum window_copy_cmd_action
window_copy_cmd_scroll_top(struct window_copy_cmd_state *cs)
{
return (window_copy_cmd_scroll_to(cs, 0));
}
static enum window_copy_cmd_action static enum window_copy_cmd_action
window_copy_cmd_cursor_up(struct window_copy_cmd_state *cs) window_copy_cmd_cursor_up(struct window_copy_cmd_state *cs)
{ {
@ -2794,6 +2826,12 @@ static const struct {
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
.f = window_copy_cmd_refresh_from_pane .f = window_copy_cmd_refresh_from_pane
}, },
{ .command = "scroll-bottom",
.minargs = 0,
.maxargs = 0,
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
.f = window_copy_cmd_scroll_bottom
},
{ .command = "scroll-down", { .command = "scroll-down",
.minargs = 0, .minargs = 0,
.maxargs = 0, .maxargs = 0,
@ -2812,6 +2850,12 @@ static const struct {
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS, .clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
.f = window_copy_cmd_scroll_middle .f = window_copy_cmd_scroll_middle
}, },
{ .command = "scroll-top",
.minargs = 0,
.maxargs = 0,
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
.f = window_copy_cmd_scroll_top
},
{ .command = "scroll-up", { .command = "scroll-up",
.minargs = 0, .minargs = 0,
.maxargs = 0, .maxargs = 0,