Skip to content

Instantly share code, notes, and snippets.

@antonkratz
Last active February 16, 2024 07:07
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save antonkratz/ebfcefdb5fdf266631e4985d65535322 to your computer and use it in GitHub Desktop.
Save antonkratz/ebfcefdb5fdf266631e4985d65535322 to your computer and use it in GitHub Desktop.
The essence of how copying and pasting works in vim.

Copy and paste with VIM across instances, SSH-borders, different clipboards

Use registers for copying and pasting WITHIN one vim instance

Vim saves text in registers. Selecting text and pressing y copies (yanks) text into a register, and pressing p pastes (puts) it.

You can see the register contents with :reg.

Named registers: there are named registers a-z.

Typing "ay will yank the current selection into named register a, and typing "ap will paste text from named register a.

Uppercase appends: typing "Ay will append the current selection to the contents of register a.

Also see

:help registers
There are ten types of registers:			*registers* *E354*
1. The unnamed register ""
2. 10 numbered registers "0 to "9
3. The small delete register "-
4. 26 named registers "a to "z or "A to "Z
5. three read-only registers ":, "., "%
6. alternate buffer register "#
7. the expression register "=
8. The selection and drop registers "*, "+ and "~ 
9. The black hole register "_
10. Last search pattern register "/

Registers are spaces in memory that can only be accessed by that instance of vim. This means that it is not possible to copy and paste text out of one vim into another vim, or into some bash, firefox or any program! Also, you cannot paste text from other vim instances or other software into vim using this mechanism! Then how can I copy and paste between vim instances, and between vim and other software?

Use the X clipboard to copy and paste IN AND OUT OF vim!

The answer is via the X clipboard. The X clipboard is the "normal" way of copying and pasting with ctrl-c, or by opening a context menu and selecting copy/cut/paste. A quick refresher on the X clipboard:

In X there are three clipboards: PRIMARY, SECONDARY and CLIPBOARD.

SECONDARY is obscure, apparently never used, and can be ignored in this context.

CLIPBOARD is what we normally understand under "the clipboard".

PRIMARY is the text that is currently selected by highlighting. This applies to text that is highlighted in vim visual mode, as well as "normal" highlighting in any program.

The key point here is that the CLIPBOARD clipboard can be read from and written to in the + (plus) register! And also that the PRIMARY clipboard can read from the * (star) register!

This way vim can interact with the X clipboard, and it is possible to copy in and out of vim.

Use the xclip command in your bash shell to inspect what is in the PRIMARY and CLIPBOARD clipoards. Copy some text (it should now be in CLIPBOARD and, for the time being, in PRIMARY), highlight some other text (it should now be in PRIMARY, while the contents of CLIPBOARD are untouched), and run these commands in bash to understand what is going on:

xclip -o -selection primary
xclip -o -selection clipboard

Connect with ssh -Y to remote machines to share the X clipoard

Section title already explains everything.

Now if you have vim running under GNU screen on a remote machine (with ssh -Y), you have a problem!

You have logged into a remote machine with ssh -Y and started GNU screen there; a vim is running within that GNU screen. Consider that this a vim running on a remote machine. If you try to move text between vim and the X clipboard using the + and * registers, this will use the X clipboards of the remote machine! The solution is to use X export when connecting to the remote machine in the first place. You can now happily copy and paste between the remote instance of vim and local software using the + and * registers.

However, this does not survive a re-connect!

Suppose you detach GNU screen, log out, log back in, re-attach GNU screen. The DISPLAY variable of the environment within GNU screen is inherited from the "outer" environment of the remote machine when creating the GNU screen instance. However, now that you have logged out and back in, the DISPLAY variable probably has changed.

Solution 1

Therefore, first in the outer environment figure out what DISPLAY is:

echo $DISPLAY

And then inside GNU screen set it accordingly:

export DISPLAY=:N.0

This still has problems! Suppose a vim was running all the time within GNU screen. There is no way to set the DISPLAY variable for that one. But it's better than nothing.

Solution 2

Applying patch 8.1.1307 should introduce the command :xrestore and thereby address this issue. See:

vim+screen: X11 server change disables X11 copy/paste #3649 vim/vim#3649

new command :xrestore to restore X11 connection after X11 server restart #844 vim/vim#844

