Sometimes I would like to paste shell command invocations from my browser into my terminal and use bracketed pasting, which is pasting without running the command directly.
Since I am running tmux (tmux 3.1c) inside of xterm, in an i3 and X.Org desktop environment, I also want to use the X clipboard. The X clipboard is used when copying text from the browser as well.
Pasting things into tmux
The X clipboard can be accessed through many different commands, such as xsel
and xclip
. I decided to use xsel
, since it appears to be shipped with
Debian 11 by default. Other than the clipboard, X also maintains two more
selections called primary and secondary.
Users learn about primary selection when accidentally pressing the middle mouse button inside an X app and they paste something random.
tmux, on top of that, maintains its own copy buffers, of which there can exist an unlimited amount that can be named arbitrarily. To see the current buffers, you can run the following in a terminal:
tmux list-buffers
If we want to paste arbitrary text, for example, the current date, into a tmux
buffer called hello-world
, we can use the following command:
# The hyphen at the end indicates that we read from stdin
date -I | tmux load-buffer -b hello-world -
Then, to verify the contents of this buffer, we can dump it like so:
tmux show-buffer -b hello-world
If we want to paste something from the X clipboard, which we can dump by
running xsel --clipboard
, we need to do three things:
- Output the current X clipboard contents
- Read them into a tmux buffer
- Dump the contents of that tmux buffer into the currently active tmux pane
I came up with the following key binding, which I have saved into my
tmux.conf
:
bind-key ']' run "xsel --clipboard | tmux load-buffer - " \; paste-buffer -p
Using paste-buffer
with the -p
flag ensures we use bracketed pasting.
Conveniently, you can add more than one command to the same key binding
executed in series using an escaped semicolon.
Since my tmux prefix is C-b, I can press C-b and then ] to paste cleanly into most terminal applications that understand bracketed pasting.
Copying from tmux
To copy something from tmux, we make use of tmux’s vi mode, which I have configured in tmux like so:
set-window-option -g mode-keys vi
Once entering tmux, the default configuration is to copy the selection to a tmux buffer using the Enter key. Instead, I would like to copy it to the X clipboard. This can be achieved with the following key binding:
bind-key -T copy-mode-vi 'Enter' send-keys -X copy-pipe-and-cancel 'xsel --clipboard --input'
Then, when you enter vi copy mode, you can copy your selection to the X clipboard.
Scenarios made possible by this
I often copy code snippets, boilerplate, and so on from documentation and paste
it into Neovim. This is possible out of the box since Neovim integrates with
the x clipboard. It breaks down, though, when editing files as root. For
example, while using sudo nano /etc/$SOME_CONFIG_FILE
, neither GNU nano
support accessing the X clipboard, nor is it being shared between a sudo
session and the currently active desktop. Using tmux to gently wrap around X is
tremendously helpful here.
Copying and pasting text is challenging due to troubles with RSI that I
currently face. Using
the preceding configuration, I can now easily copy things from my terminal. For
example, I can paste the output of dmesg
into my browser without having to
resort to overly complex keyboard chords and precise mouse cursor placements in
xterm.
This is yet another triumph for open and configurable software. Being able to customize your desktop environment is essential for accessible software development.