Key Bindings for Copy and Paste Under X11 (Shallow Thoughts)

Akkana's Musings on Open Source Computing and Technology, Science, and Nature.

Fri, 11 Sep 2020

Key Bindings for Copy and Paste Under X11

In the previous article I wrote about how the two X selections, the primary and clipboard, work. But I glossed over the details of key bindings to copy and paste the two selections in various apps.

That's because it's complicated. Although having the two selections available is really a wonderful feature, I can understand why so many people are confused about it or think that copy and paste just generally doesn't work on Linux -- because apps are so woefully inconsistent about their key bindings, and what they do have is so poorly documented.

"Why don't they all just use the standard Ctrl-C, Ctrl-V?" you ask. (Cmd-C, Cmd-V for Mac users, but I'm not going to try to include the Mac versions of every binding in this article; Mac users will have to generalize.)

Simple: those keys have well-known and very commonly used bindings already, which date back to long before copy and paste were invented. Ctrl-C in a terminal kills whatever program is currently running. Ctrl-V quotes the next character so you can insert it into your command line. Programs that don't have those bindings may have other uses for those keys: in Emacs, Ctrl-C is a command prefix, and Ctrl-V goes down one page (V looks sort of like a down-arrow). And sure, you could use the Page Down key instead of Ctrl-V: but Ctrl-V is a lot faster to type because you can keep your hands on the home row and don't need to look at the keyboard (well, at least you can if you rebind the CapsLock key to be Ctrl).

Fortunately, most X apps (not all) have configurable keybindings, so you can improve things a lot and make a set of key bindings that you find easy to remember.

Some Default Bindings

Let's start with the sad state of defaults. Here are some defaults for some common text-handling apps:
App Paste Primary Copy Clipboard Paste Clipboard Customizable?
Firefox middlemouse Ctrl-C
Ctrl-Insert
Ctrl-V
Shift-Insert
No
Emacs middlemouse Meta-w (only for text inside Emacs) Ctrl-y
Shift-Insert
Yes
Gvim middlemouse
Shift-Insert
C-y "+P (only in command mode) Yes
Xterm middlemouse
Shift-Insert
Shift-Ctrl-Insert
Ctrl-Insert   Yes
Urxvt middlemouse
Shift-Insert
Ctrl-Alt-C (only for text within urxvt)
Ctrl-Insert (anywhere)
Ctrl-Alt-V Yes
Gnome Terminal middlemouse
Shift-Insert
Ctrl-Shift-C (only for text highlighted inside the gnome-terminal), Ctrl-Insert (for selections anywhere) Ctrl-Shift-V ?
LibreOffice middlemouse
Shift-Insert
Ctrl-C Ctrl-V ? (see below)

Many of these apps have more than one key bound to each function, and most apps don't make it terribly easy to discover key bindings that aren't the primary binding in a menu, so I make no claim that this table is anywhere near complete. Updates are welcome.

You'll note that a few programs have key bindings that only apply to text selected within its own window. In general, it's nice to have Copy take whatever's in the primary selection -- regardless of what window it's in -- and copy it to the clipboard. Most of the time you'll be typing your Copy key binding in the same window that has the selection, not necessarily always, and that can lead to confusion.

How to test:

When you're testing new key bindings, or just checking defaults like I did to make that table, it's important to know what's in the two selections so you can see if what's getting pasted is what you expect.

Here's an easy way to set up your selections for testing:

$ alias setsel='echo PRIMARY | xsel -ip; echo CLIPBOARD | xsel -ib'
$ alias showsel='PRIMARY is $(xsel); echo CLIPBOARD is $(xsel -b)'
$ setsel
$ showsel
PRIMARY is PRIMARY
CLIPBOARD is CLIPBOARD

Now, if you try some key bindings in any app, you should see PRIMARY or CLIPBOARD depending on which selection you're inserting.

The only caveat is that you should check frequently to make sure the selections are what you think they are. For instance, with those Ctrl/Shift-Insert bindings I can never keep straight which one is supposed to copy and which is paste. So I'm always typing the one for Copy when I meant Paste, and now I've not only not pasted, but I've replaced the selection I was trying to paste. And of course, anything you select with your mouse will stomp the primary selection, and many emacs killring operations will replace either the primary, clipboard or both depending your emacs version and the values of several different variables.

So I recommend running setsel before each test, so you're sure you're starting out with the right selections.

Customizing App Key Bindings

Some apps let you customize their key bindings. Since the default key bindings are so inconsistent, as you can see in the table above, it can help to pick a set of bindings you like.

I decided to standardize on Ctrl-Shift-C and Ctrl-Shift-V for copying and pasting the clipboard in programs where I had the option. In some cases I also show bindings for inserting the primary selection (because it's useful to have a way to do that at the text cursor location, not the mouse pointer location, and to have a way to insert the selection without taking your hands off the keyboard). And in some cases I show how to set up Ctrl/Shift-Insert bindings, because it isn't always obvious how to bind non-alphanumeric keys.

Xterm

Xterm can rebind keys through the VT100*translations mechanism:

*VT100*translations:    #override \n\
    Shift Ctrl  C: copy-selection(CLIPBOARD) \n\
    Shift Ctrl  V: insert-selection(CLIPBOARD) \n\
    Alt  V: insert-selection(PRIMARY) \n\
    Ctrl  Insert: copy-selection(CLIPBOARD) \n\
    Shift  Insert: insert-selection(CLIPBOARD)

The first two lines are the only important ones. I only included the other four as an example of how to bind PRIMARY and how to bind to non-alphanumeric keys like Insert.

You'll find some recommendations for setting Xterm so that any selection made within it automatically gets copied to the clipboard as well as the primary selection:

XTerm*selectToClipboard: true

Personally, I definitely don't want that. The whole advantage of having a clipboard selection is that it doesn't get overwritten unless you explicitly ask for it. Besides, this would only help for text selected inside the Xterm window, not for text anywhere else.

Urxvt

Urxvt has tons of bells and whistles, and you need to enable a Perl extension in order to customize these bindings. It also has some weird ISO 14755 features enabled by default that confuse things (I'm not clear what they're even for), so you have to disable those. So:

URxvt.iso14755: false
URxvt.iso14755_52: false

URxvt.perl-ext-common: eval

URxvt.keysym.Shift-Control-Insert: eval:paste_clipboard
URxvt.keysym.Shift-Control-V: eval:paste_clipboard
URxvt.keysym.Shift-Control-C: eval:selection_to_clipboard
URxvt.keysym.M-v: eval:paste_primary

If you have URxvt.perl-ext-common: default, you might already have the "eval" extension and might not need to specify it.

Urxvt also has an option similar to Xterm's selectToClipboard that automatically copies every selection to the clipboard as well as primary, for those who want that:

URxvt.perl-ext-common: selection-to-clipboard

Emacs

Emacs is complicated (what else is new?) There are several seemingly redundant variables you have to set, and several different functions whose names aren't all that clear, and none of it is really documented, and they all change with each release and a lot of the functions recommended on Comments on CopyAndPaste are out of date and now marked as deprecated. This page on the Emacs Clipboard is a little better, but still very incomplete.

But don't give up hope: you can get emacs to work well with both primary and clipboard selections.

An obvious function to try is clipboard-yank (formerly x-clipboard-yank, which inserts into the buffer whatever is in the X clipboard. Plain yank inserts the "most recent kill". Depending on the values of the variables select-enable-primary and select-enable-clipboard (formerly x-select-enable-primary and x-select-enable-clipboard) and whether something has been recently killed, the most recent kill might correspond to the X clipboard, the X primary selection, or neither one.

But I recommend not using either one. Both yank and clipboard-yank have a tendency to stomp the "other" selection (e.g. clipboard-yank would replace the primary selection with the clipboard). And they're inconsistent: most of the time they insert the selection you want, but sometimes they insert the other one.

Fortunately, there's a function, x-selection, that fetches the selection you specify. You can use that to make a much more reliable paste function. This is what I end up with in my .emacs:

;; I'm not sure these two are actually needed:
(setq select-enable-clipboard nil)
(setq select-enable-primary t)

;; C-y inserts the PRIMARY:
(global-set-key (kbd "C-y")
                (lambda () (interactive)
                  (insert (x-selection 'PRIMARY))))
;; C-S-v inserts the CLIPBOARD:
(global-set-key (kbd "C-S-v")
                (lambda () (interactive)
                  (insert (x-selection 'CLIPBOARD))))

;; This copies whatever's selected in emacs or in the kill ring
;; to both primary and clipboard X selections.
(global-set-key (kbd "C-S-c") 'clipboard-kill-ring-save)

;; Copy to the kill ring (and primary) when you select with the mouse:
(setq mouse-drag-copy-region t)

;; When something is selected and you type, replace the selected text.
(delete-selection-mode t)

And now you're (at least in theory) insulated from the constantly-changing meanings of yank, clipboard-yank, and the assorted select-enable variables.

GVim

I normally use vim in a terminal, so I haven't messed with gvim bindings much. But the best pages I found were Accessing the System Clipboard and How to Make Vim Paste from and Copy to System Clipboard.

The real hassle of vim is that its default bindings don't give you a way to paste the clipboard from insert mode; you have to get out of insert mode then type a lengthy and unintuitive set of keystrokes. Try this for bindings that work from insert mode as well as command mode:

" copy and paste
vmap  "+yi
vmap  "+c
vmap  c"+p
imap  "+pa

Libre Office

Ugh, don't get me started on Libre Office key bindings. LO does have a mechanism for rebinding keys. But it's not a simple text file; it's bound up in their elaborate preferences mechanism which changes with each release. So you have to go in laboriously and click around to set each of your bindings by hand, guessing at which of the inconsistent command names might be the one you want. And when the next LO release comes out, it will forget all your bindings and you'll have to do it all over again.

So I haven't actually looked at whether copy and paste of primary and clipboard are rebindable, because I know that even if I figure it out, it will all change in the next version.

This is the biggest reason I avoid using Libre Office. Not because of selection/clipboard bindings, but because of the readline/emacs bindings that work in every other app I use, but in LO it takes several hours of clicking around trying to get everything working so I can type properly, and after the fifth time or so, I can't face doing it all over again.

Firefox

Firefox is even worse than LibreOffice for customizability. Sometimes you can change key bindings by unpacking omni.ja, editing the right file then repackaging it; but you'll have to do it again every time a new Firefox update comes out (every few weeks or so), there are a lot of keys that are hardwired so you have to find the place to override the hardwired binding as well as the place to set up your new one, and this is all very brittle: any little change to omni.ja is likely to break it all and force you to start over from scratch. There are many bugs filed, some dating back to the last millennium (really!), asking for custom key bindings, but so far Mozilla has staunchly resisted any requests, suggestions or patches along those lines.

Fortunately, most people don't need to do a lot of typing in Firefox, unless you use Gmail's webmail interface, and I'm guessing most people who use that are fine with the basic Ctrl-X Ctrl-C.

Tags: , , , , ,
[ 12:54 Sep 11, 2020    More linux | permalink to this entry | ]

Comments via Disqus:

blog comments powered by Disqus