diff --git a/.tmux.conf b/.tmux.conf index 86ad41a..c754c33 100644 --- a/.tmux.conf +++ b/.tmux.conf @@ -147,6 +147,17 @@ bind i split-window -h -c "#{pane_current_path}" bind -n M-f resize-pane -Z +# paste from system clipboard +bind -n C-S-v run -b "~/.config/tmux/scripts/paste_from_clipboard.sh" +bind -T copy-mode-vi C-S-v send-keys -X cancel \; run -b "~/.config/tmux/scripts/paste_from_clipboard.sh" +bind -T copy-mode C-S-v send-keys -X cancel \; run -b "~/.config/tmux/scripts/paste_from_clipboard.sh" + +# Alt+Shift+V paste +bind -n M-V run -b "~/.config/tmux/scripts/paste_from_clipboard.sh" +bind -T copy-mode-vi M-V send-keys -X cancel \; run -b "~/.config/tmux/scripts/paste_from_clipboard.sh" +bind -T copy-mode M-V send-keys -X cancel \; run -b "~/.config/tmux/scripts/paste_from_clipboard.sh" + + # pane navigation bind 1 select-pane -t:.1 bind 2 select-pane -t:.2 @@ -195,7 +206,7 @@ bind -T copy-mode-vi E send-keys -N 5 -X cursor-down bind -T copy-mode-vi N send-keys -X start-of-line bind -T copy-mode-vi I send-keys -X end-of-line bind -T copy-mode-vi Y send-keys -X copy-end-of-line -bind -T copy-mode-vi y send-keys -X copy-selection-and-cancel +bind -T copy-mode-vi y send-keys -X copy-pipe-and-cancel "~/.config/tmux/scripts/copy_to_clipboard.sh" bind -T copy-mode-vi = send-keys -X search-again bind -T copy-mode-vi = send-keys -X search-reverse diff --git a/tmux/scripts/copy_to_clipboard.sh b/tmux/scripts/copy_to_clipboard.sh new file mode 100755 index 0000000..13b6126 --- /dev/null +++ b/tmux/scripts/copy_to_clipboard.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash +set -euo pipefail + +content=$(cat | tr -d '\r') +# Update tmux buffer and system clipboard (uses tmux set-clipboard setting) +tmux set-buffer -w -- "$content" + +# Best-effort: also call platform clip utilities when available +if command -v pbcopy >/dev/null 2>&1; then + printf '%s' "$content" | pbcopy || true +elif command -v wl-copy >/dev/null 2>&1; then + printf '%s' "$content" | wl-copy --type text || wl-copy || true +elif command -v xclip >/dev/null 2>&1; then + printf '%s' "$content" | xclip -selection clipboard || true +elif command -v xsel >/dev/null 2>&1; then + printf '%s' "$content" | xsel --clipboard --input || true +elif command -v powershell.exe >/dev/null 2>&1; then + powershell.exe -NoProfile -Command Set-Clipboard -Value @" +${content} +"@ || true +fi + diff --git a/tmux/scripts/paste_from_clipboard.sh b/tmux/scripts/paste_from_clipboard.sh new file mode 100755 index 0000000..6697025 --- /dev/null +++ b/tmux/scripts/paste_from_clipboard.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash +set -euo pipefail + +read_clipboard() { + if command -v pbpaste >/dev/null 2>&1; then + pbpaste + return 0 + fi + if command -v wl-paste >/dev/null 2>&1; then + wl-paste --no-newline 2>/dev/null || wl-paste + return 0 + fi + if command -v xclip >/dev/null 2>&1; then + xclip -selection clipboard -o 2>/dev/null || true + return 0 + fi + if command -v xsel >/dev/null 2>&1; then + xsel -o --clipboard 2>/dev/null || true + return 0 + fi + if command -v powershell.exe >/dev/null 2>&1; then + powershell.exe -NoProfile -Command Get-Clipboard 2>/dev/null || true + return 0 + fi + return 1 +} + +content=$(read_clipboard || true) +if [[ -z "${content:-}" ]]; then + exit 0 +fi + +# normalize CRLF -> LF +content=$(printf '%s' "$content" | tr -d '\r') + +tmux set-buffer -- "$content" +tmux paste-buffer -p -d +