Sometimes I would like to paste shell command invocations from my browser into my terminal and use bracketed pasting, i.e., pasting without running the command directly.
Since I am running tmux (tmux 3.1c) inside of xterm, in an i3 and Xorg 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 various 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.
The primary selection is often accidentally discovered when accidentally pressing the middle mouse button pastes text where it is not supposed to go in an X application.
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
So, 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 multiple commands 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 configuration described above, 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.