patch 8.1.1307: cannot reconnect to the X server after it restarted https://github.com/vim/vim/commit/d4aa83af1d691fdabbc8e6aab36db2c96ea4d4b6

Solution 3

The best solution would be something like xpra. xpra is something like screen vor X. But xpra needs to run on both client and server, and you are very unlikely to have superuser rights on the server, and therefore you cannot install xpra.

Pasting into the search field with ctrl+r followed by the register

If you are on the vim command line, for example you typed / to start a search. Now you want to paste a text to start the search. The problem is that you cannot paste, because if you type, say, p, it does not paste but inserts the character p. The solution is to use ctrl+r and the address of the register from which you want to paste. Remember that the default register is called ".

Copy followed by multiple paste operations: The 0 register always contains the last yanked text

One operation you often want to do: you yank some text, you make a visual selection of some other text and paste, thereby overwriting that text. Now you want to make another visual selection, and paste again. But this does not overwrite with the text selected first, but with the last overwritten text! This is because by pasting, you deleted the second text. The solution is the 0 register. The 0 register always contains the last yanked text.

Install gvim to have the +xterm_clipboard feature in bash-vim , which is what you want

First, install vim with sudo apt -y install vim. This is the "Huge version without GUI". However it lacks xclipboard support. When using this version, you will encounter many unnecessary pain points. To include xclipboard support, install gvim on top of it: sudo apt -y install vim-gtk3. So this is not to have gvim (though gvim is sometimes nice to have), but to enable the +xterm_clipboard in bash-vim!

How to check if you have xclipboard support or not. Run vim --version. Look for a line that includes the string Features included (+) or not (-):. After that line comes a block with the included and not-included features. You want to have +xterm_clipboard.

Addendum: Other vim stuff unrelated to cut, copy, paste

A sane way of displaying the last line, even if it is wrapped

Often you will have wrapped lines. If a wrapped line flows out of the current terminal viewport, the entire line dissappears! This is disorienting and weird. A much saner way is to display what can be displayed:

set display=lastline

Arrow keys in insert mode print A, B, C, D instead of moving the cursor

The solution is :set nocompatible.

I want to specifiy the syntax highlighting regardless of the filename extension

Input file is named readme.txt but syntactically is a BASH script:

:set syntax=sh.

You can compile, build, install vim without being superuser/root

This is desirable if you are using vim on a remote server where you are not superuser/root; such machines typically have ancient vim installations, you probably want your own vim.

git clone https://github.com/vim/vim
cd vim
./configure --prefix=/cellar/users/kratz/vim81
make
make install

After this is done, do the relevant modifications to the PATH and EDITOR variables, and alias.

alias vi=/cellar/users/kratz/Downloads/vim/src/vim
git config --global core.editor "/cellar/users/kratz/Downloads/vim/src/vim"

Easier switching between buffers

Typically, you would rotate forward and backwards between buffers using :bn (next buffer) and :bp (previous buffer). However, these are five keystrokes! Shift-:-b-n-Enter. Ideally, I want to switch between buffers as easily as I do between screens in XFCE. In XFCE, I swtich between screen just by using control-F1, control-F2... directly addressing the screen. I do not know how to set up s/th like this in vim yet. But what is already a large improvement:

:nnoremap <F5> :buffers<CR>:buffer<Space>

Now, just by hitting F5 I can select the buffer from a list!

Build-in file system explorer

:Explore

Close the explorer with bdel (buffer delete).

Typing really fast by typing less

Abbreviation expansion

The key to producing very large amounts of text is not to type faster, but to type less. TextExpander was a very excellent program in the past, it is now a subscription-based software. You can have a TextExpander-like functionality within vim. This is extremely powerful:

:abbr dge differential gene expression
:abbr sfe The Encyclopedia of Science Fiction

Expansion will be triggered if the abbreviation is followed by a non-alphanumeric character. :ab lists defined abbreviations.

Completion

Ctrl-n completes based on the next similar word. Ctrl-p with the previous one.

What is the path of the file which I have in this buffer?

1 Ctrl-g

I am using

  • Xubuntu 16.04
  • VIM - Vi IMproved 7.4 (2013 Aug 10, compiled Nov 24 2016 16:44:48)
  • VIM - Vi IMproved 8.1 (2018 May 18, compiled Jan 18 2019 11:48:38)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment