aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Adam <thomas@xteddy.org>2022-09-28 12:01:09 +0100
committerThomas Adam <thomas@xteddy.org>2022-09-28 12:01:09 +0100
commit9ef854f5a9112a7d50c382dec403432dea2c3579 (patch)
treeb51a7cd48950393ce38a6f4b66c59d348d918a3c
parentf49f92737f859bfeac901f0eb9b1db8249368843 (diff)
parenta10452be2d84d4ff1b9d4e636627b7a9c5a2c42a (diff)
downloadrtmux-9ef854f5a9112a7d50c382dec403432dea2c3579.tar.gz
rtmux-9ef854f5a9112a7d50c382dec403432dea2c3579.tar.bz2
rtmux-9ef854f5a9112a7d50c382dec403432dea2c3579.zip
Merge branch 'obsd-master'
-rw-r--r--cmd-capture-pane.c18
-rw-r--r--grid-view.c2
-rw-r--r--grid.c88
-rw-r--r--tmux.111
-rw-r--r--tmux.h11
-rw-r--r--window-copy.c56
6 files changed, 130 insertions, 56 deletions
diff --git a/cmd-capture-pane.c b/cmd-capture-pane.c
index 422f87d6..57e9716d 100644
--- a/cmd-capture-pane.c
+++ b/cmd-capture-pane.c
@@ -40,7 +40,7 @@ const struct cmd_entry cmd_capture_pane_entry = {
.alias = "capturep",
.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,
.target = { 't', CMD_FIND_PANE, 0 },
@@ -110,7 +110,7 @@ cmd_capture_pane_history(struct args *args, struct cmdq_item *item,
struct grid *gd;
const struct grid_line *gl;
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;
char *cause, *buf, *line;
const char *Sflag, *Eflag;
@@ -169,15 +169,19 @@ cmd_capture_pane_history(struct args *args, struct cmdq_item *item,
top = tmp;
}
- with_codes = args_has(args, 'e');
- escape_c0 = args_has(args, 'C');
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;
for (i = top; i <= bottom; i++) {
- line = grid_string_cells(gd, 0, i, sx, &gc, with_codes,
- escape_c0, !join_lines && !no_trim, wp->screen);
+ line = grid_string_cells(gd, 0, i, sx, &gc, flags, wp->screen);
linelen = strlen(line);
buf = cmd_capture_pane_append(buf, len, line, linelen);
diff --git a/grid-view.c b/grid-view.c
index 689ac4e4..4d687339 100644
--- a/grid-view.c
+++ b/grid-view.c
@@ -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);
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));
}
diff --git a/grid.c b/grid.c
index b1afd398..58de03a3 100644
--- a/grid.c
+++ b/grid.c
@@ -861,40 +861,45 @@ grid_string_cells_us(const struct grid_cell *gc, int *values)
/* Add on SGR code. */
static void
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;
char tmp[64];
-
- if (nnewc != 0 &&
- (nnewc != noldc ||
- memcmp(newc, oldc, nnewc * sizeof newc[0]) != 0 ||
- (n != 0 && s[0] == 0))) {
- if (escape_c0)
- strlcat(buf, "\\033[", len);
+ int reset = (n != 0 && s[0] == 0);
+
+ if (nnewc == 0)
+ return; /* no code to add */
+ if (!reset &&
+ nnewc == noldc &&
+ memcmp(newc, oldc, nnewc * sizeof newc[0]) == 0)
+ 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
- strlcat(buf, "\033[", len);
- for (i = 0; i < nnewc; i++) {
- 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);
+ xsnprintf(tmp, sizeof tmp, "%d", newc[i]);
+ strlcat(buf, tmp, len);
}
+ strlcat(buf, "m", len);
}
static int
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;
if (strlen(uri) + strlen(id) + 17 >= len)
return (0);
- if (escape_c0)
+ if (flags & GRID_STRING_ESCAPE_SEQUENCES)
strlcat(buf, "\\033]8;", len);
else
strlcat(buf, "\033]8;", len);
@@ -905,7 +910,7 @@ grid_string_cells_add_hyperlink(char *buf, size_t len, const char *id,
} else
strlcat(buf, ";", len);
strlcat(buf, uri, len);
- if (escape_c0)
+ if (flags & GRID_STRING_ESCAPE_SEQUENCES)
strlcat(buf, "\\033\\\\", len);
else
strlcat(buf, "\033\\", len);
@@ -918,7 +923,7 @@ grid_string_cells_add_hyperlink(char *buf, size_t len, const char *id,
*/
static void
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)
{
int oldc[64], newc[64], s[128];
@@ -927,7 +932,7 @@ grid_string_cells_code(const struct grid_cell *lastgc,
char tmp[64];
const char *uri, *id;
- struct {
+ static const struct {
u_int mask;
u_int code;
} attrs[] = {
@@ -966,7 +971,7 @@ grid_string_cells_code(const struct grid_cell *lastgc,
/* Write the attributes. */
*buf = '\0';
if (n > 0) {
- if (escape_c0)
+ if (flags & GRID_STRING_ESCAPE_SEQUENCES)
strlcat(buf, "\\033[", len);
else
strlcat(buf, "\033[", len);
@@ -988,29 +993,29 @@ grid_string_cells_code(const struct grid_cell *lastgc,
nnewc = grid_string_cells_fg(gc, newc);
noldc = grid_string_cells_fg(lastgc, oldc);
grid_string_cells_add_code(buf, len, n, s, newc, oldc, nnewc, noldc,
- escape_c0);
+ flags);
/* If the background colour changed, append its parameters. */
nnewc = grid_string_cells_bg(gc, newc);
noldc = grid_string_cells_bg(lastgc, oldc);
grid_string_cells_add_code(buf, len, n, s, newc, oldc, nnewc, noldc,
- escape_c0);
+ flags);
/* If the underscore colour changed, append its parameters. */
nnewc = grid_string_cells_us(gc, newc);
noldc = grid_string_cells_us(lastgc, oldc);
grid_string_cells_add_code(buf, len, n, s, newc, oldc, nnewc, noldc,
- escape_c0);
+ flags);
/* Append shift in/shift out if needed. */
if ((attr & GRID_ATTR_CHARSET) && !(lastattr & GRID_ATTR_CHARSET)) {
- if (escape_c0)
+ if (flags & GRID_STRING_ESCAPE_SEQUENCES)
strlcat(buf, "\\016", len); /* SO */
else
strlcat(buf, "\016", len); /* SO */
}
if (!(attr & GRID_ATTR_CHARSET) && (lastattr & GRID_ATTR_CHARSET)) {
- if (escape_c0)
+ if (flags & GRID_STRING_ESCAPE_SEQUENCES)
strlcat(buf, "\\017", len); /* SI */
else
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 (hyperlinks_get(sc->hyperlinks, gc->link, &uri, &id, NULL)) {
*has_link = grid_string_cells_add_hyperlink(buf, len,
- id, uri, escape_c0);
+ id, uri, flags);
} else if (*has_link) {
grid_string_cells_add_hyperlink(buf, len, "", "",
- escape_c0);
+ flags);
*has_link = 0;
}
}
@@ -1032,15 +1037,14 @@ grid_string_cells_code(const struct grid_cell *lastgc,
/* Convert cells into a string. */
char *
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 screen *s)
+ struct grid_cell **lastgc, int flags, struct screen *s)
{
struct grid_cell gc;
static struct grid_cell lastgc1;
const char *data;
char *buf, code[8192];
size_t len, off, size, codelen;
- u_int xx, has_link = 0;
+ u_int xx, has_link = 0, end;
const struct grid_line *gl;
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;
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++) {
- if (gl == NULL || xx >= gl->cellused)
+ if (gl == NULL || xx >= end)
break;
grid_get_cell(gd, xx, py, &gc);
if (gc.flags & GRID_FLAG_PADDING)
continue;
- if (with_codes) {
+ if (flags & GRID_STRING_WITH_SEQUENCES) {
grid_string_cells_code(*lastgc, &gc, code, sizeof code,
- escape_c0, s, &has_link);
+ flags, s, &has_link);
codelen = strlen(code);
memcpy(*lastgc, &gc, sizeof **lastgc);
} else
@@ -1070,7 +1078,9 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx,
data = gc.data.data;
size = gc.data.size;
- if (escape_c0 && size == 1 && *data == '\\') {
+ if ((flags & GRID_STRING_ESCAPE_SEQUENCES) &&
+ size == 1 &&
+ *data == '\\') {
data = "\\\\";
size = 2;
}
@@ -1090,7 +1100,7 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx,
if (has_link) {
grid_string_cells_add_hyperlink(code, sizeof code, "", "",
- escape_c0);
+ flags);
codelen = strlen(code);
while (len < off + size + codelen + 1) {
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;
}
- if (trim) {
+ if (flags & GRID_STRING_TRIM_SPACES) {
while (off > 0 && buf[off - 1] == ' ')
off--;
}
diff --git a/tmux.1 b/tmux.1
index 6e880720..678fb1d1 100644
--- a/tmux.1
+++ b/tmux.1
@@ -1811,7 +1811,9 @@ The following commands are supported in copy mode:
.It Li "search-forward <for>" Ta "/" Ta ""
.It Li "search-forward-incremental <for>" Ta "" Ta "C-s"
.It Li "search-forward-text <for>" Ta "" Ta ""
+.It Li "scroll-bottom" Ta "" Ta ""
.It Li "scroll-middle" Ta "z" Ta ""
+.It Li "scroll-top" Ta "" Ta ""
.It Li "search-reverse" Ta "N" Ta "N"
.It Li "select-line" Ta "V" Ta ""
.It Li "select-word" Ta "" Ta ""
@@ -2014,7 +2016,7 @@ but a different format may be specified with
.Fl F .
.Tg capturep
.It Xo Ic capture-pane
-.Op Fl aepPqCJN
+.Op Fl aAepPqCJN
.Op Fl b Ar buffer-name
.Op Fl E Ar end-line
.Op Fl S Ar start-line
@@ -2039,10 +2041,15 @@ is given, the output includes escape sequences for text and background
attributes.
.Fl C
also escapes non-printable characters as octal \exxx.
+.Fl T
+ignores trailing positions that do not contain a character.
.Fl N
preserves trailing spaces at each line's end and
.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
captures only any output that the pane has received that is the beginning of an
as-yet incomplete escape sequence.
diff --git a/tmux.h b/tmux.h
index 61eb95d4..2e86e9d4 100644
--- a/tmux.h
+++ b/tmux.h
@@ -668,6 +668,14 @@ struct colour_palette {
#define GRID_LINE_EXTENDED 0x2
#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_TOPBOTTOM 1
#define CELL_LEFTRIGHT 2
@@ -682,6 +690,7 @@ struct colour_palette {
#define CELL_JOIN 11
#define CELL_OUTSIDE 12
+/* Cell borders. */
#define CELL_BORDERS " xqlkmjwvtun~"
#define SIMPLE_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_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,
- 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,
u_int);
void grid_reflow(struct grid *, u_int);
diff --git a/window-copy.c b/window-copy.c
index 743364d6..ed481d70 100644
--- a/window-copy.c
+++ b/window-copy.c
@@ -1250,20 +1250,23 @@ window_copy_cmd_cursor_right(struct window_copy_cmd_state *cs)
return (WINDOW_COPY_CMD_NOTHING);
}
+/* Scroll line containing the cursor to the given position. */
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_copy_mode_data *data = wme->data;
- u_int mid_value, oy, delta;
+ u_int oy, delta;
int scroll_up; /* >0 up, <0 down */
- mid_value = (screen_size_y(&data->screen) - 1) / 2;
- scroll_up = data->cy - mid_value;
+ scroll_up = data->cy - to;
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) {
window_copy_scroll_up(wme, delta);
data->cy -= delta;
@@ -1276,6 +1279,35 @@ window_copy_cmd_scroll_middle(struct window_copy_cmd_state *cs)
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
window_copy_cmd_cursor_up(struct window_copy_cmd_state *cs)
{
@@ -2794,6 +2826,12 @@ static const struct {
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
.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",
.minargs = 0,
.maxargs = 0,
@@ -2812,6 +2850,12 @@ static const struct {
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
.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",
.minargs = 0,
.maxargs = 0,