Use System Clipboard for Vi Copy Mode in Tmux in macOS and Linux
Since I sync my dotfiles through GitHub, I wanted to implement something that will work on both macOS and Linux. Enter if-shell, which is documented in tmux’s man page:
if-shell [-bF] [-t target-pane] shell-command command [command]
(alias: if)
Execute the first command if shell-command returns success or the second command otherwise. Before being executed, shell-command is expanded using the rules specified
in the FORMATS section, including those relevant to target-pane. With -b, shell-command is run in the background.
If -F is given, shell-command is not executed but considered success if neither empty nor zero (after formats are expanded).
In short, you can run a command conditionally, based on whether your “if” condition returns true. Interestingly, you can also run an “else” command without saying “else.”
Since we want to determine whether we’re on macOS or Linux, we can use the uname command. It returns Darwin for macOS and Linux for Linux.
The system-dependent commands to access the system clipboard are pbcopy on macOS and xclip on Linux. In addition, on macOS only, we must use the reattach-to-user-namespace utility to access the system clipboard in tmux.
One final note: we must wrap the commands that follow our “if” condition in quotes or braces. If braces, we don’t have to worry about escaping things, and we can specify multiple commands on multiple lines.
Here’s what I’ve put in my .tmux.conf, so that I can copy the selection, when in vi mode, into the system clipboard:
if-shell "uname | grep -q Darwin" {
bind-key -T copy-mode-vi 'y' send -X copy-pipe-and-cancel 'reattach-to-user-namespace pbcopy'
bind-key -T copy-mode-vi Enter send -X copy-pipe-and-cancel 'reattach-to-user-namespace pbcopy'
} {
bind-key -T copy-mode-vi 'y' send -X copy-pipe-and-cancel 'xclip -in -selection clipboard'
bind-key -T copy-mode-vi Enter send -X copy-pipe-and-cancel 'xclip -in -selection clipboard'
}
If uname returns “Darwin,” we run the settings in the first set of braces. If not, we run the second set.
Note: This is on tmux 3.0a (Linux) and tmux 3.1b (macOS). I’m not sure if this will work on other versions of tmux. You can get your tmux version by running tmux -V.