mirror of
https://github.com/tmux/tmux.git
synced 2026-10-09 03:34:25 +00:00
Prepare collapsible OSC 133 output for review
Use the parent output-range implementation and preserve source rows and columns when output is folded or wrapped. Clear stale exit-status presence on repeated D markers. Apply the requested coding style and add regressions for folded output selections and prompt properties.
This commit is contained in:
70
input.c
70
input.c
@@ -3203,8 +3203,13 @@ input_osc_133_save_marker(struct window_pane *wp, struct screen *s)
|
||||
struct input_osc_133_ctx ctx = {0};
|
||||
u_int y;
|
||||
|
||||
if (wp == NULL || s != &wp->base || SCREEN_IS_ALTERNATE(s) ||
|
||||
(~wp->flags & PANE_CMDRUNNING))
|
||||
if (wp == NULL)
|
||||
return (ctx);
|
||||
if (s != &wp->base)
|
||||
return (ctx);
|
||||
if (SCREEN_IS_ALTERNATE(s))
|
||||
return (ctx);
|
||||
if (~wp->flags & PANE_CMDRUNNING)
|
||||
return (ctx);
|
||||
ctx.running = 1;
|
||||
ctx.start = UINT_MAX;
|
||||
@@ -3218,12 +3223,14 @@ input_osc_133_save_marker(struct window_pane *wp, struct screen *s)
|
||||
continue;
|
||||
}
|
||||
od = &gl->osc133_data;
|
||||
if ((gl->flags & GRID_LINE_END_OUTPUT) &&
|
||||
od->out_end_col >= od->out_start_col)
|
||||
break;
|
||||
if ((gl->flags & GRID_LINE_START_PROMPT) &&
|
||||
od->prompt_col > od->out_start_col)
|
||||
break;
|
||||
if (gl->flags & GRID_LINE_END_OUTPUT) {
|
||||
if (od->out_end_col >= od->out_start_col)
|
||||
break;
|
||||
}
|
||||
if (gl->flags & GRID_LINE_START_PROMPT) {
|
||||
if (od->prompt_col > od->out_start_col)
|
||||
break;
|
||||
}
|
||||
ctx.start = y - 1;
|
||||
ctx.col = od->out_start_col;
|
||||
break;
|
||||
@@ -3243,11 +3250,14 @@ input_osc_133_restore_marker(struct screen *s,
|
||||
if (!ctx->running)
|
||||
return;
|
||||
collected = gd->scroll_collected - ctx->collected;
|
||||
if (ctx->start != UINT_MAX && ctx->start >= collected) {
|
||||
gl = grid_get_line(gd, ctx->start - collected);
|
||||
if ((gl->flags & GRID_LINE_START_OUTPUT) &&
|
||||
gl->osc133_data.out_start_col == ctx->col)
|
||||
return;
|
||||
if (ctx->start != UINT_MAX) {
|
||||
if (ctx->start >= collected) {
|
||||
gl = grid_get_line(gd, ctx->start - collected);
|
||||
if (gl->flags & GRID_LINE_START_OUTPUT) {
|
||||
if (gl->osc133_data.out_start_col == ctx->col)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
gl = grid_get_line(gd, gd->hsize);
|
||||
gl->flags |= GRID_LINE_START_OUTPUT;
|
||||
@@ -3331,11 +3341,15 @@ input_osc_133_secondary_prompt(const char *p)
|
||||
const char *cp;
|
||||
|
||||
while ((cp = strstr(p, ";k=")) != NULL) {
|
||||
cp += 3;
|
||||
if ((*cp == 's' || *cp == 'c') &&
|
||||
(cp[1] == '\0' || cp[1] == ';'))
|
||||
p = cp + 3;
|
||||
if (*p != 's') {
|
||||
if (*p != 'c')
|
||||
continue;
|
||||
}
|
||||
if (p[1] == '\0')
|
||||
return (1);
|
||||
if (p[1] == ';')
|
||||
return (1);
|
||||
p = cp;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
@@ -3344,8 +3358,9 @@ input_osc_133_secondary_prompt(const char *p)
|
||||
static void
|
||||
input_osc_133_mark_prompt(struct grid_line *gl, u_int col, const char *p)
|
||||
{
|
||||
if (gl == NULL || gl->flags &
|
||||
(GRID_LINE_START_PROMPT|GRID_LINE_SECOND_PROMPT))
|
||||
if (gl == NULL)
|
||||
return;
|
||||
if (gl->flags & (GRID_LINE_START_PROMPT|GRID_LINE_SECOND_PROMPT))
|
||||
return;
|
||||
gl->osc133_data.prompt_col = col;
|
||||
if (input_osc_133_secondary_prompt(p))
|
||||
@@ -3382,15 +3397,19 @@ input_osc_133(struct input_ctx *ictx, const char *p)
|
||||
break;
|
||||
case 'B':
|
||||
case 'I':
|
||||
if (gl != NULL && !(gl->flags & GRID_LINE_START_COMMAND)) {
|
||||
gl->flags |= GRID_LINE_START_COMMAND;
|
||||
gl->osc133_data.cmd_col = s->cx;
|
||||
if (gl != NULL) {
|
||||
if (~gl->flags & GRID_LINE_START_COMMAND) {
|
||||
gl->flags |= GRID_LINE_START_COMMAND;
|
||||
gl->osc133_data.cmd_col = s->cx;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'C':
|
||||
if (gl != NULL && !(gl->flags & GRID_LINE_START_OUTPUT)) {
|
||||
gl->flags |= GRID_LINE_START_OUTPUT;
|
||||
gl->osc133_data.out_start_col = s->cx;
|
||||
if (gl != NULL) {
|
||||
if (~gl->flags & GRID_LINE_START_OUTPUT) {
|
||||
gl->flags |= GRID_LINE_START_OUTPUT;
|
||||
gl->osc133_data.out_start_col = s->cx;
|
||||
}
|
||||
}
|
||||
if (wp != NULL) {
|
||||
wp->cmd_start_time = time(NULL);
|
||||
@@ -3410,6 +3429,7 @@ input_osc_133(struct input_ctx *ictx, const char *p)
|
||||
}
|
||||
if (gl != NULL) {
|
||||
gl->flags |= GRID_LINE_END_OUTPUT;
|
||||
gl->flags &= ~GRID_LINE_END_OUTPUT_STATUS;
|
||||
if (status_present)
|
||||
gl->flags |= GRID_LINE_END_OUTPUT_STATUS;
|
||||
gl->osc133_data.out_end_col = s->cx;
|
||||
|
||||
64
regress/collapse-output-copy.sh
Normal file
64
regress/collapse-output-copy.sh
Normal file
@@ -0,0 +1,64 @@
|
||||
#!/bin/sh
|
||||
|
||||
PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -LtestA$$ -f/dev/null"
|
||||
|
||||
$TMUX kill-server 2>/dev/null
|
||||
trap '$TMUX kill-server 2>/dev/null' 0
|
||||
trap 'exit 1' 1 2 3 15
|
||||
|
||||
$TMUX new-session -d -x20 -y10 \
|
||||
"printf '\033]133;A\007P0> \033]133;B\007first\r\n\033]133;C\007FIRST-OUTPUT\r\n\033]133;D;0\007\033]133;A\007P1> \033]133;B\007second\r\n\033]133;C\007012345678901234567890123456789\r\nlast\r\n\033]133;D;7\007\033]133;A\007P2> \033]133;B\007'; exec sleep 100" || exit 1
|
||||
sleep 1
|
||||
|
||||
expected=$(printf '012345678901234567890123456789\nlast')
|
||||
for keys in emacs vi; do
|
||||
$TMUX set -g mode-keys "$keys" || exit 1
|
||||
$TMUX copy-mode -c || exit 1
|
||||
$TMUX send -X search-backward-text second || exit 1
|
||||
$TMUX set-buffer sentinel || exit 1
|
||||
$TMUX send -X copy-output || exit 1
|
||||
[ "$($TMUX show-buffer)" = "$expected" ] || exit 1
|
||||
|
||||
$TMUX send -X select-output || exit 1
|
||||
[ "$($TMUX display -p '#{selection_present}')" = 1 ] || exit 1
|
||||
$TMUX send -X copy-selection || exit 1
|
||||
[ "$($TMUX show-buffer)" = "$expected" ] || exit 1
|
||||
case "$($TMUX capture-pane -Mp)" in
|
||||
*FIRST-OUTPUT*) exit 1 ;;
|
||||
esac
|
||||
|
||||
# All-output commands include the original source, even while folded.
|
||||
$TMUX send -X copy-output -a || exit 1
|
||||
all=$($TMUX show-buffer)
|
||||
case "$all" in
|
||||
*FIRST-OUTPUT*012345678901234567890123456789*last*) ;;
|
||||
*) exit 1 ;;
|
||||
esac
|
||||
$TMUX send -X select-output -a || exit 1
|
||||
$TMUX send -X copy-selection || exit 1
|
||||
[ "$($TMUX show-buffer)" = "$all" ] || exit 1
|
||||
$TMUX send -X cancel || exit 1
|
||||
done
|
||||
|
||||
# A prompt after an output end on the same source line moves left when folded.
|
||||
$TMUX new-window -n shared \
|
||||
"printf '\033]133;A\007P0> \033]133;B\007first\r\n\033]133;C\007head\r\ntail\033]133;D;0\007\033]133;A\007P1> \033]133;B\007second\r\n\033]133;C\007SECOND-OUTPUT\r\n\033]133;D;0\007\033]133;A\007P2> \033]133;B\007'; exec sleep 100" || exit 1
|
||||
sleep 1
|
||||
for keys in emacs vi; do
|
||||
$TMUX set -g mode-keys "$keys" || exit 1
|
||||
$TMUX copy-mode -c || exit 1
|
||||
$TMUX send -X search-backward-text P1 || exit 1
|
||||
$TMUX send -X start-of-line || exit 1
|
||||
$TMUX send -X copy-output || exit 1
|
||||
[ "$($TMUX show-buffer)" = SECOND-OUTPUT ] || exit 1
|
||||
$TMUX send -X select-output || exit 1
|
||||
$TMUX send -X copy-selection || exit 1
|
||||
[ "$($TMUX show-buffer)" = SECOND-OUTPUT ] || exit 1
|
||||
$TMUX send -X cancel || exit 1
|
||||
done
|
||||
|
||||
exit 0
|
||||
@@ -37,5 +37,20 @@ check_raw_matches osc133-status \
|
||||
'L 4 \(4\) flags=START_OUTPUT,END_OUTPUT\[[0-9a-f]+\].* osc133=0,0,0,1,0' \
|
||||
'L 5 \(5\) flags=START_OUTPUT,END_OUTPUT\[[0-9a-f]+\].* osc133=0,0,0,1,0'
|
||||
|
||||
# A later D without a status must clear the earlier status-present flag.
|
||||
start_pane osc133-repeated-status 20 3 \
|
||||
'\033]133;C\007out\033]133;D;7\007\033]133;D\007\n'
|
||||
check_raw_matches osc133-repeated-status \
|
||||
'L 0 \(0\) flags=START_OUTPUT,END_OUTPUT\[[0-9a-f]+\].* osc133=0,0,0,3,0'
|
||||
|
||||
# Prompt properties may repeat or appear in any order; values must end.
|
||||
start_pane osc133-properties 20 6 \
|
||||
'\033]133;A;foo=bar;k=s;id=1\007secondary\n\033]133;P;k=x;foo=bar;k=c\007continuation\n\033]133;A;k=second\007primary\n\033]133;P;k=continued\007primary\n'
|
||||
check_raw_matches osc133-properties \
|
||||
'L 0 \(0\) flags=SECOND_PROMPT\[[0-9a-f]+\].* osc133=0,0,0,0,0' \
|
||||
'L 1 \(1\) flags=SECOND_PROMPT\[[0-9a-f]+\].* osc133=0,0,0,0,0' \
|
||||
'L 2 \(2\) flags=START_PROMPT\[[0-9a-f]+\].* osc133=0,0,0,0,0' \
|
||||
'L 3 \(3\) flags=START_PROMPT\[[0-9a-f]+\].* osc133=0,0,0,0,0'
|
||||
|
||||
$TMUX kill-server 2>/dev/null
|
||||
exit $exit_status
|
||||
|
||||
@@ -2084,8 +2084,10 @@ screen_write_clearendofscreen(struct screen_write_ctx *ctx, u_int bg)
|
||||
ttyctx.bg = bg;
|
||||
|
||||
/* Erasing to the end clears the whole screen at 0,0. */
|
||||
if (s->cx == 0 && s->cy == 0)
|
||||
osc133 = input_osc_133_save_marker(ctx->owner, s);
|
||||
if (s->cx == 0) {
|
||||
if (s->cy == 0)
|
||||
osc133 = input_osc_133_save_marker(ctx->owner, s);
|
||||
}
|
||||
|
||||
/* Scroll into history if it is enabled and clearing entire screen. */
|
||||
if (s->cx == 0 &&
|
||||
|
||||
1
tmux.1
1
tmux.1
@@ -2224,6 +2224,7 @@ With
|
||||
toggle all command output in the copy-mode buffer.
|
||||
The Tab key toggles output for the command on the cursor line and S-Tab
|
||||
toggles all command output.
|
||||
Clicking the line-number or output-control area toggles the command on that line.
|
||||
.It Xo
|
||||
.Ic fold\-view\-toggle
|
||||
(vi: O)
|
||||
|
||||
858
window-copy.c
858
window-copy.c
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user