mirror of
https://github.com/tmux/tmux.git
synced 2026-09-19 11:28:08 +00:00
Compare commits
34 Commits
3.8-rc
...
osc133_awa
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2ec4328380 | ||
|
|
8746405e34 | ||
|
|
8c0ac1fe05 | ||
|
|
dc65677ff9 | ||
|
|
2142818e25 | ||
|
|
cda0fe9f7b | ||
|
|
4cc9fc91fa | ||
|
|
081b79fd6e | ||
|
|
6294be4986 | ||
|
|
c5a5b99788 | ||
|
|
e23219ec04 | ||
|
|
0f29c47278 | ||
|
|
7c9fdcb770 | ||
|
|
0330d8ac57 | ||
|
|
0a7788b66f | ||
|
|
458d045bd2 | ||
|
|
a81154d6d9 | ||
|
|
cffc86dae5 | ||
|
|
4cfd155ffc | ||
|
|
670ea5d083 | ||
|
|
eaeb234dd4 | ||
|
|
5948722d5a | ||
|
|
d8ad7cd9c5 | ||
|
|
b49cc2d936 | ||
|
|
abb7108e25 | ||
|
|
d080378464 | ||
|
|
473eca949a | ||
|
|
f0eaa5e9d6 | ||
|
|
f44246c764 | ||
|
|
5d4d41da57 | ||
|
|
bacbb4d9d8 | ||
|
|
07a3a16ae7 | ||
|
|
f41288ee27 | ||
|
|
457b6cbefd |
@@ -30,8 +30,8 @@ const struct cmd_entry cmd_copy_mode_entry = {
|
||||
.name = "copy-mode",
|
||||
.alias = NULL,
|
||||
|
||||
.args = { "dekHMqSs:t:u", 0, 0, NULL },
|
||||
.usage = "[-dekHMqSu] [-s src-pane] " CMD_TARGET_PANE_USAGE,
|
||||
.args = { "UcdekHMqSs:t:u", 0, 0, NULL },
|
||||
.usage = "[-UcdekHMqSu] [-s src-pane] " CMD_TARGET_PANE_USAGE,
|
||||
|
||||
.source = { 's', CMD_FIND_PANE, 0 },
|
||||
.target = { 't', CMD_FIND_PANE, 0 },
|
||||
|
||||
2
grid.c
2
grid.c
@@ -1760,6 +1760,8 @@ grid_line_flags_string(int flags)
|
||||
strlcat(s, "START_OUTPUT,", sizeof s);
|
||||
if (flags & GRID_LINE_END_OUTPUT)
|
||||
strlcat(s, "END_OUTPUT,", sizeof s);
|
||||
if (flags & GRID_LINE_END_OUTPUT_STATUS)
|
||||
strlcat(s, "END_OUTPUT_STATUS,", sizeof s);
|
||||
if (flags & GRID_LINE_HYPERLINK)
|
||||
strlcat(s, "HYPERLINK,", sizeof s);
|
||||
if (*s == '\0')
|
||||
|
||||
74
input.c
74
input.c
@@ -3194,13 +3194,14 @@ input_osc_112(struct input_ctx *ictx, const char *p)
|
||||
|
||||
/* Parse the OSC 133 D exit status. */
|
||||
static int
|
||||
input_osc_133_exit_status(const char *p)
|
||||
input_osc_133_exit_status(const char *p, int *present)
|
||||
{
|
||||
const char *end;
|
||||
char *copy;
|
||||
const char *errstr;
|
||||
char *endptr;
|
||||
long long status;
|
||||
|
||||
*present = 0;
|
||||
if (p[1] != ';' || p[2] == '\0' || strchr(p + 2, '=') == p + 2)
|
||||
return (0);
|
||||
end = strchr(p + 2, ';');
|
||||
@@ -3214,9 +3215,11 @@ input_osc_133_exit_status(const char *p)
|
||||
free(copy);
|
||||
return (0);
|
||||
}
|
||||
status = strtonum(copy, 0, 255, &errstr);
|
||||
*present = 1;
|
||||
errno = 0;
|
||||
status = (int)strtol(copy, &endptr, 10);
|
||||
free(copy);
|
||||
if (errstr != NULL)
|
||||
if (errno != 0 || endptr == copy || status < 0 || status > 255)
|
||||
return (255);
|
||||
return (status);
|
||||
}
|
||||
@@ -3261,6 +3264,22 @@ input_fire_command_event(struct window_pane *wp, const char *name)
|
||||
events_fire(name, ep);
|
||||
}
|
||||
|
||||
/* Check if an OSC 133 prompt is secondary or a continuation. */
|
||||
static int
|
||||
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] == ';'))
|
||||
return (1);
|
||||
p = cp;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Handle the OSC 133 sequence. */
|
||||
static void
|
||||
input_osc_133(struct input_ctx *ictx, const char *p)
|
||||
@@ -3270,8 +3289,7 @@ input_osc_133(struct input_ctx *ictx, const char *p)
|
||||
struct grid *gd = s->grid;
|
||||
u_int line = s->cy + gd->hsize;
|
||||
struct grid_line *gl = NULL;
|
||||
const char *cp;
|
||||
int status;
|
||||
int status, status_present;
|
||||
|
||||
if (line < gd->hsize + gd->sy)
|
||||
gl = grid_get_line(gd, line);
|
||||
@@ -3280,9 +3298,17 @@ 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->flags |= GRID_LINE_START_PROMPT;
|
||||
if (!(gl->flags & (GRID_LINE_START_PROMPT|
|
||||
GRID_LINE_SECOND_PROMPT))) {
|
||||
gl->osc133_data.prompt_col = s->cx;
|
||||
if (input_osc_133_secondary_prompt(p))
|
||||
gl->flags |= GRID_LINE_SECOND_PROMPT;
|
||||
else
|
||||
gl->flags |= GRID_LINE_START_PROMPT;
|
||||
log_debug("%s: osc133 %s at %u,%u", __func__,
|
||||
input_osc_133_secondary_prompt(p) ? "secondary prompt" :
|
||||
"prompt", s->cx, line);
|
||||
}
|
||||
}
|
||||
if (wp != NULL) {
|
||||
wp->last_prompt_time = time(NULL);
|
||||
@@ -3291,25 +3317,33 @@ input_osc_133(struct input_ctx *ictx, const char *p)
|
||||
break;
|
||||
case 'P':
|
||||
if (gl != NULL) {
|
||||
cp = strstr(p, ";k=s");
|
||||
if (cp != NULL && (cp[4] == ';' || cp[4] == '\0'))
|
||||
gl->flags |= GRID_LINE_SECOND_PROMPT;
|
||||
else
|
||||
gl->flags |= GRID_LINE_START_PROMPT;
|
||||
gl->osc133_data.prompt_col = s->cx;
|
||||
if (!(gl->flags & (GRID_LINE_START_PROMPT|
|
||||
GRID_LINE_SECOND_PROMPT))) {
|
||||
gl->osc133_data.prompt_col = s->cx;
|
||||
if (input_osc_133_secondary_prompt(p))
|
||||
gl->flags |= GRID_LINE_SECOND_PROMPT;
|
||||
else
|
||||
gl->flags |= GRID_LINE_START_PROMPT;
|
||||
log_debug("%s: osc133 prompt at %u,%u", __func__, s->cx,
|
||||
line);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'B':
|
||||
case 'I':
|
||||
if (gl != NULL) {
|
||||
if (gl != NULL && !(gl->flags & GRID_LINE_START_COMMAND)) {
|
||||
gl->flags |= GRID_LINE_START_COMMAND;
|
||||
gl->osc133_data.cmd_col = s->cx;
|
||||
log_debug("%s: osc133 command at %u,%u", __func__, s->cx,
|
||||
line);
|
||||
}
|
||||
break;
|
||||
case 'C':
|
||||
if (gl != NULL) {
|
||||
if (gl != NULL && !(gl->flags & GRID_LINE_START_OUTPUT)) {
|
||||
gl->flags |= GRID_LINE_START_OUTPUT;
|
||||
gl->osc133_data.out_start_col = s->cx;
|
||||
log_debug("%s: osc133 output start at %u,%u", __func__, s->cx,
|
||||
line);
|
||||
}
|
||||
if (wp != NULL) {
|
||||
wp->cmd_start_time = time(NULL);
|
||||
@@ -3320,7 +3354,7 @@ input_osc_133(struct input_ctx *ictx, const char *p)
|
||||
}
|
||||
break;
|
||||
case 'D':
|
||||
status = input_osc_133_exit_status(p);
|
||||
status = input_osc_133_exit_status(p, &status_present);
|
||||
if (wp != NULL) {
|
||||
wp->cmd_end_time = time(NULL);
|
||||
wp->flags &= ~PANE_CMDRUNNING;
|
||||
@@ -3329,8 +3363,12 @@ input_osc_133(struct input_ctx *ictx, const char *p)
|
||||
}
|
||||
if (gl != NULL) {
|
||||
gl->flags |= GRID_LINE_END_OUTPUT;
|
||||
if (status_present)
|
||||
gl->flags |= GRID_LINE_END_OUTPUT_STATUS;
|
||||
gl->osc133_data.out_end_col = s->cx;
|
||||
gl->osc133_data.exit_status = status;
|
||||
log_debug("%s: osc133 output end at %u,%u (status %d)",
|
||||
__func__, s->cx, line, status);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -52,7 +52,9 @@
|
||||
" '#{?#{m/r:(copy|view)-mode,#{pane_mode}},Go To Top,}' '<' {send -X history-top}" \
|
||||
" '#{?#{m/r:(copy|view)-mode,#{pane_mode}},Go To Bottom,}' '>' {send -X history-bottom}" \
|
||||
" ''" \
|
||||
" '#{?#{==:#{pane_mode},copy-mode},#{?copy_line_numbers,Hide Line Numbers,Show Line Numbers},}' 'L' {send -X line-numbers-toggle}" \
|
||||
" '#{?#{==:#{pane_mode},copy-mode},#{?copy_line_numbers,Line Numbers Off,Line Numbers On},}' 'L' {send -X line-numbers-toggle}" \
|
||||
" '#{?#{==:#{pane_mode},copy-mode},#{?copy_fold_view,Fold View Off,Fold View On},}' 'O' {send -X fold-view-toggle}" \
|
||||
" '#{?#{==:#{pane_mode},copy-mode},Edit,}' 'e' {if -F '#{selection_present}' {send -X open-selection} {send -X open-output}}" \
|
||||
" '#{?#{==:#{pane_mode},copy-mode},#{?refresh_active,Refresh Off,Refresh On},}' 'r' {send -X refresh-toggle}" \
|
||||
" ''" \
|
||||
" '#{?#{&&:#{buffer_size},#{!:#{pane_in_mode}}},Paste #[underscore]#{=/9/...:buffer_sample},}' 'p' {paste-buffer}" \
|
||||
@@ -575,6 +577,7 @@ key_bindings_init(void)
|
||||
"bind -Tcopy-mode C-l { send -X recentre-top-bottom }",
|
||||
"bind -Tcopy-mode M-l { send -X cursor-centre-horizontal }",
|
||||
"bind -Tcopy-mode C-n { send -X cursor-down }",
|
||||
"bind -Tcopy-mode C-o { send -X select-output }",
|
||||
"bind -Tcopy-mode C-p { send -X cursor-up }",
|
||||
"bind -Tcopy-mode C-r { command-prompt -P -T search -ip'(search up)' -I'#{pane_search_string}' { send -X search-backward-incremental -- '%%' } }",
|
||||
"bind -Tcopy-mode C-s { command-prompt -P -T search -ip'(search down)' -I'#{pane_search_string}' { send -X search-forward-incremental -- '%%' } }",
|
||||
@@ -583,15 +586,19 @@ key_bindings_init(void)
|
||||
"bind -Tcopy-mode Escape { send -X cancel }",
|
||||
"bind -Tcopy-mode C-[ { send -X cancel }",
|
||||
"bind -Tcopy-mode Space { send -X page-down }",
|
||||
"bind -Tcopy-mode Tab { send -X toggle-output }",
|
||||
"bind -Tcopy-mode BTab { send -X toggle-output -a }",
|
||||
"bind -Tcopy-mode , { send -X jump-reverse }",
|
||||
"bind -Tcopy-mode \\; { send -X jump-again }",
|
||||
"bind -Tcopy-mode F { command-prompt -P -1p'(jump backward)' { send -X jump-backward -- '%%' } }",
|
||||
"bind -Tcopy-mode L { send -X line-numbers-toggle }",
|
||||
"bind -Tcopy-mode N { send -X search-reverse }",
|
||||
"bind -Tcopy-mode O { send -X fold-view-toggle }",
|
||||
"bind -Tcopy-mode P { send -X toggle-position }",
|
||||
"bind -Tcopy-mode R { send -X rectangle-toggle }",
|
||||
"bind -Tcopy-mode T { command-prompt -P -1p'(jump to backward)' { send -X jump-to-backward -- '%%' } }",
|
||||
"bind -Tcopy-mode X { send -X set-mark }",
|
||||
"bind -Tcopy-mode e { if -F '#{selection_present}' { send -X open-selection } { send -X open-output } }",
|
||||
"bind -Tcopy-mode f { command-prompt -P -1p'(jump forward)' { send -X jump-forward -- '%%' } }",
|
||||
"bind -Tcopy-mode g { command-prompt -P -p'(goto line)' { send -X goto-line -- '%%' } }",
|
||||
"bind -Tcopy-mode n { send -X search-again }",
|
||||
@@ -600,7 +607,7 @@ key_bindings_init(void)
|
||||
"bind -Tcopy-mode t { command-prompt -P -1p'(jump to forward)' { send -X jump-to-forward -- '%%' } }",
|
||||
"bind -Tcopy-mode Home { send -X start-of-line }",
|
||||
"bind -Tcopy-mode End { send -X end-of-line }",
|
||||
"bind -Tcopy-mode MouseDown1Pane select-pane",
|
||||
"bind -Tcopy-mode MouseDown1Pane { select-pane; send -X toggle-output -m }",
|
||||
"bind -Tcopy-mode MouseDrag1Pane { select-pane; send -X begin-selection }",
|
||||
"bind -Tcopy-mode MouseDragEnd1Pane { send -X copy-pipe-and-cancel }",
|
||||
"bind -Tcopy-mode WheelUpPane { select-pane; send -N5 -X scroll-up }",
|
||||
@@ -660,6 +667,8 @@ key_bindings_init(void)
|
||||
"bind -Tcopy-mode-vi Escape { send -X clear-selection }",
|
||||
"bind -Tcopy-mode-vi C-[ { send -X clear-selection }",
|
||||
"bind -Tcopy-mode-vi Space { send -X begin-selection }",
|
||||
"bind -Tcopy-mode-vi Tab { send -X toggle-output }",
|
||||
"bind -Tcopy-mode-vi BTab { send -X toggle-output -a }",
|
||||
"bind -Tcopy-mode-vi '$' { send -X end-of-line }",
|
||||
"bind -Tcopy-mode-vi , { send -X jump-reverse }",
|
||||
"bind -Tcopy-mode-vi / { command-prompt -P -T search -p'(search down)' { send -X search-forward -- '%%' } }",
|
||||
@@ -687,7 +696,10 @@ key_bindings_init(void)
|
||||
"bind -Tcopy-mode-vi K { send -X scroll-up }",
|
||||
"bind -Tcopy-mode-vi L { send -X bottom-line }",
|
||||
"bind -Tcopy-mode-vi M { send -X middle-line }",
|
||||
"bind -Tcopy-mode-vi M-e { if -F '#{selection_present}' { send -X open-selection } { send -X open-output } }",
|
||||
"bind -Tcopy-mode-vi M-o { send -X select-output }",
|
||||
"bind -Tcopy-mode-vi N { send -X search-reverse }",
|
||||
"bind -Tcopy-mode-vi O { send -X fold-view-toggle }",
|
||||
"bind -Tcopy-mode-vi P { send -X toggle-position }",
|
||||
"bind -Tcopy-mode-vi T { command-prompt -P -1p'(jump to backward)' { send -X jump-to-backward -- '%%' } }",
|
||||
"bind -Tcopy-mode-vi V { send -X select-line }",
|
||||
@@ -715,7 +727,7 @@ key_bindings_init(void)
|
||||
"bind -Tcopy-mode-vi % { send -X next-matching-bracket }",
|
||||
"bind -Tcopy-mode-vi Home { send -X start-of-line }",
|
||||
"bind -Tcopy-mode-vi End { send -X end-of-line }",
|
||||
"bind -Tcopy-mode-vi MouseDown1Pane { select-pane }",
|
||||
"bind -Tcopy-mode-vi MouseDown1Pane { select-pane; send -X toggle-output -m }",
|
||||
"bind -Tcopy-mode-vi MouseDrag1Pane { select-pane; send -X begin-selection }",
|
||||
"bind -Tcopy-mode-vi MouseDragEnd1Pane { send -X copy-pipe-and-cancel }",
|
||||
"bind -Tcopy-mode-vi WheelUpPane { select-pane; send -N5 -X scroll-up }",
|
||||
|
||||
@@ -114,7 +114,6 @@ static const char *options_table_theme_list[] = {
|
||||
static const char *options_table_copy_mode_line_numbers_list[] = {
|
||||
"off", "default", "absolute", "relative", "hybrid", NULL
|
||||
};
|
||||
|
||||
/* Status line format. */
|
||||
#define OPTIONS_TABLE_STATUS_FORMAT1 \
|
||||
"#[align=left range=left #{E:status-left-style}]" \
|
||||
@@ -1384,6 +1383,13 @@ const struct options_table_entry options_table[] = {
|
||||
.text = "Style of search matches in copy mode."
|
||||
},
|
||||
|
||||
{ .name = "copy-mode-exit-status-format",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE,
|
||||
.default_str = "#{?exit_status,#[fg=themered]!, }",
|
||||
.text = "Format of OSC 133 exit status indicator in copy mode."
|
||||
},
|
||||
|
||||
{ .name = "copy-mode-current-match-style",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_WINDOW,
|
||||
|
||||
81
regress/collapse-output.sh
Normal file
81
regress/collapse-output.sh
Normal file
@@ -0,0 +1,81 @@
|
||||
#!/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
|
||||
$TMUX new-session -d -x80 -y20 "sh -c 'printf \"\\033]133;A\\007p\\$ \\033]133;B\\007echo hi\\n\\033]133;C\\007hello\\n\\033]133;D;0\\007separator\\n\\033]133;A\\007p\\$ \\033]133;B\\007\"; exec sleep 100'" || exit 1
|
||||
sleep 1
|
||||
|
||||
$TMUX copy-mode -c || exit 1
|
||||
$TMUX send-keys -X search-backward hello || exit 1
|
||||
hidden=$($TMUX display-message -p '#{copy_cursor_line}')
|
||||
[ "$hidden" != hello ] || exit 1
|
||||
$TMUX send-keys -X search-backward separator || exit 1
|
||||
hidden=$($TMUX display-message -p '#{copy_cursor_line}')
|
||||
[ "$hidden" != separator ] || exit 1
|
||||
|
||||
$TMUX send-keys BTab || exit 1
|
||||
$TMUX send-keys -X search-backward hello || exit 1
|
||||
shown=$($TMUX display-message -p '#{copy_cursor_line}')
|
||||
[ "$shown" = hello ] || exit 1
|
||||
$TMUX send-keys -X select-line || exit 1
|
||||
$TMUX send-keys -X copy-selection || exit 1
|
||||
selected=$($TMUX show-buffer)
|
||||
[ "$selected" = hello ] || exit 1
|
||||
$TMUX send-keys -X cancel || exit 1
|
||||
|
||||
$TMUX kill-server
|
||||
$TMUX new-session -d -x80 -y20 "sh -c 'printf \"first\\n\\033]133;D;0\\007separator\\n\\033]133;A\\007p\\$ \\033]133;B\\007\"; exec sleep 100'" || exit 1
|
||||
sleep 1
|
||||
|
||||
$TMUX copy-mode -c || exit 1
|
||||
$TMUX send-keys -X search-backward separator || exit 1
|
||||
hidden=$($TMUX display-message -p '#{copy_cursor_line}')
|
||||
[ "$hidden" != separator ] || exit 1
|
||||
$TMUX send-keys BTab || exit 1
|
||||
$TMUX send-keys -X search-backward separator || exit 1
|
||||
shown=$($TMUX display-message -p '#{copy_cursor_line}')
|
||||
[ "$shown" = separator ] || exit 1
|
||||
$TMUX send-keys -X cancel || exit 1
|
||||
|
||||
$TMUX kill-server
|
||||
$TMUX new-session -d -x80 -y20 "sh -c 'printf \"\\033]133;A\\007P> \\033]133;B\\007for i in 1 2 3; do\\n\\033]133;A;k=s\\007> \\033]133;B\\007echo \\$i\\n\\033]133;P;k=s\\007> \\033]133;B\\007done\\033]133;C\\007\\nRESULT\\n\\033]133;D;0\\007separator\\n\\033]133;A\\007P> \\033]133;B\\007\"; exec sleep 100'" || exit 1
|
||||
sleep 1
|
||||
|
||||
$TMUX copy-mode -c || exit 1
|
||||
$TMUX send-keys -X search-backward RESULT || exit 1
|
||||
hidden=$($TMUX display-message -p '#{copy_cursor_line}')
|
||||
[ "$hidden" != RESULT ] || exit 1
|
||||
$TMUX send-keys -X search-backward 'echo $i' || exit 1
|
||||
shown=$($TMUX display-message -p '#{copy_cursor_line}')
|
||||
[ "$shown" = 'echo $i' ] || exit 1
|
||||
$TMUX send-keys -X cancel || exit 1
|
||||
|
||||
$TMUX copy-mode -U || exit 1
|
||||
$TMUX send-keys -X search-backward RESULT || exit 1
|
||||
$TMUX send-keys Tab || exit 1
|
||||
cursor=$($TMUX display-message -p '#{copy_cursor_line}')
|
||||
[ "$cursor" = done ] || exit 1
|
||||
$TMUX send-keys -X cancel || exit 1
|
||||
|
||||
$TMUX kill-server
|
||||
$TMUX new-session -d -x80 -y20 "sh -c 'printf \"\\033]133;A\\007P0> \\033]133;B\\007\\r\\n\\033]133;D;0\\007empty-separator\\n\\033]133;A\\007P1> \\033]133;B\\007\"; exec sleep 100'" || exit 1
|
||||
sleep 1
|
||||
|
||||
$TMUX copy-mode -c || exit 1
|
||||
collapsed=$($TMUX capture-pane -p)
|
||||
case "$collapsed" in
|
||||
*"+ P0>"*) ;;
|
||||
*) exit 1 ;;
|
||||
esac
|
||||
$TMUX send-keys -X search-backward empty-separator || exit 1
|
||||
hidden=$($TMUX display-message -p '#{copy_cursor_line}')
|
||||
[ "$hidden" != empty-separator ] || exit 1
|
||||
$TMUX send-keys -X cancel || exit 1
|
||||
|
||||
$TMUX kill-server 2>/dev/null
|
||||
exit 0
|
||||
102
regress/copy-mode-exit-status.sh
Normal file
102
regress/copy-mode-exit-status.sh
Normal file
@@ -0,0 +1,102 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Check OSC 133 exit status indicators in copy mode using a real client.
|
||||
|
||||
PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
LC_ALL=C.UTF-8
|
||||
export TERM LC_ALL
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -LtestA$$ -f/dev/null"
|
||||
TMUX2="$TEST_TMUX -LtestB$$ -f/dev/null"
|
||||
|
||||
fail() {
|
||||
echo "$*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
capture() {
|
||||
$TMUX capture-pane -pS0 -E- >$TMP || exit 1
|
||||
}
|
||||
|
||||
check_grep() {
|
||||
grep -Fq "$1" $TMP || fail "missing pattern: $1"
|
||||
}
|
||||
|
||||
check_no_grep() {
|
||||
grep -Fq "$1" $TMP && fail "unexpected pattern: $1"
|
||||
}
|
||||
|
||||
$TMUX kill-server 2>/dev/null
|
||||
$TMUX2 kill-server 2>/dev/null
|
||||
|
||||
TMP=$(mktemp)
|
||||
trap "rm -f $TMP; $TMUX kill-server 2>/dev/null; $TMUX2 kill-server 2>/dev/null" 0 1 15
|
||||
|
||||
$TMUX2 new-session -d -x80 -y10 \
|
||||
"printf '\033]133;A\007p\$ \033]133;B\007one\n\033]133;C\007out1\n\033]133;D;0\007\033]133;A\007p\$ \033]133;B\007two\n\033]133;C\007out2\n\033]133;D;123\007\033]133;A\007p\$ \033]133;B\007silent\n\033]133;C\007\033]133;D;7\007\033]133;A\007p\$ \033]133;B\007three\n\033]133;C\007out3\n\033]133;D\007\033]133;A\007p\$ \033]133;B\007'; exec sleep 100" || \
|
||||
exit 1
|
||||
$TMUX2 set -g status off || exit 1
|
||||
$TMUX2 set -g copy-mode-position-format '#[align=left]POS' || exit 1
|
||||
$TMUX2 list-keys -Tcopy-mode O | grep -Fq 'fold-view-toggle' || exit 1
|
||||
$TMUX2 list-keys -Tcopy-mode-vi O | grep -Fq 'fold-view-toggle' || exit 1
|
||||
|
||||
$TMUX new-session -d -x80 -y10 || exit 1
|
||||
$TMUX set -g status off || exit 1
|
||||
$TMUX send -l "$TMUX2 attach" || exit 1
|
||||
$TMUX send Enter || exit 1
|
||||
sleep 1
|
||||
|
||||
$TMUX2 copy-mode -U || exit 1
|
||||
$TMUX2 send -X history-top || exit 1
|
||||
sleep 1
|
||||
capture
|
||||
check_grep "!- p\$ two"
|
||||
check_grep "! p\$ silent"
|
||||
check_no_grep "!+ p\$ silent"
|
||||
check_grep "POS"
|
||||
|
||||
# Rebuilding with collapsed output must not expand copy-mode formats before
|
||||
# the viewport has been restored for the shorter backing grid.
|
||||
$TMUX2 send -X collapse-output -a || exit 1
|
||||
sleep 1
|
||||
capture
|
||||
check_grep "!+ p\$ two"
|
||||
check_grep "! p\$ silent"
|
||||
check_no_grep "!+ p\$ silent"
|
||||
$TMUX2 send -X line-numbers-on || exit 1
|
||||
sleep 1
|
||||
capture
|
||||
check_grep " 3 !+ p\$ two"
|
||||
$TMUX2 send -X fold-view-toggle || exit 1
|
||||
[ "$($TMUX2 display -p '#{copy_fold_view}')" = 0 ] || exit 1
|
||||
sleep 1
|
||||
capture
|
||||
check_grep "out2"
|
||||
check_no_grep "!+ p\$ two"
|
||||
check_grep " 3 p\$ two"
|
||||
$TMUX2 send -X fold-view-toggle || exit 1
|
||||
[ "$($TMUX2 display -p '#{copy_fold_view}')" = 1 ] || exit 1
|
||||
sleep 1
|
||||
capture
|
||||
check_grep " 3 !- p\$ two"
|
||||
|
||||
# A format wider than the standard three-column gutter is not truncated.
|
||||
$TMUX2 send -X cancel || exit 1
|
||||
$TMUX2 set -g copy-mode-exit-status-format \
|
||||
'#[align=right]#{?exit_status,!#{exit_status}, }' || exit 1
|
||||
$TMUX2 copy-mode -c || exit 1
|
||||
$TMUX2 send -X history-top || exit 1
|
||||
sleep 1
|
||||
capture
|
||||
check_grep "!123+ p\$ two"
|
||||
|
||||
$TMUX2 send -X select-line || exit 1
|
||||
$TMUX2 send -X copy-selection || exit 1
|
||||
selection=$($TMUX2 show-buffer)
|
||||
case $selection in
|
||||
*RC=*) fail "exit status was copied" ;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
@@ -5,9 +5,12 @@
|
||||
start_pane alternate 10 3 'MAIN\033[?1049hALT\033[?1049lZ\n'
|
||||
check_capture alternate 'MAINZ'
|
||||
|
||||
start_pane osc133 20 8 'xx\033]133;A\007p>\033]133;B\007cmd\nxy\033]133;P;k=s\007more\nzz\033]133;C\007out\033]133;D;7\007\nq\033]133;C\007bad\033]133;D;-1\007\nqq\033]133;C\007big\033]133;D;300\007\nzzz\033]133;C\007ok\033]133;D\007\n'
|
||||
start_pane osc133 20 12 'xx\033]133;A\007p>\033]133;B\007cmd\nxy\033]133;P;k=s\007more\nxz\033]133;A;k=s\007more\nxw\033]133;P;k=c\007more\nxv\033]133;A;k=c\007more\nzz\033]133;C\007out\033]133;D;7\007\nq\033]133;C\007bad\033]133;D;-1\007\nqq\033]133;C\007big\033]133;D;300\007\nzzz\033]133;C\007ok\033]133;D\007\n'
|
||||
check_capture osc133 'xxp>cmd
|
||||
xymore
|
||||
xzmore
|
||||
xwmore
|
||||
xvmore
|
||||
zzout
|
||||
qbad
|
||||
qqbig
|
||||
@@ -15,10 +18,13 @@ zzzok'
|
||||
check_raw_matches osc133 \
|
||||
'L 0 \(0\) flags=START_PROMPT,START_COMMAND\[[0-9a-f]+\].* osc133=2,4,0,0,0' \
|
||||
'L 1 \(1\) flags=SECOND_PROMPT\[[0-9a-f]+\].* osc133=2,0,0,0,0' \
|
||||
'L 2 \(2\) flags=START_OUTPUT,END_OUTPUT\[[0-9a-f]+\].* osc133=0,0,2,5,7' \
|
||||
'L 3 \(3\) flags=START_OUTPUT,END_OUTPUT\[[0-9a-f]+\].* osc133=0,0,1,4,255' \
|
||||
'L 4 \(4\) flags=START_OUTPUT,END_OUTPUT\[[0-9a-f]+\].* osc133=0,0,2,5,255' \
|
||||
'L 5 \(5\) flags=START_OUTPUT,END_OUTPUT\[[0-9a-f]+\].* osc133=0,0,3,5,0'
|
||||
'L 2 \(2\) flags=SECOND_PROMPT\[[0-9a-f]+\].* osc133=2,0,0,0,0' \
|
||||
'L 3 \(3\) flags=SECOND_PROMPT\[[0-9a-f]+\].* osc133=2,0,0,0,0' \
|
||||
'L 4 \(4\) flags=SECOND_PROMPT\[[0-9a-f]+\].* osc133=2,0,0,0,0' \
|
||||
'L 5 \(5\) flags=START_OUTPUT,END_OUTPUT,END_OUTPUT_STATUS\[[0-9a-f]+\].* osc133=0,0,2,5,7' \
|
||||
'L 6 \(6\) flags=START_OUTPUT,END_OUTPUT,END_OUTPUT_STATUS\[[0-9a-f]+\].* osc133=0,0,1,4,255' \
|
||||
'L 7 \(7\) flags=START_OUTPUT,END_OUTPUT,END_OUTPUT_STATUS\[[0-9a-f]+\].* osc133=0,0,2,5,255' \
|
||||
'L 8 \(8\) flags=START_OUTPUT,END_OUTPUT\[[0-9a-f]+\].* osc133=0,0,3,5,0'
|
||||
|
||||
$TMUX kill-server 2>/dev/null
|
||||
exit $exit_status
|
||||
|
||||
168
regress/output-commands.sh
Normal file
168
regress/output-commands.sh
Normal file
@@ -0,0 +1,168 @@
|
||||
#!/bin/sh
|
||||
|
||||
PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -L${TEST_SOCKET:-testO$$} -f/dev/null"
|
||||
OUT=/tmp/tmux-output-commands-$$
|
||||
EXPECTED=$(printf 'one\ntwo')
|
||||
|
||||
cleanup()
|
||||
{
|
||||
$TMUX kill-server 2>/dev/null
|
||||
rm -f "$OUT"
|
||||
}
|
||||
trap cleanup EXIT HUP INT TERM
|
||||
|
||||
$TMUX kill-server 2>/dev/null
|
||||
$TMUX new-session -d -x80 -y20 "sh -c 'printf \"\\033]133;A\\007p\\$ \\033]133;B\\007echo\\n\\033]133;C\\007one\\ntwo\\n\\033]133;D;0\\007separator\\n\\033]133;A\\007p\\$ \\033]133;B\\007broken\\n\\033]133;C\\007unfinished\"; exec sleep 100'" || exit 1
|
||||
sleep 1
|
||||
|
||||
$TMUX copy-mode -U || exit 1
|
||||
$TMUX send-keys -X copy-output || exit 1
|
||||
[ "$($TMUX show-buffer)" = unfinished ] || exit 1
|
||||
|
||||
$TMUX send-keys -X pipe-output "wc -c >$OUT" || exit 1
|
||||
sleep 1
|
||||
[ "$(cat "$OUT")" = 10 ] || exit 1
|
||||
|
||||
$TMUX send-keys -X copy-pipe-output "wc -c >$OUT" output || exit 1
|
||||
sleep 1
|
||||
[ "$(cat "$OUT")" = 10 ] || exit 1
|
||||
[ "$($TMUX show-buffer)" = unfinished ] || exit 1
|
||||
|
||||
$TMUX send-keys -X select-output || exit 1
|
||||
$TMUX send-keys -X copy-selection || exit 1
|
||||
[ "$($TMUX show-buffer)" = unfinished ] || exit 1
|
||||
$TMUX send-keys -X cancel || exit 1
|
||||
|
||||
$TMUX copy-mode -U || exit 1
|
||||
$TMUX send-keys -X search-backward separator || exit 1
|
||||
$TMUX send-keys -X copy-output || exit 1
|
||||
copied=$($TMUX show-buffer)
|
||||
[ "$copied" = "$EXPECTED" ] || exit 1
|
||||
$TMUX send-keys -X cancel || exit 1
|
||||
|
||||
$TMUX copy-mode -U || exit 1
|
||||
$TMUX send-keys -X search-backward one || exit 1
|
||||
$TMUX send-keys -X copy-output || exit 1
|
||||
copied=$($TMUX show-buffer)
|
||||
[ "$copied" = "$EXPECTED" ] || exit 1
|
||||
|
||||
$TMUX send-keys -X pipe-output "wc -l >$OUT" || exit 1
|
||||
sleep 1
|
||||
[ "$(cat "$OUT")" = 2 ] || exit 1
|
||||
|
||||
$TMUX send-keys -X copy-pipe-output "wc -l >$OUT" output || exit 1
|
||||
sleep 1
|
||||
[ "$(cat "$OUT")" = 2 ] || exit 1
|
||||
copied=$($TMUX show-buffer)
|
||||
[ "$copied" = "$EXPECTED" ] || exit 1
|
||||
$TMUX send-keys -X cancel || exit 1
|
||||
|
||||
$TMUX copy-mode -c || exit 1
|
||||
$TMUX send-keys -X search-backward echo || exit 1
|
||||
$TMUX send-keys -X select-output || exit 1
|
||||
$TMUX send-keys -X copy-selection || exit 1
|
||||
selected=$($TMUX show-buffer)
|
||||
[ "$selected" = "$EXPECTED" ] || exit 1
|
||||
$TMUX send-keys -X cancel || exit 1
|
||||
|
||||
$TMUX set-buffer -b keep unchanged || exit 1
|
||||
$TMUX copy-mode -U || exit 1
|
||||
$TMUX send-keys -X search-backward unfinished || exit 1
|
||||
$TMUX send-keys -X copy-output || exit 1
|
||||
[ "$($TMUX show-buffer)" = unfinished ] || exit 1
|
||||
$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 send-keys -t :plain.0 -X copy-output -a || exit 1
|
||||
all=$($TMUX show-buffer)
|
||||
case "$all" in
|
||||
*alpha*beta*) ;;
|
||||
*) exit 1 ;;
|
||||
esac
|
||||
$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 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 copy-mode -t :plain || exit 1
|
||||
$TMUX send-keys -t :plain.0 -X select-output || exit 1
|
||||
$TMUX send-keys -t :plain.0 -X select-output -a || exit 1
|
||||
$TMUX send-keys -t :plain.0 -X copy-selection || exit 1
|
||||
all=$($TMUX show-buffer)
|
||||
case "$all" in
|
||||
*alpha*beta*) ;;
|
||||
*) exit 1 ;;
|
||||
esac
|
||||
$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
|
||||
sleep 1
|
||||
$TMUX copy-mode -t :empty || 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
|
||||
|
||||
$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 -U -t :prompt || 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
|
||||
|
||||
$TMUX copy-mode -c -t :prompt || exit 1
|
||||
$TMUX send-keys -t :prompt.0 -X expand-output || exit 1
|
||||
$TMUX send-keys -t :prompt.0 -X -N 10 cursor-down || exit 1
|
||||
$TMUX send-keys -t :prompt.0 -X select-output || exit 1
|
||||
[ "$($TMUX display-message -p -t :prompt.0 '#{selection_present}')" = 1 ] || 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
|
||||
|
||||
$TMUX new-window -d -n below "printf '\\033]133;A\\007p\\$ \\033]133;B\\007old\\n\\033]133;C\\007old1\\nold2\\nold3\\nold4\\nold5\\n\\033]133;D;0\\007separator\\n\\033]133;A\\007p\\$ \\033]133;B\\007ps\\n\\033]133;C\\007PID TTY\\n1 pts/0\\n\\033]133;D;0\\007separator\\n\\033]133;A\\007p\\$ \\033]133;B\\007'; exec sleep 100" || exit 1
|
||||
sleep 1
|
||||
$TMUX copy-mode -c -t :below || exit 1
|
||||
$TMUX send-keys -t :below.0 -X search-backward ps || exit 1
|
||||
$TMUX send-keys -t :below.0 -X expand-output || exit 1
|
||||
$TMUX send-keys -t :below.0 -X -N 100 cursor-down || exit 1
|
||||
$TMUX send-keys -t :below.0 C-o || exit 1
|
||||
[ "$($TMUX display-message -p -t :below.0 '#{selection_present}')" = 1 ] || exit 1
|
||||
$TMUX send-keys -t :below.0 -X copy-selection || exit 1
|
||||
[ "$($TMUX show-buffer)" = "$(printf 'PID TTY\\n1 pts/0')" ] || exit 1
|
||||
$TMUX send-keys -t :below.0 -X cancel || exit 1
|
||||
|
||||
$TMUX new-window -d -n clear "printf 'old1\\nold2\\nold3\\nold4\\nold5\\nold6\\n\\033]133;A\\007p\\$ \\033]133;B\\007echo 1; clear; ps\\n\\033]133;C\\0071\\n\\033[H\\033[2JPID TTY\\n1 pts/0\\n\\033]133;D;0\\007separator\\n\\033]133;A\\007p\\$ \\033]133;B\\007'; exec sleep 100" || exit 1
|
||||
sleep 1
|
||||
$TMUX copy-mode -t :clear || exit 1
|
||||
$TMUX send-keys -t :clear.0 C-o || 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 send-keys -t :clear.0 -X cancel || exit 1
|
||||
|
||||
$TMUX new-window -d -n same "printf '\\033]133;A\\007p\\$ \\033]133;B\\007echo\\n\\033]133;C\\007one\\033]133;D;0\\007\\033]133;A\\007p\\$ \\033]133;B\\007'; exec sleep 100" || exit 1
|
||||
sleep 1
|
||||
$TMUX copy-mode -U -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 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
|
||||
|
||||
$TMUX copy-mode -t :plain || exit 1
|
||||
$TMUX send-keys -t :plain.0 -X copy-output -a || exit 1
|
||||
all=$($TMUX show-buffer)
|
||||
case "$all" in
|
||||
*alpha*beta*) ;;
|
||||
*) exit 1 ;;
|
||||
esac
|
||||
$TMUX send-keys -t :plain.0 -X cancel || exit 1
|
||||
|
||||
exit 0
|
||||
6
spawn.c
6
spawn.c
@@ -701,7 +701,7 @@ spawn_editor_finish(struct window_pane *wp)
|
||||
|
||||
struct spawn_editor_state *
|
||||
spawn_editor(struct client *c, const char *buf, size_t len,
|
||||
spawn_finish_edit_cb cb, void *arg)
|
||||
const char *editor, spawn_finish_edit_cb cb, void *arg)
|
||||
{
|
||||
struct spawn_editor_state *es;
|
||||
struct spawn_context sc = { 0 };
|
||||
@@ -715,13 +715,13 @@ spawn_editor(struct client *c, const char *buf, size_t len,
|
||||
FILE *f;
|
||||
char *cmd, *cause = NULL;
|
||||
char path[] = _PATH_TMP "tmux.XXXXXXXX";
|
||||
const char *editor;
|
||||
int fd;
|
||||
|
||||
if (w->modal != NULL)
|
||||
return (NULL);
|
||||
|
||||
editor = options_get_string(global_options, "editor");
|
||||
if (editor == NULL)
|
||||
editor = options_get_string(global_options, "editor");
|
||||
fd = mkstemp(path);
|
||||
if (fd == -1)
|
||||
return (NULL);
|
||||
|
||||
176
tmux.1
176
tmux.1
@@ -2004,6 +2004,25 @@ Same as
|
||||
.Ic copy\-pipe
|
||||
but also exit copy mode.
|
||||
.It Xo
|
||||
.Ic copy\-pipe\-output
|
||||
.Op Fl aCP
|
||||
.Op Ar command
|
||||
.Op Ar prefix
|
||||
.Xc
|
||||
Copy the current OSC 133 command output, pipe it to
|
||||
.Ar command ,
|
||||
and clear the selection.
|
||||
.Ar prefix
|
||||
is used to name the new paste buffer.
|
||||
.It Xo
|
||||
.Ic copy\-output
|
||||
.Op Fl aCP
|
||||
.Op Ar prefix
|
||||
.Xc
|
||||
Copy the current OSC 133 command output and clear the selection.
|
||||
.Ar prefix
|
||||
is used to name the new paste buffer.
|
||||
.It Xo
|
||||
.Ic copy\-selection
|
||||
.Op Fl CP
|
||||
.Op Ar prefix
|
||||
@@ -2169,6 +2188,27 @@ Hide line numbers in copy mode.
|
||||
.Xc
|
||||
Toggle line numbers in copy mode.
|
||||
.It Xo
|
||||
.Ic collapse\-output
|
||||
.Op Fl a
|
||||
.Xc
|
||||
Collapse the output for the command on the cursor line.
|
||||
With
|
||||
.Fl a ,
|
||||
collapse all command output in the copy-mode buffer.
|
||||
Text before the first OSC 133 prompt is treated as an initial command output
|
||||
region.
|
||||
.It Xo
|
||||
.Ic expand\-output
|
||||
.Op Fl a
|
||||
.Xc
|
||||
Expand the output for the command on the cursor line.
|
||||
With
|
||||
.Fl a ,
|
||||
expand all command output in the copy-mode buffer.
|
||||
.Pp
|
||||
The Tab key toggles output for the command on the cursor line and S-Tab
|
||||
toggles all command output.
|
||||
.It Xo
|
||||
.Ic middle\-line
|
||||
(vi: M)
|
||||
(emacs: M\-r)
|
||||
@@ -2222,6 +2262,32 @@ but treat all non-whitespace characters as part of a word.
|
||||
.Xc
|
||||
Switch at which end of the selection the cursor sits.
|
||||
.It Xo
|
||||
.Ic open\-output
|
||||
.Op Fl a
|
||||
.Op Ar command
|
||||
.Xc
|
||||
Open the current OSC 133 command output in an editor.
|
||||
If
|
||||
.Ar command
|
||||
is given, it is used as the editor command; otherwise, the
|
||||
.Ic editor
|
||||
option is used.
|
||||
.It Xo
|
||||
.Ic open\-selection
|
||||
.Op Ar command
|
||||
.Xc
|
||||
Open the current selection in an editor.
|
||||
If
|
||||
.Ar command
|
||||
is given, it is used as the editor command; otherwise, the
|
||||
.Ic editor
|
||||
option is used.
|
||||
In emacs mode,
|
||||
.Ql e ,
|
||||
and in vi mode,
|
||||
.Ql M\-e ,
|
||||
opens the selection if one is present, otherwise the command output.
|
||||
.It Xo
|
||||
.Ic page\-down
|
||||
(vi: C\-f)
|
||||
(emacs: PageDown)
|
||||
@@ -2262,6 +2328,14 @@ Same as
|
||||
.Ic pipe
|
||||
but also exit copy mode.
|
||||
.It Xo
|
||||
.Ic pipe\-output
|
||||
.Op Fl a
|
||||
.Op Ar command
|
||||
.Xc
|
||||
Pipe the current OSC 133 command output to
|
||||
.Ar command
|
||||
and clear the selection.
|
||||
.It Xo
|
||||
.Ic previous\-matching\-bracket
|
||||
(emacs: M\-C\-b)
|
||||
.Xc
|
||||
@@ -2456,6 +2530,16 @@ backward becomes forward).
|
||||
.Xc
|
||||
Select the current line.
|
||||
.It Xo
|
||||
.Ic select\-output
|
||||
.Op Fl a
|
||||
.Xc
|
||||
Select the current OSC 133 command output.
|
||||
If it is collapsed, it is expanded first.
|
||||
The default emacs binding is
|
||||
.Ql C\-o
|
||||
and the default vi binding is
|
||||
.Ql M\-o .
|
||||
.It Xo
|
||||
.Ic select\-word
|
||||
.Xc
|
||||
Select the current word.
|
||||
@@ -2494,6 +2578,12 @@ Toggle the visibility of the position indicator in the top right.
|
||||
Move to the top line.
|
||||
.El
|
||||
.Pp
|
||||
The output commands use OSC 133 output text from the C marker to the D marker.
|
||||
If there is no D marker, the output ends at the end of the copy-mode buffer.
|
||||
With
|
||||
.Fl a ,
|
||||
they use the entire copy-mode buffer instead.
|
||||
.Pp
|
||||
The search commands come in several varieties:
|
||||
.Ql search\-forward
|
||||
and
|
||||
@@ -2539,6 +2629,15 @@ Finding the beginning of command output requires the shell to emit an escape
|
||||
sequence (\e033]133;C\e033\e\e) to tell tmux where the output begins.
|
||||
If the shell does not send these escape sequences, these commands do nothing.
|
||||
.Pp
|
||||
The output commands operate on text from an OSC 133
|
||||
.Ql C
|
||||
marker up to its matching
|
||||
.Ql D
|
||||
marker, or the current end of the buffer if there is no
|
||||
.Ql D
|
||||
marker.
|
||||
They do nothing if the cursor is not associated with an output range.
|
||||
.Pp
|
||||
Copy commands may take an optional buffer prefix argument which is used
|
||||
to generate the buffer name (the default is
|
||||
.Ql buffer
|
||||
@@ -2601,12 +2700,19 @@ The synopsis for the
|
||||
command is:
|
||||
.Bl -tag -width Ds
|
||||
.It Xo Ic copy\-mode
|
||||
.Op Fl dekHMqSu
|
||||
.Op Fl UcdekHMqSu
|
||||
.Op Fl s Ar src\-pane
|
||||
.Op Fl t Ar target\-pane
|
||||
.Xc
|
||||
Enter copy mode.
|
||||
.Pp
|
||||
.Fl c
|
||||
enters copy mode with OSC 133 command output collapsed.
|
||||
.Fl U
|
||||
enters copy mode with OSC 133 output controls shown and all output expanded.
|
||||
When output is collapsed, the prompt and entered command are shown and text
|
||||
from the output start marker to the next primary prompt marker is hidden.
|
||||
.Pp
|
||||
.Fl u
|
||||
enters copy mode and scrolls one page up and
|
||||
.Fl d
|
||||
@@ -2647,6 +2753,60 @@ bind PageDown copy\-mode \-ed
|
||||
kills the pane when the mode is exited.
|
||||
.El
|
||||
.Pp
|
||||
The following commands operate on OSC 133 command output. In copy mode, they
|
||||
use the output on the cursor line; otherwise, they use the most recent output
|
||||
in the target pane. If an output has a C marker but no D marker, it ends at the
|
||||
end of the pane buffer. If there is no OSC 133 output, they do nothing unless
|
||||
.Fl a
|
||||
is given, which uses the entire buffer.
|
||||
.Bl -tag -width Ds
|
||||
.It Xo Ic select\-output
|
||||
.Op Fl a
|
||||
.Op Fl t Ar target\-pane
|
||||
.Xc
|
||||
Enter copy mode if necessary and select the output.
|
||||
.It Xo Ic copy\-output
|
||||
.Op Fl aCP
|
||||
.Op Fl t Ar target\-pane
|
||||
.Op Ar prefix
|
||||
.Xc
|
||||
Copy the output to a paste buffer.
|
||||
.It Xo Ic copy\-pipe\-output
|
||||
.Op Fl aCP
|
||||
.Op Fl t Ar target\-pane
|
||||
.Op Ar command
|
||||
.Op Ar prefix
|
||||
.Xc
|
||||
Copy the output to a paste buffer and pipe it to
|
||||
.Ar command .
|
||||
.It Xo Ic pipe\-output
|
||||
.Op Fl a
|
||||
.Op Fl t Ar target\-pane
|
||||
.Op Ar command
|
||||
.Xc
|
||||
Pipe the output to
|
||||
.Ar command .
|
||||
.It Xo Ic open\-output
|
||||
.Op Fl a
|
||||
.Op Fl t Ar target\-pane
|
||||
.Op Ar command
|
||||
.Xc
|
||||
Open the output in an editor. If
|
||||
.Ar command
|
||||
is given, it is used as the editor command; otherwise the
|
||||
.Ic editor
|
||||
option is used.
|
||||
.It Xo Ic open\-selection
|
||||
.Op Fl t Ar target\-pane
|
||||
.Op Ar command
|
||||
.Xc
|
||||
Open the current copy-mode selection in an editor. If
|
||||
.Ar command
|
||||
is given, it is used as the editor command; otherwise the
|
||||
.Ic editor
|
||||
option is used.
|
||||
.El
|
||||
.Pp
|
||||
A number of preset arrangements of panes are available, these are called
|
||||
layouts.
|
||||
These may be selected with the
|
||||
@@ -5798,6 +5958,20 @@ section.
|
||||
.It Ic copy\-mode\-position\-format Ar format
|
||||
Format of the position indicator in copy mode.
|
||||
.Pp
|
||||
.It Ic copy\-mode\-exit\-status\-format Ar format
|
||||
Format of the OSC 133 exit status indicator in the copy-mode gutter.
|
||||
The default displays a theme red
|
||||
.Ql !
|
||||
for a nonzero status and a space otherwise.
|
||||
The gutter grows to fit the expanded format.
|
||||
The format is drawn to the left of the collapse control, and its alignment
|
||||
applies within that area.
|
||||
The format is expanded with
|
||||
.Ql exit_status
|
||||
and
|
||||
.Ql exit_status_present ,
|
||||
which is set only when the OSC 133 end-of-output marker includes a status.
|
||||
.Pp
|
||||
.It Ic copy\-mode\-position\-style Ar style
|
||||
Set the style of the position indicator in copy mode.
|
||||
For how to specify
|
||||
|
||||
6
tmux.h
6
tmux.h
@@ -815,6 +815,7 @@ struct colour_palette {
|
||||
#define GRID_LINE_START_OUTPUT 0x40
|
||||
#define GRID_LINE_END_OUTPUT 0x80
|
||||
#define GRID_LINE_HYPERLINK 0x100
|
||||
#define GRID_LINE_END_OUTPUT_STATUS 0x200
|
||||
|
||||
/* All OSC 133 flags. */
|
||||
#define GRID_LINE_OSC133_FLAGS \
|
||||
@@ -822,7 +823,8 @@ struct colour_palette {
|
||||
GRID_LINE_SECOND_PROMPT| \
|
||||
GRID_LINE_START_COMMAND| \
|
||||
GRID_LINE_START_OUTPUT| \
|
||||
GRID_LINE_END_OUTPUT)
|
||||
GRID_LINE_END_OUTPUT| \
|
||||
GRID_LINE_END_OUTPUT_STATUS)
|
||||
|
||||
/* Grid string flags. */
|
||||
#define GRID_STRING_WITH_SEQUENCES 0x1
|
||||
@@ -4221,7 +4223,7 @@ struct winlink *spawn_window(struct spawn_context *, char **);
|
||||
struct window_pane *spawn_pane(struct spawn_context *, char **);
|
||||
typedef void (*spawn_finish_edit_cb)(char *, size_t, void *);
|
||||
struct spawn_editor_state *spawn_editor(struct client *, const char *, size_t,
|
||||
spawn_finish_edit_cb, void *);
|
||||
const char *, spawn_finish_edit_cb, void *);
|
||||
void spawn_cancel_editor(struct spawn_editor_state *);
|
||||
pid_t spawn_get_editor_pid(struct spawn_editor_state *);
|
||||
void spawn_editor_finish(struct window_pane *);
|
||||
|
||||
@@ -606,7 +606,8 @@ window_buffer_start_edit(struct window_buffer_modedata *data,
|
||||
ed->name = xstrdup(paste_buffer_name(pb));
|
||||
ed->pb = pb;
|
||||
|
||||
ed->editor = spawn_editor(c, buf, len, window_buffer_edit_close_cb, ed);
|
||||
ed->editor = spawn_editor(c, buf, len, NULL,
|
||||
window_buffer_edit_close_cb, ed);
|
||||
if (ed->editor == NULL)
|
||||
window_buffer_finish_edit(ed);
|
||||
else {
|
||||
|
||||
1584
window-copy.c
1584
window-copy.c
File diff suppressed because it is too large
Load Diff
@@ -2104,8 +2104,8 @@ window_customize_start_edit(struct window_customize_modedata *data,
|
||||
buf = "\n";
|
||||
len = 1;
|
||||
}
|
||||
ed->editor = spawn_editor(c, buf, len, window_customize_edit_close_cb,
|
||||
ed);
|
||||
ed->editor = spawn_editor(c, buf, len, NULL,
|
||||
window_customize_edit_close_cb, ed);
|
||||
free(value);
|
||||
if (ed->editor == NULL)
|
||||
window_customize_finish_edit(ed);
|
||||
|
||||
Reference in New Issue
Block a user