Compare commits

...

34 Commits

Author SHA1 Message Date
Michael Grant
2ec4328380 Fixed clear erasinng the usable C marker, use beginning of buffer in this case, up to D marker. 2026-09-14 03:09:42 +01:00
Michael Grant
8746405e34 In copy-mode if cursor is below last line, select-output uses the previous command. 2026-09-14 02:50:32 +01:00
Michael Grant
8c0ac1fe05 Fixed output may end on the next prompt's line. 2026-09-09 06:01:10 +01:00
Michael Grant
dc65677ff9 Add more logging for osc133. 2026-09-07 14:22:54 +01:00
Michael Grant
2142818e25 Undo these as top level tmux commands. 2026-09-07 14:12:01 +01:00
Michael Grant
cda0fe9f7b Act on previous cmd output when cursor on prompt at end of copy-buffer. 2026-09-07 05:21:25 +01:00
Michael Grant
4cc9fc91fa Bugfix copy-output outside copy-mode now properly copies last output. 2026-09-05 20:47:21 +01:00
Michael Grant
081b79fd6e - Added top-level commands:
- select-output
    - copy-output
    - copy-pipe-output
    - pipe-output
    - open-output
    - open-selection

- Added -a support to operate on the entire pane/copy-mode buffer, including panes without OSC 133 markers.
- Output extraction now supports unfinished commands with C but no D, ending at the current pane cursor.
- Top-level commands use the most recent OSC 133 output when outside copy mode.
- select-output enters copy mode and selects the output; other top-level operations use a temporary copy-mode snapshot.
- Added copy-mode bindings to open the selection when present, otherwise the current command output:
    - emacs: e
    - vi: M-e

- Added copy-mode bidings to select the output of command cursor is on:
    - emacs copy mode: C-o → select-output
    - vi copy mode: M-o → select-output

- Updated command registration, build sources, and tmux.1 documentation.
- Added/extended regress/output-commands.sh.
- Verified with make, regress/collapse-output.sh, and regress/output-commands.sh.
2026-09-05 18:43:15 +01:00
Michael Grant
6294be4986 Merge branch 'master' into osc133_line_collapsible 2026-09-05 15:15:29 +01:00
Michael Grant
c5a5b99788 Rename output to fold in places for consistency. 2026-08-01 11:59:18 +01:00
Michael Grant
e23219ec04 Add comments during my review including one fix, separator text after D also expandable. 2026-08-01 11:47:25 +01:00
Michael Grant
0f29c47278 Cleanup. Rename things for consistency. Fix indenting. 2026-08-01 08:26:05 +01:00
Michael Grant
7c9fdcb770 Add k=c and a helper function to check for secondary prompt. 2026-07-31 10:39:09 +01:00
Michael Grant
0330d8ac57 Change line-numbers menu to On/Off. 2026-07-29 23:35:11 +01:00
Michael Grant
0a7788b66f Add Fold View menu item and O key to toggle fold view. 2026-07-29 23:25:36 +01:00
Michael Grant
458d045bd2 With collapsible output active, line-numbers-on now shows each visible line’s original buffer line number, so hidden lines remain counted. 2026-07-29 22:10:19 +01:00
Michael Grant
a81154d6d9 Fix missing ! before commands with no output and non-zero exit status. 2026-07-22 23:40:01 +01:00
Michael Grant
cffc86dae5 Merge branch 'osc133_line_collapsible' of github.com:tmux/tmux into osc133_line_collapsible 2026-07-22 11:39:04 +01:00
Michael Grant
4cfd155ffc Add copy-mode collapse output regression test. 2026-07-22 11:38:07 +01:00
Michael Grant
670ea5d083 Add regression test for copy-mode-exit-status. 2026-07-22 11:35:59 +01:00
Michael Grant
eaeb234dd4 Remove code to put exit-code on right and go for just simple ! on left of +. 2026-07-22 11:35:59 +01:00
Michael Grant
5948722d5a Add highlighting to the current line. 2026-07-22 11:35:59 +01:00
Michael Grant
d8ad7cd9c5 Add exit status on right. 2026-07-22 11:35:59 +01:00
Michael Grant
b49cc2d936 Fix stray L on empty commands. 2026-07-22 11:35:59 +01:00
Michael Grant
abb7108e25 Add vertical bar next to expanded lines. 2026-07-22 11:35:59 +01:00
Michael Grant
d080378464 Add collapsible lines. 2026-07-22 11:35:59 +01:00
Michael Grant
473eca949a Add regression test for copy-mode-exit-status. 2026-07-22 11:35:28 +01:00
Michael Grant
f0eaa5e9d6 Remove code to put exit-code on right and go for just simple ! on left of +. 2026-07-22 11:33:46 +01:00
Michael Grant
f44246c764 Add highlighting to the current line. 2026-07-21 19:19:31 +01:00
Michael Grant
5d4d41da57 Add exit status on right. 2026-07-21 18:48:16 +01:00
Michael Grant
bacbb4d9d8 Fix stray L on empty commands. 2026-07-21 15:03:52 +01:00
Michael Grant
07a3a16ae7 Add vertical bar next to expanded lines. 2026-07-21 07:42:20 +01:00
Michael Grant
f41288ee27 Add collapsible lines. 2026-07-20 16:26:02 +01:00
Nicholas Marriott
457b6cbefd Put OSC 133 data into grid_line. 2026-07-20 11:24:33 +01:00
15 changed files with 2168 additions and 84 deletions

View File

@@ -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
View File

@@ -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
View File

@@ -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;
}

View File

@@ -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 }",

View File

@@ -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,

View 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

View 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

View File

@@ -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
View 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

View File

@@ -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
View File

@@ -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
View File

@@ -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 *);

View File

@@ -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 {

File diff suppressed because it is too large Load Diff

View File

@@ -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);