Last active
April 27, 2026 08:01
-
-
Save taiseiue/1c9915e74984118b94631a12e4cf2404 to your computer and use it in GitHub Desktop.
OSC52経由でのpbcopy,pbpaste
This file contains hidden or 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
| #!/usr/bin/env bash | |
| # pbcopy | |
| # Usage: echo "text" | pbcopy | |
| # pbcopy < file.txt | |
| # pbcopy "text" | |
| set -euo pipefail | |
| # 引数があればそれを使い、なければstdinを読む | |
| if [[ $# -gt 0 ]]; then | |
| data="$*" | |
| else | |
| data="$(cat)" | |
| fi | |
| # macOSとGNUのもので挙動が違うので出し分け | |
| if base64 --version &>/dev/null 2>&1; then | |
| encoded="$(printf '%s' "$data" | base64 | tr -d '\n')" | |
| else | |
| encoded="$(printf '%s' "$data" | base64 -w 0)" | |
| fi | |
| # tmux/screen内ではラッピングする必要がある | |
| emit_osc52() { | |
| local payload="$1" | |
| printf '\033]52;c;%s\007' "$payload" | |
| } | |
| if [[ -n "${TMUX:-}" ]]; then | |
| # tmuxならDCSで囲む | |
| printf '\033Ptmux;\033\033]52;c;%s\007\033\\' "$encoded" | |
| elif [[ "${TERM:-}" == screen* ]]; then | |
| # screen | |
| printf '\033P\033]52;c;%s\007\033\\' "$encoded" | |
| else | |
| emit_osc52 "$encoded" | |
| fi | |
| # /dev/ttyが使えるならそこに出力 | |
| if [[ -w /dev/tty ]]; then | |
| : | |
| fi | |
| # ttyへ直接書き込む | |
| { | |
| if [[ -n "${TMUX:-}" ]]; then | |
| printf '\033Ptmux;\033\033]52;c;%s\007\033\\' "$encoded" | |
| elif [[ "${TERM:-}" == screen* ]]; then | |
| printf '\033P\033]52;c;%s\007\033\\' "$encoded" | |
| else | |
| printf '\033]52;c;%s\007' "$encoded" | |
| fi | |
| } > /dev/tty | |
| byte_count=${#data} | |
| printf '%d bytes copied to clipboard\n' "$byte_count" >&2 |
This file contains hidden or 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
| #!/usr/bin/env bash | |
| # pbpaste | |
| # Note: Requires terminal emulators support. | |
| # Available: iTerm2, xterm, wezterm | |
| # Usage: pbpaste | |
| # pbpaste | grep "pattern" | |
| set -euo pipefail | |
| # OSC52 paste request: \e]52;c;?\a を送るとターミナルが | |
| # \e]52;c;<base64>\a で応答する | |
| request_clipboard() { | |
| local tty_dev="/dev/tty" | |
| if [[ ! -r "$tty_dev" ]] || [[ ! -w "$tty_dev" ]]; then | |
| echo "pbpaste: /dev/tty にアクセスできません" >&2 | |
| exit 1 | |
| fi | |
| local old_stty | |
| old_stty=$(stty -g < "$tty_dev") | |
| trap 'stty "$old_stty" < "$tty_dev"' EXIT INT TERM | |
| stty raw -echo min 0 time 3 < "$tty_dev" | |
| # OSC52 paste queryを送信する | |
| if [[ -n "${TMUX:-}" ]]; then | |
| printf '\033Ptmux;\033\033]52;c;?\007\033\\' > "$tty_dev" | |
| elif [[ "${TERM:-}" == screen* ]]; then | |
| printf '\033P\033]52;c;?\007\033\\' > "$tty_dev" | |
| else | |
| printf '\033]52;c;?\007' > "$tty_dev" | |
| fi | |
| local response="" | |
| local char | |
| local timeout=30 # 3秒 (time 3 = 0.3秒 × 10) | |
| local count=0 | |
| while [[ $count -lt $timeout ]]; do | |
| char=$(dd if="$tty_dev" bs=1 count=1 2>/dev/null || true) | |
| if [[ -z "$char" ]]; then | |
| ((count++)) || true | |
| continue | |
| fi | |
| response+="$char" | |
| count=0 | |
| # BEL (\a = \007) で終端 | |
| if [[ "$response" == *$'\007' ]]; then | |
| break | |
| fi | |
| done | |
| stty "$old_stty" < "$tty_dev" | |
| trap - EXIT INT TERM | |
| # レスポンス: ESC ] 52 ; c ; DATA BEL | |
| local base64_data | |
| base64_data=$(printf '%s' "$response" | sed 's/.*]52;c;//; s/\x07//') | |
| if [[ -z "$base64_data" ]] || [[ "$base64_data" == "?" ]]; then | |
| echo "pbpaste: ターミナルがOSC52 pasteに応答しませんでした" >&2 | |
| echo "ターミナルエミュレータがOSC52読み取りをサポートしているか確認してください" >&2 | |
| exit 1 | |
| fi | |
| if base64 --version &>/dev/null 2>&1; then | |
| printf '%s' "$base64_data" | base64 --decode | |
| else | |
| printf '%s' "$base64_data" | base64 -d | |
| fi | |
| } | |
| request_clipboard |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment