mirror of
https://github.com/tmux/tmux.git
synced 2026-10-06 17:49:52 +00:00
Fix OSC 133 output range lookup for markers sharing a line
Handle C and D on the same line, output ending on the next prompt's line, and output starting on a prompt line. Keep the output columns when A resets a line's prompt data, and fall back to the previous output if the range is empty. Extend the regress test to cover these and reset the paste buffer before each check.
This commit is contained in:
2
input.c
2
input.c
@@ -3278,8 +3278,8 @@ input_osc_133(struct input_ctx *ictx, const char *p)
|
||||
case 'A':
|
||||
case 'N':
|
||||
if (gl != NULL) {
|
||||
memset(&gl->osc133_data, 0, sizeof gl->osc133_data);
|
||||
gl->osc133_data.prompt_col = s->cx;
|
||||
gl->osc133_data.cmd_col = 0;
|
||||
gl->flags |= GRID_LINE_START_PROMPT;
|
||||
}
|
||||
if (wp != NULL) {
|
||||
|
||||
@@ -20,6 +20,7 @@ $TMUX new-session -d -x80 -y20 "sh -c 'printf \"\\033]133;A\\007p\\$ \\033]133;B
|
||||
sleep 1
|
||||
|
||||
$TMUX copy-mode || exit 1
|
||||
$TMUX set-buffer sentinel || exit 1
|
||||
$TMUX send-keys -X copy-output || exit 1
|
||||
[ "$($TMUX show-buffer)" = unfinished ] || exit 1
|
||||
|
||||
@@ -33,6 +34,7 @@ sleep 1
|
||||
[ "$($TMUX show-buffer)" = unfinished ] || exit 1
|
||||
|
||||
$TMUX send-keys -X select-output || exit 1
|
||||
$TMUX set-buffer sentinel || exit 1
|
||||
$TMUX send-keys -X copy-selection || exit 1
|
||||
[ "$($TMUX show-buffer)" = unfinished ] || exit 1
|
||||
$TMUX send-keys -X cancel || exit 1
|
||||
@@ -46,12 +48,14 @@ $TMUX send-keys -X cancel || exit 1
|
||||
|
||||
$TMUX copy-mode || exit 1
|
||||
$TMUX send-keys -X search-backward separator || exit 1
|
||||
$TMUX set-buffer sentinel || exit 1
|
||||
$TMUX send-keys -X copy-output || exit 1
|
||||
[ "$($TMUX show-buffer)" = "$EXPECTED" ] || exit 1
|
||||
$TMUX send-keys -X cancel || exit 1
|
||||
|
||||
$TMUX copy-mode || exit 1
|
||||
$TMUX send-keys -X search-backward one || exit 1
|
||||
$TMUX set-buffer sentinel || exit 1
|
||||
$TMUX send-keys -X copy-output || exit 1
|
||||
[ "$($TMUX show-buffer)" = "$EXPECTED" ] || exit 1
|
||||
$TMUX send-keys -X cancel || exit 1
|
||||
@@ -59,6 +63,7 @@ $TMUX send-keys -X cancel || exit 1
|
||||
$TMUX new-window -d -n plain "printf 'alpha\\nbeta\\n'; exec sleep 100" || exit 1
|
||||
sleep 1
|
||||
$TMUX copy-mode -t :plain || exit 1
|
||||
$TMUX set-buffer sentinel || exit 1
|
||||
$TMUX send-keys -t :plain.0 -X copy-output -a || exit 1
|
||||
all=$($TMUX show-buffer)
|
||||
case "$all" in
|
||||
@@ -69,13 +74,15 @@ $TMUX send-keys -t :plain.0 -X cancel || exit 1
|
||||
|
||||
$TMUX set-buffer -b keep unchanged || exit 1
|
||||
$TMUX copy-mode -t :plain || exit 1
|
||||
$TMUX set-buffer sentinel || exit 1
|
||||
$TMUX send-keys -t :plain.0 -X copy-output || exit 1
|
||||
[ "$($TMUX show-buffer -b keep)" = unchanged ] || exit 1
|
||||
$TMUX send-keys -t :plain.0 -X cancel || exit 1
|
||||
|
||||
$TMUX new-window -d -n empty "printf '\\033]133;A\\007p\\$ \\033]133;B\\007echo\\033]133;C\\007one\\n\\033]133;D;0\\007\\033]133;A\\007p\\$ \\033]133;B\\007true\\033]133;C\\033]133;D;0\\007'; exec sleep 100" || exit 1
|
||||
$TMUX new-window -d -n empty "printf '\\033]133;A\\007p\\$ \\033]133;B\\007echo\\033]133;C\\007one\\n\\033]133;D;0\\007\\033]133;A\\007p\\$ \\033]133;B\\007true\\n\\033]133;C\\007\\033]133;D;0\\007'; exec sleep 100" || exit 1
|
||||
sleep 1
|
||||
$TMUX copy-mode -t :empty || exit 1
|
||||
$TMUX set-buffer sentinel || exit 1
|
||||
$TMUX send-keys -t :empty.0 -X copy-output || exit 1
|
||||
[ "$($TMUX show-buffer)" = one ] || exit 1
|
||||
$TMUX send-keys -t :empty.0 -X cancel || exit 1
|
||||
@@ -83,6 +90,7 @@ $TMUX send-keys -t :empty.0 -X cancel || exit 1
|
||||
$TMUX new-window -d -n prompt "printf '\\033]133;A\\007p\\$ \\033]133;B\\007echo\\033]133;C\\007one\\n\\033]133;D;0\\007\\033]133;A\\007p\\$ \\033]133;B\\007'; exec sleep 100" || exit 1
|
||||
sleep 1
|
||||
$TMUX copy-mode -t :prompt || exit 1
|
||||
$TMUX set-buffer sentinel || exit 1
|
||||
$TMUX send-keys -t :prompt.0 -X copy-output || exit 1
|
||||
[ "$($TMUX show-buffer)" = one ] || exit 1
|
||||
$TMUX send-keys -t :prompt.0 -X cancel || exit 1
|
||||
@@ -91,6 +99,7 @@ $TMUX copy-mode -t :prompt || exit 1
|
||||
$TMUX send-keys -t :prompt.0 -X -N 100 cursor-down || exit 1
|
||||
$TMUX send-keys -t :prompt.0 C-o || exit 1
|
||||
[ "$($TMUX display-message -p -t :prompt.0 '#{selection_present}')" = 1 ] || exit 1
|
||||
$TMUX set-buffer sentinel || exit 1
|
||||
$TMUX send-keys -t :prompt.0 -X copy-selection || exit 1
|
||||
[ "$($TMUX show-buffer)" = one ] || exit 1
|
||||
$TMUX send-keys -t :prompt.0 -X cancel || exit 1
|
||||
@@ -100,6 +109,7 @@ sleep 1
|
||||
$TMUX copy-mode -t :same || exit 1
|
||||
$TMUX send-keys -t :same.0 -X search-backward one || exit 1
|
||||
$TMUX send-keys -t :same.0 -X select-output || exit 1
|
||||
$TMUX set-buffer sentinel || exit 1
|
||||
$TMUX send-keys -t :same.0 -X copy-selection || exit 1
|
||||
[ "$($TMUX show-buffer)" = one ] || exit 1
|
||||
$TMUX send-keys -t :same.0 -X cancel || exit 1
|
||||
@@ -108,8 +118,41 @@ $TMUX new-window -d -n clear "printf 'old1\\nold2\\nold3\\nold4\\nold5\\nold6\\n
|
||||
sleep 1
|
||||
$TMUX copy-mode -t :clear || exit 1
|
||||
$TMUX send-keys -t :clear.0 C-o || exit 1
|
||||
$TMUX set-buffer sentinel || exit 1
|
||||
$TMUX send-keys -t :clear.0 -X copy-selection || exit 1
|
||||
[ "$($TMUX show-buffer)" = "$(printf 'PID TTY\n1 pts/0')" ] || exit 1
|
||||
[ "$($TMUX show-buffer)" = "$(printf '1\nPID TTY\n1 pts/0')" ] || exit 1
|
||||
$TMUX send-keys -t :clear.0 -X cancel || exit 1
|
||||
|
||||
$TMUX new-window -d -n oneline "printf '\\033]133;A\\007p\\$ \\033]133;B\\007echo\\n\\033]133;C\\007one\\033]133;D;0\\007\\nseparator\\n\\033]133;A\\007p\\$ \\033]133;B\\007'; exec sleep 100" || exit 1
|
||||
sleep 1
|
||||
$TMUX copy-mode -t :oneline || exit 1
|
||||
$TMUX send-keys -t :oneline.0 -X search-backward echo || exit 1
|
||||
$TMUX set-buffer sentinel || exit 1
|
||||
$TMUX send-keys -t :oneline.0 -X copy-output || exit 1
|
||||
[ "$($TMUX show-buffer)" = one ] || exit 1
|
||||
$TMUX send-keys -t :oneline.0 -X cancel || exit 1
|
||||
|
||||
$TMUX new-window -d -n nextprompt "printf '\\033]133;A\\007p\\$ \\033]133;B\\007echo\\n\\033]133;C\\007one\\ntwo\\033]133;D;0\\007\\033]133;A\\007p\\$ \\033]133;B\\007'; exec sleep 100" || exit 1
|
||||
sleep 1
|
||||
$TMUX copy-mode -t :nextprompt || exit 1
|
||||
$TMUX send-keys -t :nextprompt.0 -X search-backward echo || exit 1
|
||||
$TMUX set-buffer sentinel || exit 1
|
||||
$TMUX send-keys -t :nextprompt.0 -X copy-output || exit 1
|
||||
[ "$($TMUX show-buffer)" = "$EXPECTED" ] || exit 1
|
||||
$TMUX send-keys -t :nextprompt.0 -X cancel || exit 1
|
||||
|
||||
$TMUX new-window -d -n hist "printf '\\033]133;A\\007p\\$ \\033]133;B\\007seq\\n\\033]133;C\\007'; seq 1 40; sleep 3; seq 100 103; printf '\\033]133;D;0\\007\\033]133;A\\007p\\$ \\033]133;B\\007'; exec sleep 100" || exit 1
|
||||
sleep 1
|
||||
$TMUX clear-history -t :hist.0 || exit 1
|
||||
sleep 4
|
||||
$TMUX copy-mode -t :hist || exit 1
|
||||
$TMUX set-buffer sentinel || exit 1
|
||||
$TMUX send-keys -t :hist.0 -X copy-output || exit 1
|
||||
$TMUX show-buffer >$OUT
|
||||
[ "$(head -n1 "$OUT")" != sentinel ] || exit 1
|
||||
[ "$(head -n1 "$OUT")" != 1 ] || exit 1
|
||||
[ "$(tail -n1 "$OUT")" = 103 ] || exit 1
|
||||
grep -q seq "$OUT" && exit 1
|
||||
$TMUX send-keys -t :hist.0 -X cancel || exit 1
|
||||
|
||||
exit 0
|
||||
|
||||
@@ -6236,6 +6236,9 @@ window_copy_find_output_range(struct window_mode_entry *wme, u_int *sx,
|
||||
u_int cursor_x, cursor_y, prompt_x = 0;
|
||||
u_int prompt_y = UINT_MAX, y, total;
|
||||
int found_start = 0, found_end = 0;
|
||||
int next_prompt, in_range, found;
|
||||
void *buf;
|
||||
size_t len;
|
||||
|
||||
cursor_x = data->cx;
|
||||
cursor_y = screen_hsize(data->backing) + data->cy - data->oy;
|
||||
@@ -6260,27 +6263,38 @@ window_copy_find_output_range(struct window_mode_entry *wme, u_int *sx,
|
||||
|
||||
for (y = prompt_y; y < total; y++) {
|
||||
gl = grid_get_line(gd, y);
|
||||
/* An output may end on the next prompt's line. */
|
||||
next_prompt = (y != prompt_y &&
|
||||
gl->flags & GRID_LINE_START_PROMPT);
|
||||
/* Output before the next prompt on its line is ours. */
|
||||
if (y == prompt_y)
|
||||
in_range = (gl->osc133_data.out_start_col >= prompt_x);
|
||||
else if (next_prompt)
|
||||
in_range = (gl->osc133_data.out_start_col <
|
||||
gl->osc133_data.prompt_col);
|
||||
else
|
||||
in_range = 1;
|
||||
if (gl->flags & GRID_LINE_START_OUTPUT && in_range) {
|
||||
*sx = gl->osc133_data.out_start_col;
|
||||
*sy = y;
|
||||
found_start = 1;
|
||||
}
|
||||
/* An output may end on the same line or the next prompt's. */
|
||||
if (found_start && gl->flags & GRID_LINE_END_OUTPUT &&
|
||||
(y != prompt_y || gl->osc133_data.out_end_col >= prompt_x)) {
|
||||
(y != prompt_y || gl->osc133_data.out_end_col >= prompt_x) &&
|
||||
(y != *sy || gl->osc133_data.out_end_col >= *sx)) {
|
||||
*ex = gl->osc133_data.out_end_col;
|
||||
*ey = y;
|
||||
found_end = 1;
|
||||
break;
|
||||
}
|
||||
if (y != prompt_y && gl->flags & GRID_LINE_START_PROMPT)
|
||||
if (next_prompt)
|
||||
break;
|
||||
if (gl->flags & GRID_LINE_START_OUTPUT &&
|
||||
(y != prompt_y || gl->osc133_data.out_start_col >= prompt_x)) {
|
||||
*sx = gl->osc133_data.out_start_col;
|
||||
*sy = y;
|
||||
found_start = 1;
|
||||
}
|
||||
}
|
||||
if (!found_start) {
|
||||
log_debug("%s: no output after prompt", __func__);
|
||||
return (window_copy_find_previous_output_range(wme, cursor_x,
|
||||
cursor_y, sx, sy, ex, ey));
|
||||
found = window_copy_find_previous_output_range(wme, cursor_x,
|
||||
cursor_y, sx, sy, ex, ey);
|
||||
return (found);
|
||||
}
|
||||
if (!found_end) {
|
||||
if (y != total) {
|
||||
@@ -6289,6 +6303,14 @@ window_copy_find_output_range(struct window_mode_entry *wme, u_int *sx,
|
||||
}
|
||||
window_copy_output_end(data->backing, ex, ey);
|
||||
}
|
||||
buf = window_copy_get_grid_range(wme, *sx, *sy, *ex, *ey, &len);
|
||||
if (buf == NULL) {
|
||||
log_debug("%s: empty output", __func__);
|
||||
found = window_copy_find_previous_output_range(wme, cursor_x,
|
||||
cursor_y, sx, sy, ex, ey);
|
||||
return (found);
|
||||
}
|
||||
free(buf);
|
||||
log_debug("%s: output from %u,%u to %u,%u", __func__, *sx, *sy,
|
||||
*ex, *ey);
|
||||
return (1);
|
||||
@@ -6303,19 +6325,28 @@ window_copy_find_previous_output_range(struct window_mode_entry *wme,
|
||||
struct window_copy_mode_data *data = wme->data;
|
||||
struct grid *gd = data->backing->grid;
|
||||
struct grid_line *gl;
|
||||
struct osc133_data *od;
|
||||
void *buf;
|
||||
u_int start_x, start_y, end_x, end_y;
|
||||
u_int y, total;
|
||||
size_t len;
|
||||
int found = 0, have_prompt = 0;
|
||||
int pending = 0;
|
||||
int has_start, has_end, end_first;
|
||||
|
||||
total = gd->hsize + gd->sy;
|
||||
for (y = 0; y < total && y <= cursor_y; y++) {
|
||||
gl = grid_get_line(gd, y);
|
||||
if (gl->flags & GRID_LINE_START_OUTPUT &&
|
||||
(y != cursor_y || gl->osc133_data.out_start_col <= cursor_x)) {
|
||||
start_x = gl->osc133_data.out_start_col;
|
||||
od = &gl->osc133_data;
|
||||
has_start = (gl->flags & GRID_LINE_START_OUTPUT &&
|
||||
(y != cursor_y || od->out_start_col <= cursor_x));
|
||||
has_end = (gl->flags & GRID_LINE_END_OUTPUT &&
|
||||
(y != cursor_y || od->out_end_col <= cursor_x));
|
||||
/* An end before the start ends the previous output. */
|
||||
end_first = (has_start && has_end &&
|
||||
od->out_end_col < od->out_start_col);
|
||||
if (has_start && !end_first) {
|
||||
start_x = od->out_start_col;
|
||||
start_y = y;
|
||||
pending = 1;
|
||||
}
|
||||
@@ -6323,13 +6354,12 @@ window_copy_find_previous_output_range(struct window_mode_entry *wme,
|
||||
if (!pending && !have_prompt &&
|
||||
gl->flags & GRID_LINE_END_OUTPUT &&
|
||||
(~gl->flags & GRID_LINE_START_PROMPT ||
|
||||
gl->osc133_data.out_end_col <= gl->osc133_data.prompt_col)) {
|
||||
od->out_end_col <= od->prompt_col)) {
|
||||
start_x = start_y = 0;
|
||||
pending = 1;
|
||||
}
|
||||
if (pending && gl->flags & GRID_LINE_END_OUTPUT &&
|
||||
(y != cursor_y || gl->osc133_data.out_end_col <= cursor_x)) {
|
||||
end_x = gl->osc133_data.out_end_col;
|
||||
if (pending && has_end) {
|
||||
end_x = od->out_end_col;
|
||||
end_y = y;
|
||||
buf = window_copy_get_grid_range(wme, start_x, start_y,
|
||||
end_x, end_y, &len);
|
||||
@@ -6343,8 +6373,15 @@ window_copy_find_previous_output_range(struct window_mode_entry *wme,
|
||||
}
|
||||
pending = 0;
|
||||
}
|
||||
if (has_start && end_first) {
|
||||
start_x = od->out_start_col;
|
||||
start_y = y;
|
||||
pending = 1;
|
||||
}
|
||||
if (gl->flags & GRID_LINE_START_PROMPT) {
|
||||
pending = 0;
|
||||
/* Output may start after the prompt. */
|
||||
if (!has_start || od->out_start_col < od->prompt_col)
|
||||
pending = 0;
|
||||
have_prompt = 1;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user