-
Notifications
You must be signed in to change notification settings - Fork 498
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Integration with clipboard: pbcopy, reattach-to-user-namespace, xclip…
…, xsel, OSC 52 ANSI escape sequence
- Loading branch information
Showing
2 changed files
with
91 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
#!/bin/bash | ||
|
||
set -eu | ||
|
||
is_app_installed() { | ||
type "$1" &>/dev/null | ||
} | ||
|
||
# get data either form stdin or from file | ||
buf=$(cat "$@") | ||
|
||
# Resolve copy backend: pbcopy (OSX), reattach-to-user-namespace (OSX), xclip/xsel (Linux) | ||
copy_backend="" | ||
if is_app_installed pbcopy; then | ||
copy_backend="pbcopy" | ||
elif is_app_installed reattach-to-user-namespace; then | ||
copy_backend="reattach-to-user-namespace pbcopy" | ||
elif [ -n "${DISPLAY-}" ] && is_app_installed xclip; then | ||
copy_backend="xclip -selection clipboard -i" | ||
elif [ -n "${DISPLAY-}" ] && is_app_installed xsel; then | ||
copy_backend="xsel -i --clipboard" | ||
fi | ||
|
||
# if copy backend is resolved, copy and exit | ||
if [ -n "$copy_backend" ]; then | ||
printf "$buf" | "$copy_backend" | ||
exit; | ||
fi | ||
|
||
# TODO: send to local socket which is remote tunneled to "pbcopy|xclip" listener on local machine | ||
# TODO: otherwise fallback to OSC 52 escape sequence | ||
|
||
# Copy via OSC 52 ANSI escape sequence to controlling terminal | ||
buflen=$( printf %s "$buf" | wc -c ) | ||
|
||
# https://sunaku.github.io/tmux-yank-osc52.html | ||
# The maximum length of an OSC 52 escape sequence is 100_000 bytes, of which | ||
# 7 bytes are occupied by a "\033]52;c;" header, 1 byte by a "\a" footer, and | ||
# 99_992 bytes by the base64-encoded result of 74_994 bytes of copyable text | ||
maxlen=74994 | ||
|
||
# warn if exceeds maxlen | ||
if [ "$buflen" -gt "$maxlen" ]; then | ||
printf "input is %d bytes too long" "$(( buflen - maxlen ))" >&2 | ||
fi | ||
|
||
# build up OSC 52 ANSI escape sequence | ||
esc="\033]52;c;$( printf %s "$buf" | head -c $maxlen | base64 | tr -d '\r\n' )\a" | ||
esc="\033Ptmux;\033$esc\033\\" | ||
|
||
# resolve target terminal to send escape sequence | ||
# if we are on remote machine, send directly to SSH_TTY to transport escape sequence | ||
# to terminal on local machine, so data lands in clipboard on our local machine | ||
pane_active_tty=$(tmux list-panes -F "#{pane_active} #{pane_tty}" | awk '$1=="1" { print $2 }') | ||
target_tty="${SSH_TTY:-$pane_active_tty}" | ||
|
||
printf "$esc" > "$target_tty" |