Add a -T flag to capture-pane to stop at the last used cell instead of

the full width. Restore the previous behaviour by making it default to
off unless -J is used (the only time it matters). Fixes mosh unit tests;
GitHub issue 3339.
This commit is contained in:
nicm 2022-09-28 07:55:29 +00:00
parent a2cc601c3d
commit 9cc8e40aa0
4 changed files with 70 additions and 47 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.h
View File

@ -667,6 +667,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
@ -681,6 +689,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 " "
@ -2783,7 +2792,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);