mirror of
https://github.com/tmux/tmux.git
synced 2026-09-19 03:24:46 +00:00
Compare commits
3 Commits
master
...
osc133_out
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a8b05dd7d7 | ||
|
|
71865a58d1 | ||
|
|
9837766857 |
@@ -53,6 +53,7 @@
|
|||||||
" '#{?#{m/r:(copy|view)-mode,#{pane_mode}},Go To Bottom,}' '>' {send -X history-bottom}" \
|
" '#{?#{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,Hide Line Numbers,Show Line Numbers},}' 'L' {send -X line-numbers-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}" \
|
" '#{?#{==:#{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}" \
|
" '#{?#{&&:#{buffer_size},#{!:#{pane_in_mode}}},Paste #[underscore]#{=/9/...:buffer_sample},}' 'p' {paste-buffer}" \
|
||||||
@@ -575,6 +576,7 @@ key_bindings_init(void)
|
|||||||
"bind -Tcopy-mode C-l { send -X recentre-top-bottom }",
|
"bind -Tcopy-mode C-l { send -X recentre-top-bottom }",
|
||||||
"bind -Tcopy-mode M-l { send -X cursor-centre-horizontal }",
|
"bind -Tcopy-mode M-l { send -X cursor-centre-horizontal }",
|
||||||
"bind -Tcopy-mode C-n { send -X cursor-down }",
|
"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-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-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 -- '%%' } }",
|
"bind -Tcopy-mode C-s { command-prompt -P -T search -ip'(search down)' -I'#{pane_search_string}' { send -X search-forward-incremental -- '%%' } }",
|
||||||
@@ -592,6 +594,7 @@ key_bindings_init(void)
|
|||||||
"bind -Tcopy-mode R { send -X rectangle-toggle }",
|
"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 T { command-prompt -P -1p'(jump to backward)' { send -X jump-to-backward -- '%%' } }",
|
||||||
"bind -Tcopy-mode X { send -X set-mark }",
|
"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 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 g { command-prompt -P -p'(goto line)' { send -X goto-line -- '%%' } }",
|
||||||
"bind -Tcopy-mode n { send -X search-again }",
|
"bind -Tcopy-mode n { send -X search-again }",
|
||||||
@@ -687,6 +690,8 @@ key_bindings_init(void)
|
|||||||
"bind -Tcopy-mode-vi K { send -X scroll-up }",
|
"bind -Tcopy-mode-vi K { send -X scroll-up }",
|
||||||
"bind -Tcopy-mode-vi L { send -X bottom-line }",
|
"bind -Tcopy-mode-vi L { send -X bottom-line }",
|
||||||
"bind -Tcopy-mode-vi M { send -X middle-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 N { send -X search-reverse }",
|
||||||
"bind -Tcopy-mode-vi P { send -X toggle-position }",
|
"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 T { command-prompt -P -1p'(jump to backward)' { send -X jump-to-backward -- '%%' } }",
|
||||||
|
|||||||
115
regress/output-commands.sh
Executable file
115
regress/output-commands.sh
Executable file
@@ -0,0 +1,115 @@
|
|||||||
|
#!/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 || 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 || exit 1
|
||||||
|
$TMUX send-keys -X select-output || exit 1
|
||||||
|
$TMUX send-keys -X pipe-selection "wc -c >$OUT" || exit 1
|
||||||
|
sleep 1
|
||||||
|
[ "$(cat "$OUT")" = 10 ] || exit 1
|
||||||
|
$TMUX send-keys -X cancel || exit 1
|
||||||
|
|
||||||
|
$TMUX copy-mode || exit 1
|
||||||
|
$TMUX send-keys -X search-backward separator || 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 send-keys -X copy-output || exit 1
|
||||||
|
[ "$($TMUX show-buffer)" = "$EXPECTED" ] || 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 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 -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 -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 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 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 -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 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
|
||||||
|
|
||||||
|
exit 0
|
||||||
6
spawn.c
6
spawn.c
@@ -701,7 +701,7 @@ spawn_editor_finish(struct window_pane *wp)
|
|||||||
|
|
||||||
struct spawn_editor_state *
|
struct spawn_editor_state *
|
||||||
spawn_editor(struct client *c, const char *buf, size_t len,
|
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_editor_state *es;
|
||||||
struct spawn_context sc = { 0 };
|
struct spawn_context sc = { 0 };
|
||||||
@@ -715,13 +715,13 @@ spawn_editor(struct client *c, const char *buf, size_t len,
|
|||||||
FILE *f;
|
FILE *f;
|
||||||
char *cmd, *cause = NULL;
|
char *cmd, *cause = NULL;
|
||||||
char path[] = _PATH_TMP "tmux.XXXXXXXX";
|
char path[] = _PATH_TMP "tmux.XXXXXXXX";
|
||||||
const char *editor;
|
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
if (w->modal != NULL)
|
if (w->modal != NULL)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
editor = options_get_string(global_options, "editor");
|
if (editor == NULL)
|
||||||
|
editor = options_get_string(global_options, "editor");
|
||||||
fd = mkstemp(path);
|
fd = mkstemp(path);
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|||||||
83
tmux.1
83
tmux.1
@@ -2006,6 +2006,25 @@ Same as
|
|||||||
.Ic copy\-pipe
|
.Ic copy\-pipe
|
||||||
but also exit copy mode.
|
but also exit copy mode.
|
||||||
.It Xo
|
.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
|
.Ic copy\-selection
|
||||||
.Op Fl CP
|
.Op Fl CP
|
||||||
.Op Ar prefix
|
.Op Ar prefix
|
||||||
@@ -2224,6 +2243,32 @@ but treat all non-whitespace characters as part of a word.
|
|||||||
.Xc
|
.Xc
|
||||||
Switch at which end of the selection the cursor sits.
|
Switch at which end of the selection the cursor sits.
|
||||||
.It Xo
|
.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
|
.Ic page\-down
|
||||||
(vi: C\-f)
|
(vi: C\-f)
|
||||||
(emacs: PageDown)
|
(emacs: PageDown)
|
||||||
@@ -2264,6 +2309,21 @@ Same as
|
|||||||
.Ic pipe
|
.Ic pipe
|
||||||
but also exit copy mode.
|
but also exit copy mode.
|
||||||
.It Xo
|
.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 pipe\-selection
|
||||||
|
.Op Ar command
|
||||||
|
.Xc
|
||||||
|
Pipe the selected text to
|
||||||
|
.Ar command
|
||||||
|
and clear the selection.
|
||||||
|
.It Xo
|
||||||
.Ic previous\-matching\-bracket
|
.Ic previous\-matching\-bracket
|
||||||
(emacs: M\-C\-b)
|
(emacs: M\-C\-b)
|
||||||
.Xc
|
.Xc
|
||||||
@@ -2453,6 +2513,15 @@ Search forward for the specified plain text.
|
|||||||
Repeat the last search in the reverse direction (forward becomes backward and
|
Repeat the last search in the reverse direction (forward becomes backward and
|
||||||
backward becomes forward).
|
backward becomes forward).
|
||||||
.It Xo
|
.It Xo
|
||||||
|
.Ic select\-output
|
||||||
|
.Op Fl a
|
||||||
|
.Xc
|
||||||
|
Select the current OSC 133 command output.
|
||||||
|
The default emacs binding is
|
||||||
|
.Ql C\-o
|
||||||
|
and the default vi binding is
|
||||||
|
.Ql M\-o .
|
||||||
|
.It Xo
|
||||||
.Ic select\-line
|
.Ic select\-line
|
||||||
(vi: V)
|
(vi: V)
|
||||||
.Xc
|
.Xc
|
||||||
@@ -2496,6 +2565,20 @@ Toggle the visibility of the position indicator in the top right.
|
|||||||
Move to the top line.
|
Move to the top line.
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
|
The output commands use OSC 133 output text from the
|
||||||
|
.Ql C
|
||||||
|
marker up to its matching
|
||||||
|
.Ql D
|
||||||
|
marker.
|
||||||
|
If there is no
|
||||||
|
.Ql D
|
||||||
|
marker, the output ends at the end of the copy-mode buffer.
|
||||||
|
At the following prompt or below it, they use the most recent nonempty output.
|
||||||
|
With
|
||||||
|
.Fl a ,
|
||||||
|
they use the entire copy-mode buffer instead.
|
||||||
|
If no output range can be found, they do nothing.
|
||||||
|
.Pp
|
||||||
The search commands come in several varieties:
|
The search commands come in several varieties:
|
||||||
.Ql search\-forward
|
.Ql search\-forward
|
||||||
and
|
and
|
||||||
|
|||||||
2
tmux.h
2
tmux.h
@@ -4227,7 +4227,7 @@ struct winlink *spawn_window(struct spawn_context *, char **);
|
|||||||
struct window_pane *spawn_pane(struct spawn_context *, char **);
|
struct window_pane *spawn_pane(struct spawn_context *, char **);
|
||||||
typedef void (*spawn_finish_edit_cb)(char *, size_t, void *);
|
typedef void (*spawn_finish_edit_cb)(char *, size_t, void *);
|
||||||
struct spawn_editor_state *spawn_editor(struct client *, const char *, size_t,
|
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 *);
|
void spawn_cancel_editor(struct spawn_editor_state *);
|
||||||
pid_t spawn_get_editor_pid(struct spawn_editor_state *);
|
pid_t spawn_get_editor_pid(struct spawn_editor_state *);
|
||||||
void spawn_editor_finish(struct window_pane *);
|
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->name = xstrdup(paste_buffer_name(pb));
|
||||||
ed->pb = 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)
|
if (ed->editor == NULL)
|
||||||
window_buffer_finish_edit(ed);
|
window_buffer_finish_edit(ed);
|
||||||
else {
|
else {
|
||||||
|
|||||||
452
window-copy.c
452
window-copy.c
@@ -117,9 +117,20 @@ static int window_copy_set_selection(struct window_mode_entry *, int, int);
|
|||||||
static int window_copy_update_selection(struct window_mode_entry *, int,
|
static int window_copy_update_selection(struct window_mode_entry *, int,
|
||||||
int);
|
int);
|
||||||
static void window_copy_synchronize_cursor(struct window_mode_entry *, int);
|
static void window_copy_synchronize_cursor(struct window_mode_entry *, int);
|
||||||
|
static int window_copy_find_output_range(struct window_mode_entry *,
|
||||||
|
u_int *, u_int *, u_int *, u_int *);
|
||||||
|
static int window_copy_find_previous_output_range(struct window_mode_entry *,
|
||||||
|
u_int, u_int, u_int *, u_int *, u_int *, u_int *);
|
||||||
|
static void window_copy_output_end(struct screen *, u_int *, u_int *);
|
||||||
static void *window_copy_get_selection(struct window_mode_entry *, size_t *);
|
static void *window_copy_get_selection(struct window_mode_entry *, size_t *);
|
||||||
|
static void *window_copy_get_output(struct window_mode_entry *, size_t *,
|
||||||
|
int);
|
||||||
|
static void *window_copy_get_grid_range(struct window_mode_entry *, u_int,
|
||||||
|
u_int, u_int, u_int, size_t *);
|
||||||
static void window_copy_copy_buffer(struct window_mode_entry *,
|
static void window_copy_copy_buffer(struct window_mode_entry *,
|
||||||
const char *, void *, size_t, int, int);
|
const char *, void *, size_t, int, int);
|
||||||
|
static void window_copy_pipe_buffer(struct session *, const char *, void *,
|
||||||
|
size_t);
|
||||||
static void window_copy_pipe(struct window_mode_entry *,
|
static void window_copy_pipe(struct window_mode_entry *,
|
||||||
struct session *, const char *);
|
struct session *, const char *);
|
||||||
static void window_copy_copy_pipe(struct window_mode_entry *,
|
static void window_copy_copy_pipe(struct window_mode_entry *,
|
||||||
@@ -1587,6 +1598,80 @@ window_copy_cmd_copy_selection_and_cancel(struct window_copy_cmd_state *cs)
|
|||||||
return (WINDOW_COPY_CMD_CANCEL);
|
return (WINDOW_COPY_CMD_CANCEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static enum window_copy_cmd_action
|
||||||
|
window_copy_cmd_select_output(struct window_copy_cmd_state *cs)
|
||||||
|
{
|
||||||
|
struct window_mode_entry *wme = cs->wme;
|
||||||
|
struct window_copy_mode_data *data = wme->data;
|
||||||
|
struct grid_reader gr;
|
||||||
|
void *buf;
|
||||||
|
size_t len;
|
||||||
|
u_int sx, sy, ex, ey, total;
|
||||||
|
int all = args_has(cs->wargs, 'a');
|
||||||
|
|
||||||
|
if (all) {
|
||||||
|
sx = sy = 0;
|
||||||
|
total = data->backing->grid->hsize + data->backing->grid->sy;
|
||||||
|
ey = total - 1;
|
||||||
|
ex = grid_get_line(data->backing->grid, ey)->cellused;
|
||||||
|
} else if (!window_copy_find_output_range(wme, &sx, &sy, &ex, &ey))
|
||||||
|
return (WINDOW_COPY_CMD_NOTHING);
|
||||||
|
buf = window_copy_get_output(wme, &len, all);
|
||||||
|
if (buf == NULL)
|
||||||
|
return (WINDOW_COPY_CMD_NOTHING);
|
||||||
|
free(buf);
|
||||||
|
|
||||||
|
window_copy_clear_selection(wme);
|
||||||
|
data->lineflag = LINE_SEL_NONE;
|
||||||
|
data->rectflag = 0;
|
||||||
|
data->selflag = SEL_CHAR;
|
||||||
|
window_copy_scroll_to(wme, sx, sy, 1);
|
||||||
|
window_copy_start_selection(wme);
|
||||||
|
if (options_get_number(wme->wp->window->options, "mode-keys") ==
|
||||||
|
MODEKEY_VI) {
|
||||||
|
grid_reader_start(&gr, data->backing->grid, ex, ey);
|
||||||
|
grid_reader_cursor_left(&gr, 1);
|
||||||
|
grid_reader_get_cursor(&gr, &ex, &ey);
|
||||||
|
}
|
||||||
|
window_copy_scroll_to(wme, ex, ey, 1);
|
||||||
|
return (WINDOW_COPY_CMD_REDRAW);
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum window_copy_cmd_action
|
||||||
|
window_copy_cmd_copy_output_no_clear(struct window_copy_cmd_state *cs)
|
||||||
|
{
|
||||||
|
struct window_mode_entry *wme = cs->wme;
|
||||||
|
struct client *c = cs->c;
|
||||||
|
struct session *s = cs->s;
|
||||||
|
struct winlink *wl = cs->wl;
|
||||||
|
struct window_pane *wp = wme->wp;
|
||||||
|
void *buf;
|
||||||
|
char *prefix = NULL;
|
||||||
|
const char *arg0 = args_string(cs->wargs, 0);
|
||||||
|
size_t len;
|
||||||
|
int set_paste = !args_has(cs->wargs, 'P');
|
||||||
|
int set_clip = !args_has(cs->wargs, 'C');
|
||||||
|
|
||||||
|
if (arg0 != NULL)
|
||||||
|
prefix = format_single(NULL, arg0, c, s, wl, wp);
|
||||||
|
if (s != NULL) {
|
||||||
|
buf = window_copy_get_output(wme, &len, args_has(cs->wargs, 'a'));
|
||||||
|
if (buf != NULL)
|
||||||
|
window_copy_copy_buffer(wme, prefix, buf, len, set_paste,
|
||||||
|
set_clip);
|
||||||
|
}
|
||||||
|
free(prefix);
|
||||||
|
return (WINDOW_COPY_CMD_NOTHING);
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum window_copy_cmd_action
|
||||||
|
window_copy_cmd_copy_output(struct window_copy_cmd_state *cs)
|
||||||
|
{
|
||||||
|
window_copy_cmd_copy_output_no_clear(cs);
|
||||||
|
window_copy_clear_selection(cs->wme);
|
||||||
|
return (WINDOW_COPY_CMD_REDRAW);
|
||||||
|
}
|
||||||
|
|
||||||
static enum window_copy_cmd_action
|
static enum window_copy_cmd_action
|
||||||
window_copy_cmd_cursor_down(struct window_copy_cmd_state *cs)
|
window_copy_cmd_cursor_down(struct window_copy_cmd_state *cs)
|
||||||
{
|
{
|
||||||
@@ -2742,6 +2827,133 @@ window_copy_cmd_pipe_and_cancel(struct window_copy_cmd_state *cs)
|
|||||||
return (WINDOW_COPY_CMD_CANCEL);
|
return (WINDOW_COPY_CMD_CANCEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static enum window_copy_cmd_action
|
||||||
|
window_copy_cmd_copy_pipe_output_no_clear(struct window_copy_cmd_state *cs)
|
||||||
|
{
|
||||||
|
struct window_mode_entry *wme = cs->wme;
|
||||||
|
struct client *c = cs->c;
|
||||||
|
struct session *s = cs->s;
|
||||||
|
struct winlink *wl = cs->wl;
|
||||||
|
struct window_pane *wp = wme->wp;
|
||||||
|
void *buf;
|
||||||
|
char *command = NULL, *prefix = NULL;
|
||||||
|
const char *arg0 = args_string(cs->wargs, 0);
|
||||||
|
const char *arg1 = args_string(cs->wargs, 1);
|
||||||
|
size_t len;
|
||||||
|
int set_paste = !args_has(cs->wargs, 'P');
|
||||||
|
int set_clip = !args_has(cs->wargs, 'C');
|
||||||
|
|
||||||
|
if (arg1 != NULL)
|
||||||
|
prefix = format_single(NULL, arg1, c, s, wl, wp);
|
||||||
|
if (s != NULL && arg0 != NULL && *arg0 != '\0')
|
||||||
|
command = format_single(NULL, arg0, c, s, wl, wp);
|
||||||
|
if (s != NULL) {
|
||||||
|
buf = window_copy_get_output(wme, &len, args_has(cs->wargs, 'a'));
|
||||||
|
if (buf != NULL) {
|
||||||
|
window_copy_pipe_buffer(s, command, buf, len);
|
||||||
|
window_copy_copy_buffer(wme, prefix, buf, len, set_paste,
|
||||||
|
set_clip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(command);
|
||||||
|
free(prefix);
|
||||||
|
return (WINDOW_COPY_CMD_NOTHING);
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum window_copy_cmd_action
|
||||||
|
window_copy_cmd_copy_pipe_output(struct window_copy_cmd_state *cs)
|
||||||
|
{
|
||||||
|
window_copy_cmd_copy_pipe_output_no_clear(cs);
|
||||||
|
window_copy_clear_selection(cs->wme);
|
||||||
|
return (WINDOW_COPY_CMD_REDRAW);
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum window_copy_cmd_action
|
||||||
|
window_copy_cmd_pipe_output_no_clear(struct window_copy_cmd_state *cs)
|
||||||
|
{
|
||||||
|
struct window_mode_entry *wme = cs->wme;
|
||||||
|
struct client *c = cs->c;
|
||||||
|
struct session *s = cs->s;
|
||||||
|
struct winlink *wl = cs->wl;
|
||||||
|
struct window_pane *wp = wme->wp;
|
||||||
|
void *buf;
|
||||||
|
char *command = NULL;
|
||||||
|
const char *arg0 = args_string(cs->wargs, 0);
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (s != NULL && arg0 != NULL && *arg0 != '\0')
|
||||||
|
command = format_single(NULL, arg0, c, s, wl, wp);
|
||||||
|
if (s != NULL) {
|
||||||
|
buf = window_copy_get_output(wme, &len, args_has(cs->wargs, 'a'));
|
||||||
|
if (buf != NULL) {
|
||||||
|
window_copy_pipe_buffer(s, command, buf, len);
|
||||||
|
free(buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(command);
|
||||||
|
return (WINDOW_COPY_CMD_NOTHING);
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum window_copy_cmd_action
|
||||||
|
window_copy_cmd_pipe_output(struct window_copy_cmd_state *cs)
|
||||||
|
{
|
||||||
|
window_copy_cmd_pipe_output_no_clear(cs);
|
||||||
|
window_copy_clear_selection(cs->wme);
|
||||||
|
return (WINDOW_COPY_CMD_REDRAW);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
window_copy_open_done(char *buf, __unused size_t len, __unused void *arg)
|
||||||
|
{
|
||||||
|
free(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum window_copy_cmd_action
|
||||||
|
window_copy_cmd_open_selection(struct window_copy_cmd_state *cs)
|
||||||
|
{
|
||||||
|
struct window_mode_entry *wme = cs->wme;
|
||||||
|
struct window_copy_mode_data *data = wme->data;
|
||||||
|
void *buf;
|
||||||
|
char *editor = NULL;
|
||||||
|
const char *arg0 = args_string(cs->wargs, 0);
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (cs->c == NULL ||
|
||||||
|
(data->screen.sel == NULL && data->lineflag == LINE_SEL_NONE))
|
||||||
|
return (WINDOW_COPY_CMD_NOTHING);
|
||||||
|
if (arg0 != NULL && *arg0 != '\0')
|
||||||
|
editor = format_single(NULL, arg0, cs->c, cs->s, cs->wl, wme->wp);
|
||||||
|
buf = window_copy_get_selection(wme, &len);
|
||||||
|
if (buf != NULL) {
|
||||||
|
spawn_editor(cs->c, buf, len, editor, window_copy_open_done, NULL);
|
||||||
|
free(buf);
|
||||||
|
}
|
||||||
|
free(editor);
|
||||||
|
return (WINDOW_COPY_CMD_NOTHING);
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum window_copy_cmd_action
|
||||||
|
window_copy_cmd_open_output(struct window_copy_cmd_state *cs)
|
||||||
|
{
|
||||||
|
struct window_mode_entry *wme = cs->wme;
|
||||||
|
void *buf;
|
||||||
|
char *editor = NULL;
|
||||||
|
const char *arg0 = args_string(cs->wargs, 0);
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (cs->c == NULL)
|
||||||
|
return (WINDOW_COPY_CMD_NOTHING);
|
||||||
|
if (arg0 != NULL && *arg0 != '\0')
|
||||||
|
editor = format_single(NULL, arg0, cs->c, cs->s, cs->wl, wme->wp);
|
||||||
|
buf = window_copy_get_output(wme, &len, args_has(cs->wargs, 'a'));
|
||||||
|
if (buf != NULL) {
|
||||||
|
spawn_editor(cs->c, buf, len, editor, window_copy_open_done, NULL);
|
||||||
|
free(buf);
|
||||||
|
}
|
||||||
|
free(editor);
|
||||||
|
return (WINDOW_COPY_CMD_NOTHING);
|
||||||
|
}
|
||||||
|
|
||||||
static enum window_copy_cmd_action
|
static enum window_copy_cmd_action
|
||||||
window_copy_cmd_goto_line(struct window_copy_cmd_state *cs)
|
window_copy_cmd_goto_line(struct window_copy_cmd_state *cs)
|
||||||
{
|
{
|
||||||
@@ -3404,6 +3616,18 @@ static const struct {
|
|||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_copy_pipe_and_cancel
|
.f = window_copy_cmd_copy_pipe_and_cancel
|
||||||
},
|
},
|
||||||
|
{ .command = "copy-pipe-output",
|
||||||
|
.args = { "aCP", 0, 2, NULL },
|
||||||
|
.flags = 0,
|
||||||
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
|
.f = window_copy_cmd_copy_pipe_output
|
||||||
|
},
|
||||||
|
{ .command = "copy-output",
|
||||||
|
.args = { "aCP", 0, 1, NULL },
|
||||||
|
.flags = 0,
|
||||||
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
|
.f = window_copy_cmd_copy_output
|
||||||
|
},
|
||||||
{ .command = "copy-selection-no-clear",
|
{ .command = "copy-selection-no-clear",
|
||||||
.args = { "CP", 0, 1, NULL },
|
.args = { "CP", 0, 1, NULL },
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
@@ -3626,6 +3850,18 @@ static const struct {
|
|||||||
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
||||||
.f = window_copy_cmd_other_end
|
.f = window_copy_cmd_other_end
|
||||||
},
|
},
|
||||||
|
{ .command = "open-output",
|
||||||
|
.args = { "a", 0, 1, NULL },
|
||||||
|
.flags = 0,
|
||||||
|
.clear = WINDOW_COPY_CMD_CLEAR_NEVER,
|
||||||
|
.f = window_copy_cmd_open_output
|
||||||
|
},
|
||||||
|
{ .command = "open-selection",
|
||||||
|
.args = { "", 0, 1, NULL },
|
||||||
|
.flags = 0,
|
||||||
|
.clear = WINDOW_COPY_CMD_CLEAR_NEVER,
|
||||||
|
.f = window_copy_cmd_open_selection
|
||||||
|
},
|
||||||
{ .command = "page-down",
|
{ .command = "page-down",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
@@ -3662,6 +3898,18 @@ static const struct {
|
|||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_pipe_and_cancel
|
.f = window_copy_cmd_pipe_and_cancel
|
||||||
},
|
},
|
||||||
|
{ .command = "pipe-output",
|
||||||
|
.args = { "a", 0, 1, NULL },
|
||||||
|
.flags = 0,
|
||||||
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
|
.f = window_copy_cmd_pipe_output
|
||||||
|
},
|
||||||
|
{ .command = "pipe-selection",
|
||||||
|
.args = { "", 0, 1, NULL },
|
||||||
|
.flags = 0,
|
||||||
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
|
.f = window_copy_cmd_pipe
|
||||||
|
},
|
||||||
{ .command = "previous-matching-bracket",
|
{ .command = "previous-matching-bracket",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
@@ -3839,6 +4087,12 @@ static const struct {
|
|||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_search_reverse
|
.f = window_copy_cmd_search_reverse
|
||||||
},
|
},
|
||||||
|
{ .command = "select-output",
|
||||||
|
.args = { "a", 0, 0, NULL },
|
||||||
|
.flags = 0,
|
||||||
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
|
.f = window_copy_cmd_select_output
|
||||||
|
},
|
||||||
{ .command = "select-line",
|
{ .command = "select-line",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
@@ -5970,6 +6224,185 @@ window_copy_set_selection(struct window_mode_entry *wme, int may_redraw,
|
|||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Find the output range for the command at the cursor. */
|
||||||
|
static int
|
||||||
|
window_copy_find_output_range(struct window_mode_entry *wme, u_int *sx,
|
||||||
|
u_int *sy, u_int *ex, u_int *ey)
|
||||||
|
{
|
||||||
|
struct window_copy_mode_data *data = wme->data;
|
||||||
|
struct grid *gd = data->backing->grid;
|
||||||
|
struct grid_line *gl;
|
||||||
|
u_int cursor_x, cursor_y, prompt_x = 0;
|
||||||
|
u_int prompt_y = UINT_MAX, y, total;
|
||||||
|
int found_start = 0, found_end = 0;
|
||||||
|
|
||||||
|
cursor_x = data->cx;
|
||||||
|
cursor_y = screen_hsize(data->backing) + data->cy - data->oy;
|
||||||
|
log_debug("%s: cursor at %u,%u", __func__, cursor_x, cursor_y);
|
||||||
|
|
||||||
|
total = gd->hsize + gd->sy;
|
||||||
|
for (y = 0; y < total; y++) {
|
||||||
|
gl = grid_get_line(gd, y);
|
||||||
|
if (~gl->flags & GRID_LINE_START_PROMPT)
|
||||||
|
continue;
|
||||||
|
if (y > cursor_y ||
|
||||||
|
(y == cursor_y && gl->osc133_data.prompt_col > cursor_x))
|
||||||
|
break;
|
||||||
|
prompt_y = y;
|
||||||
|
prompt_x = gl->osc133_data.prompt_col;
|
||||||
|
}
|
||||||
|
if (prompt_y == UINT_MAX) {
|
||||||
|
log_debug("%s: no osc133 prompt before cursor", __func__);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
log_debug("%s: prompt at %u,%u", __func__, prompt_x, prompt_y);
|
||||||
|
|
||||||
|
for (y = prompt_y; y < total; y++) {
|
||||||
|
gl = grid_get_line(gd, y);
|
||||||
|
/* An output may end on the next prompt's line. */
|
||||||
|
if (found_start && gl->flags & GRID_LINE_END_OUTPUT &&
|
||||||
|
(y != prompt_y || gl->osc133_data.out_end_col >= prompt_x)) {
|
||||||
|
*ex = gl->osc133_data.out_end_col;
|
||||||
|
*ey = y;
|
||||||
|
found_end = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (y != prompt_y && gl->flags & GRID_LINE_START_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));
|
||||||
|
}
|
||||||
|
if (!found_end) {
|
||||||
|
if (y != total) {
|
||||||
|
log_debug("%s: output interrupted by next prompt", __func__);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
window_copy_output_end(data->backing, ex, ey);
|
||||||
|
}
|
||||||
|
log_debug("%s: output from %u,%u to %u,%u", __func__, *sx, *sy,
|
||||||
|
*ex, *ey);
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find the most recent complete output at or before a position. */
|
||||||
|
static int
|
||||||
|
window_copy_find_previous_output_range(struct window_mode_entry *wme,
|
||||||
|
u_int cursor_x, u_int cursor_y, u_int *sx, u_int *sy, u_int *ex,
|
||||||
|
u_int *ey)
|
||||||
|
{
|
||||||
|
struct window_copy_mode_data *data = wme->data;
|
||||||
|
struct grid *gd = data->backing->grid;
|
||||||
|
struct grid_line *gl;
|
||||||
|
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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
start_y = y;
|
||||||
|
pending = 1;
|
||||||
|
}
|
||||||
|
/* The output may have cleared its C marker from the screen. */
|
||||||
|
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)) {
|
||||||
|
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;
|
||||||
|
end_y = y;
|
||||||
|
buf = window_copy_get_grid_range(wme, start_x, start_y,
|
||||||
|
end_x, end_y, &len);
|
||||||
|
if (buf != NULL) {
|
||||||
|
free(buf);
|
||||||
|
*sx = start_x;
|
||||||
|
*sy = start_y;
|
||||||
|
*ex = end_x;
|
||||||
|
*ey = end_y;
|
||||||
|
found = 1;
|
||||||
|
}
|
||||||
|
pending = 0;
|
||||||
|
}
|
||||||
|
if (gl->flags & GRID_LINE_START_PROMPT) {
|
||||||
|
pending = 0;
|
||||||
|
have_prompt = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (found);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
window_copy_output_end(struct screen *s, u_int *x, u_int *y)
|
||||||
|
{
|
||||||
|
*x = s->cx;
|
||||||
|
*y = screen_hsize(s) + s->cy;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
window_copy_get_output(struct window_mode_entry *wme, size_t *len, int all)
|
||||||
|
{
|
||||||
|
struct window_copy_mode_data *data = wme->data;
|
||||||
|
struct grid *gd = data->backing->grid;
|
||||||
|
u_int sx, sy, ex, ey, total;
|
||||||
|
|
||||||
|
total = gd->hsize + gd->sy;
|
||||||
|
if (all) {
|
||||||
|
sx = sy = 0;
|
||||||
|
ey = total - 1;
|
||||||
|
ex = grid_get_line(gd, ey)->cellused;
|
||||||
|
} else if (!window_copy_find_output_range(wme, &sx, &sy, &ex, &ey)) {
|
||||||
|
*len = 0;
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
return (window_copy_get_grid_range(wme, sx, sy, ex, ey, len));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
window_copy_get_grid_range(struct window_mode_entry *wme, u_int sx, u_int sy,
|
||||||
|
u_int ex, u_int ey, size_t *len)
|
||||||
|
{
|
||||||
|
struct window_copy_mode_data *data = wme->data;
|
||||||
|
struct grid *gd = data->backing->grid;
|
||||||
|
char *buf;
|
||||||
|
size_t off;
|
||||||
|
u_int i;
|
||||||
|
|
||||||
|
buf = xmalloc(1);
|
||||||
|
off = 0;
|
||||||
|
for (i = sy; i <= ey; i++) {
|
||||||
|
window_copy_copy_line(wme, &buf, &off, i, i == sy ? sx : 0,
|
||||||
|
i == ey ? ex : gd->sx);
|
||||||
|
}
|
||||||
|
if (off != 0 && buf[off - 1] == '\n')
|
||||||
|
off--;
|
||||||
|
if (off == 0) {
|
||||||
|
free(buf);
|
||||||
|
*len = 0;
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
*len = off;
|
||||||
|
return (buf);
|
||||||
|
}
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
window_copy_get_selection(struct window_mode_entry *wme, size_t *len)
|
window_copy_get_selection(struct window_mode_entry *wme, size_t *len)
|
||||||
{
|
{
|
||||||
@@ -6102,8 +6535,7 @@ window_copy_copy_buffer(struct window_mode_entry *wme, const char *prefix,
|
|||||||
|
|
||||||
if (set_clip &&
|
if (set_clip &&
|
||||||
options_get_number(global_options, "set-clipboard") != 0) {
|
options_get_number(global_options, "set-clipboard") != 0) {
|
||||||
if (window_copy_line_numbers_active(wme) &&
|
if (wp->flags & PANE_REDRAW) {
|
||||||
(wp->flags & PANE_REDRAW)) {
|
|
||||||
/* Clear PANE_REDRAW so clipboard write not skipped. */
|
/* Clear PANE_REDRAW so clipboard write not skipped. */
|
||||||
redraw = PANE_REDRAW;
|
redraw = PANE_REDRAW;
|
||||||
wp->flags &= ~PANE_REDRAW;
|
wp->flags &= ~PANE_REDRAW;
|
||||||
@@ -6126,18 +6558,28 @@ window_copy_pipe_run(struct window_mode_entry *wme, struct session *s,
|
|||||||
const char *cmd, size_t *len)
|
const char *cmd, size_t *len)
|
||||||
{
|
{
|
||||||
void *buf;
|
void *buf;
|
||||||
struct job *job;
|
|
||||||
|
|
||||||
buf = window_copy_get_selection(wme, len);
|
buf = window_copy_get_selection(wme, len);
|
||||||
|
window_copy_pipe_buffer(s, cmd, buf, *len);
|
||||||
|
return (buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
window_copy_pipe_buffer(struct session *s, const char *cmd, void *buf,
|
||||||
|
size_t len)
|
||||||
|
{
|
||||||
|
struct job *job;
|
||||||
|
|
||||||
|
if (buf == NULL)
|
||||||
|
return;
|
||||||
if (cmd == NULL || *cmd == '\0')
|
if (cmd == NULL || *cmd == '\0')
|
||||||
cmd = options_get_string(global_options, "copy-command");
|
cmd = options_get_string(global_options, "copy-command");
|
||||||
if (cmd != NULL && *cmd != '\0') {
|
if (cmd != NULL && *cmd != '\0') {
|
||||||
job = job_run(cmd, 0, NULL, NULL, s, NULL, NULL, NULL, NULL,
|
job = job_run(cmd, 0, NULL, NULL, s, NULL, NULL, NULL, NULL,
|
||||||
NULL, JOB_NOWAIT, -1, -1);
|
NULL, JOB_NOWAIT, -1, -1);
|
||||||
if (job != NULL)
|
if (job != NULL)
|
||||||
bufferevent_write(job_get_event(job), buf, *len);
|
bufferevent_write(job_get_event(job), buf, len);
|
||||||
}
|
}
|
||||||
return (buf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|||||||
@@ -2104,8 +2104,8 @@ window_customize_start_edit(struct window_customize_modedata *data,
|
|||||||
buf = "\n";
|
buf = "\n";
|
||||||
len = 1;
|
len = 1;
|
||||||
}
|
}
|
||||||
ed->editor = spawn_editor(c, buf, len, window_customize_edit_close_cb,
|
ed->editor = spawn_editor(c, buf, len, NULL,
|
||||||
ed);
|
window_customize_edit_close_cb, ed);
|
||||||
free(value);
|
free(value);
|
||||||
if (ed->editor == NULL)
|
if (ed->editor == NULL)
|
||||||
window_customize_finish_edit(ed);
|
window_customize_finish_edit(ed);
|
||||||
|
|||||||
Reference in New Issue
Block a user