System Clipboard With tmux
By Jason FilsingerUsing tmux is huge win while working in a terminal, help make it better by adding support for your system clipboard.
The Problem
Although tmux does provide a built-in clipboard, the contents of this clipboard are not synchronized with the system clipboard. Lucky for us, this problem can be solved (and in a way that will allow us to share our tmux config across multiple platforms).
The Solution
Thanks to the way tmux is designed we are able to script it via
the shell. If we bind shell commands to the default copy/paste keychords in ~/.tmux.conf we
can take full control of what happens when we copy and paste.
Here is an example of what what you would put in your ~/.tmux.conf :
# copy:
bind-key -n -t emacs-copy M-w copy-pipe "my_copy_command"
# paste:
bind ] run "my_paste_command | tmux load-buffer - ; tmux paste-buffer"copy-pipe: runs the command you specify and passes the tmux clipboard buffer via stdin.run: executes a shell command.load-buffer: load text into the tmux buffer (will load via stdin when followed by a single ‘-’).paste-buffer: paste the tmux buffer into the active tmux pane.
By mixing the above example with the if_shell command we can specify different behavior for
individual platforms:
if_shell'<shell_command>' '<tmux_success_command>' '<tmux_failure_command>'
Example:
# Mac OS X
if-shell "uname | grep -qi Darwin" "run 'echo Running on OS X'"
# Linux
if-shell "uname | grep -qi Linux" "run 'echo Running on Linux'"
# Cygwin
if-shell "uname | grep -qi Cygwin" "run 'echo Running on Windows'"The Platforms
Mac OS X
In order to use the clipboard on OS X with tmux you will need to install reattach-to-user-namespace. (e.g. of installing with homebrew.)
~/ ❯ brew install reattach-to-user-namespaceThe reattach-to-user-namespace command will be used as a wrapper around the pbcopy
and pbpaste commands.
# copy
if-shell 'uname | grep -qi Darwin && which reattach-to-user-namespace > /dev/null' 'bind-key -n -t emacs-copy M-w copy-pipe "reattach-to-user-namespace pbcopy"'
# paste
if-shell 'uname | grep -qi Darwin && which reattach-to-user-namespace > /dev/null' 'bind ] run "reattach-to-user-namespace pbpaste | tmux load-buffer - ; tmux paste-buffer"'Linux
On Linux we can use the xclip command to handle clipboard synchronization.
# copy
if-shell 'uname | grep -qi Linux && which xclip > /dev/null' 'bind-key -n -t emacs-copy M-w copy-pipe "xclip -i -sel p -f | xclip -i -sel c "'
# paste:
if-shell 'uname | grep -qi Linux && which xclip > /dev/null' 'bind-key -n C-y run "xclip -o | tmux load-buffer - ; tmux paste-buffer"'Cygwin
The clipboard on cygwin is available via /dev/clipboard.
# copy
if-shell 'uname | grep -qi Cygwin' 'bind-key -n -t emacs-copy M-w copy-pipe "cat > /dev/clipboard"'
# paste:
if-shell 'uname | grep -qi Cygwin' 'bind ] run "cat /dev/clipboard | tmux load-buffer - ; tmux paste-buffer"'Putting It All Together
Place the following in ~/.tmux.clipboard.conf
# Mac OX X
if-shell 'uname | grep -qi Darwin && which reattach-to-user-namespace > /dev/null' 'bind-key -n -t emacs-copy M-w copy-pipe "reattach-to-user-namespace pbcopy"'
if-shell 'uname | grep -qi Darwin && which reattach-to-user-namespace > /dev/null' 'bind ] run "reattach-to-user-namespace pbpaste | tmux load-buffer - ; tmux paste-buffer"'
# Linux
if-shell 'uname | grep -qi Linux && which xclip > /dev/null' 'bind-key -n -t emacs-copy M-w copy-pipe "xclip -i -sel p -f | xclip -i -sel c "'
if-shell 'uname | grep -qi Linux && which xclip > /dev/null' 'bind-key -n C-y run "xclip -o | tmux load-buffer - ; tmux paste-buffer"'
# Cygwin
if-shell 'uname | grep -qi Cygwin' 'bind-key -n -t emacs-copy M-w copy-pipe "cat > /dev/clipboard"'
if-shell 'uname | grep -qi Cygwin' 'bind ] run "cat /dev/clipboard | tmux load-buffer - ; tmux paste-buffer"'Next add a new line to ~/.tmux.conf
# System clipboard support
source-file ~/.tmux.clipboard.confRunning tmux Outside of a Window Manager
Chances are that if you are running tmux without a window manager you won’t want any of the
custom clipboard configuration. Because we split the clipboard config into a separate file
we can use the if-shell tmux command to limit when the .tmux.clipboard.conf file is
sourced.
# Clipboard support when a display is detected
if-shell '[[ -n $DISPLAY ]]' 'source-file ~/.tmux.clipboard.conf'Bonus Round: Emacs in tmux on OS X
Running Emacs inside of tmux on OS X is pretty straightforward; add the following code to your .emacs config file to allow copy/paste with the system clipboard.
(when (eq system-type 'darwin)
;; terminal clipboard while inside tmux
(unless (display-graphic-p)
(when (and (> (length (getenv "TMUX")) 0) (executable-find "reattach-to-user-namespace"))
(defun paste-from-osx ()
(shell-command-to-string "reattach-to-user-namespace pbpaste") )
(defun cut-to-osx (text &optional push)
(let ((process-connection-type nil))
(let ((proc (start-process "pbcopy" "*Messages*" "reattach-to-user-namespace" "pbcopy") ))
(process-send-string proc text)
(process-send-eof proc))))
(setq interprogram-cut-function 'cut-to-osx)
(setq interprogram-paste-function 'paste-from-osx)
)
)
)