17

I am trying to use Vim to locate and copy/paste some code I need to analyze and take notes on. I am using Debian, in a Windows WSL environment. That's what makes this tricky.

The regular "yank and put to global register" commands "+y and "*y commands didn't work.

On the other hand, the brute force approach where I just use the mouse to scrape the terminal text won't work either. Strangely, WSL terminal has mouse support, and Vim can track its movements, select in visual mode, etc. So Vim intercepts the selection command, and then there is nothing selected for ctrl-shift-c to copy into the Windows clipboard.

I know the WSL terminal supports copy and paste, and I can successfully do it if I cat my file to the screen, and copy and paste that using ctrl-shift-c and ctrl-v. But then I lose out on ease of navigation.

What's the best way to copy text out of Vim inside a WSL terminal and into the windows clipboard?

5
  • 4
    If you don't want vim to handle your mouse so you can still highlight and copy as you would anything else from the terminal, you should be able to :set mouse= Commented May 1, 2020 at 22:39
  • Can you use clip.exe to access the clipboard from WSL? If so, select the lines visually them run :w !clip.exe. (Source for the clip.exe suggestion: raymondcamden.com/2017/10/19/…)
    – filbranden
    Commented May 2, 2020 at 3:31
  • 2
    I'm using Neovim and went with the instructions on their FAQ at github.com/neovim/neovim/wiki/…. Otherwise, I think How to “copy to clipboard” in vim of Bash on Windows? can help you out. There's a few solutions that don't require installing an X server on Windows. Commented May 18, 2020 at 8:03
  • @nomen Check my answer. I think it is the best one so far.
    – 71GA
    Commented Apr 5, 2022 at 12:11
  • I run vim inside tmux. Tmux has a "vim" mode copy paste system where you can use vim movement commands to copy. There are config options to tmux that allow the use of clip.exe which is available under WSL to send to the clipboard. It's not perfect and actual vim clipboard is not connected, you have to use the tmux system, but you also get the advantage of using the tmux terminal multiplexor which gives you a consistent reliable environment everywhere. If you're interested request in a comment and I'll post an answer describing the setup.
    – NeilG
    Commented May 13, 2023 at 2:46

6 Answers 6

44

Answer is, do a vim visual selection then do the command:

:'<,'>w !clip.exe

This pipes the current selection out to the shell command clip.exe, which utilizes WSL's ability to execute Windows executables (even with a pipeline). Text piped to clip.exe goes to the Windows clipboard.

Also, this command saves the whole file to the clipboard (not the requirement):

 :w !clip.exe
5
  • 2
    Wow - It's really rare when I see a new user provide a correct and useful answer to an old question! Congratulations, and welcome to Stack Overflow! One small suggestion - Provide some detail on why this works, so people better understand the mechanics and can adjust it to other uses. I'm going to make a small edit to it to add this info. Commented Jul 9, 2021 at 15:11
  • 1
    For those wondering, pasting into WSL Vim from clipboard can still be done by right-clicking while in insert mode.
    – mbomb007
    Commented Jan 7, 2022 at 16:32
  • Command equivalent for pasting is powershell.exe Get-Clipboard. Caveats due to UNIX and Windows convention mismatch: the output of powershell.exe Get-Clipboard will have carriage returns on each line, and the UNIX norm of having a trailing newline at the end of the last line is interpreted by the Windows clipboard as an extra empty line at the end.
    – mtraceur
    Commented Feb 15, 2023 at 5:08
  • So a fuller solution is probably perl -pe 'chomp if eof' | clip.exe for copy (to chomp off one trailing newline if there is one), and powershell.exe Get-Clipboard | sed 's/\r$//' for paste (to delete the spurious carriage returns at the end of each line). This is the closest we get to a translation between UNIX and Windows text semantics. (Sadly, the trailing newline workaround means there's an ambiguity/collision on the round trip - if you intentionally send data with no trailing newline to the Windows clipboard, you'll get back data with a trailing newline.)
    – mtraceur
    Commented Feb 15, 2023 at 5:34
  • this tip actually works! even though it defeats the purpose of efficiency. But obviously it only applies to local WSL vim. If you e.g. ssh somehwere then it seems you are out of luck without really awkward xserver piping. Easier to mouse select in terminal window but don't forget to disable line numbers before...
    – rogerovo
    Commented Mar 24, 2023 at 21:14
2

On Linux, Vim's clipboard support is intimately tied to X. If you want the same level of integration between WSL and the rest of Windows as you are used to in a proper Linux Box you will have to install a Windows X Server.

  1. On the Linux side, install a clipboard-enabled build of Vim. The vim-gtk package is fine.

  2. On the Windows side, install an X Server like VcXsrv (there are many alternatives, you are on your own to find the one that best suit your needs).

  3. You generally have to edit a couple of configuration files on the Linux side for your X clients to use the right X Server. What to do exactly will depend on the X Server you choose.

  4. In Vim, on the Linux side, use either "+ or "* as you would if you where on a genuine Linux box.

2
  • I did this, and it takes a really long time for vim to start up now when I run vim somefile.
    – mbomb007
    Commented Nov 24, 2020 at 15:15
  • @mbomb007, FWIW, I wrote this answer a few weeks after starting a gig for $BIG_PHARMA where I had to work on one of their beaten-up Lenovos and figured out that exact setup. The whole machine was a slug, mind you, but I didn't notice any particular startup slowdown. Long startup times can be due to Vim's inability/difficulty to connect to the X server. See if you have all the config done properly.
    – romainl
    Commented Nov 24, 2020 at 17:25
2

Windows's WSL2 now supports X11 by default (see here), so there is no need to install third part packages anymore for it to work.

Neovim does therefore support copying and pasting between Windows and itself.

Vim on the other hand, at least on the version that is installed in Debian and Ubuntu, comes without support for the shared clipboard (see this post to understand why).

To enable it you either have to compile vim yourself with the clipboard compilation flags enabled, or you can install the vim-gtk package, which has been compiled with those flags enabled, and it will work fine. In my case, using WSL with Debian 12, the name of the vim-gtk package is vim-gtk3.

1

Like romainl mentioned, clipboard is at X level. So the most important step is you need to have an X-server running on Windows, and you need to set DISPLAY variable on Linux to point to X-server. Then in neovim set clipboard=unnamedplus or vim set clipboard=unnamed to link to the system clipboard.

Follow this nice gist should make things work.

For me I use fish shell, the wsl specific logic becomes in your config.fish.

if uname -r | grep 'microsoft' > /dev/null 
  set -l LOCAL_IP (cat /etc/resolv.conf | grep nameserver | awk '{print $2}')
  set -xg DISPLAY $LOCAL_IP:0
end

1

I have "WSL Debian" installed and I installed a neovim package inside. PAckage installs a nvim text editor without a clipboard support. I can verify this like this:

$ nvim --version

NVIM 0.1.7
Build type: None
Compilation: /usr/bin/cc -g -O2 -fdebug-prefix-map=/build/neovim-HEl3mV/neovim-0.1.7=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -DDISABLE_LOG -Wconversion -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1  -Wall -Wextra -pedantic -Wno-unused-parameter -Wstrict-prototypes -std=gnu99 -Wvla -fstack-protector-strong -fdiagnostics-color=auto -DINCLUDE_GENERATED_DECLARATIONS -DHAVE_CONFIG_H -D_GNU_SOURCE -I/build/neovim-HEl3mV/neovim-0.1.7/build/config -I/build/neovim-HEl3mV/neovim-0.1.7/src -I/usr/include -I/usr/include -I/usr/include -I/usr/include -I/usr/include -I/usr/include -I/usr/include -I/build/neovim-HEl3mV/neovim-0.1.7/build/src/nvim/auto -I/build/neovim-HEl3mV/neovim-0.1.7/build/include
Compiled by [email protected]

Optional features included (+) or not (-): +acl   +iconv    +jemalloc +tui
For differences from Vim, see :help vim-differences

   system vimrc file: "$VIM/sysinit.vim"
  fall-back for $VIM: "/usr/share/nvim"

Note that under Optional features included there is no +clipboard entry and this means that my nvim doesn't support clipboard out of the box.

Then I open the nvim editor and execute a command :CheckHealth to get this feedback:

## Clipboard
  - WARNING: No clipboard tool found. Using the system clipboard won't work.
    - SUGGESTIONS:
      - See |clipboard|

This tells me (a) that clipboard is not working currently and (b) to use a command :help clipboard inside the nvim to get more info. So I execute this command and I can read this:

Clipboard access is implicitly enabled if any of the following clipboard tools
are found in your `$PATH`.

  - xclip
  - xsel (newer alternative to xclip)
  - pbcopy/pbpaste (Mac OS X)
  - lemonade (for SSH) https://github.com/pocke/lemonade
  - doitclient (for SSH) http://www.chiark.greenend.org.uk/~sgtatham/doit/

The presence of a suitable clipboard tool implicitly enables the '+' and '*'
registers.

If you want to ALWAYS use the clipboard for ALL operations (as opposed
to interacting with the '+' and/or '*' registers explicitly), set the
following option:

    set clipboard+=unnamedplus

This tells me that even though clipboard support was not compiled in, it is still possible to implicitly enable it if we only install e.g. xsel. So I do it:

$ sudo apt install xsel

This also tells me to put the below line in my ~/.config/nvim/init.vim:

$ set clipboard+=unnamedplus

It looks like this should already be solved, but at this point things will not yet work. Why is that? This is because xsel (as it's name implies) is a graphical application that needs X server in order to run!

So we install X server for Windows! One option is to simply install "VcXSrv"(link). This will create a "Xlaunch" launcher in the Windows start menu. We run this launcher and just click next until the "Extra settings" window. Here we make sure to check all the boxes like shown below and click "Next".

enter image description here

Now we will store our "Xlaunch" configuration by pressing "Save Configuration" and make sure to store our configuration as:

C:\Users\<Username>\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\config.xlaunch

This will make sure that X server will start with the same configuration whenever Windows starts! Note that X server has to be running before starting the "WSL Debian".

Now we click "Finish" and for this session X server will run.

Now inside the "WSL Debian" we only have to export a DISPLAY enviromental variable which is where X server applications e.g xset will search for a working X server session. Our job is to point them to our Windows machine! So we can export DISPLAY like this:

LOCAL_IP=$(cat /etc/resolv.conf | grep nameserver | awk '{print $2}')
export DISPLAY=$LOCAL_IP:0

If you want you can add these two lines in the ~/.bashrc file on "WSL Debian" so that they will always be exported when you open an interactive terminal.

Now everything should work.

0

While the answer with :'<,'>w !clip.exe is certainly correct, I found it a little lacking in terms of usability. Typing the command is tedious. Another drawback is that it takes entire lines, not specific characters. Finally, if block selection mode is used, '< and '> don't help much.

If the line mode is enough, then here's how to map it to a key, e.g. F5 in this case:

:xnoremap <silent> <F5> :w !clip.exe<CR><CR>

(xnoremap introduces a shortcut that works only in visual mode, <silent> suppresses command output, <F5> denotes the shortcut, the rest of the line is literally when vim processes when the shortcut is pressed -- if you try it manually, you'd see '<,'> is added automatically, so no need to add it to the command; finally, the second <CR> is to suppress Press ENTER or type command to continue message that appears).

The approach does not address block selection mode, though. So, what I find useful, is to put to Windows clipboard something that was yanked when I need it. To access yanked text, there's "0" register in vim. To obtain it, we can use getreg("0") function call. And to pass this as input to clip.exe -- system function. So, the full command with the mapping to F5 key will look like this:

:noremap <silent> <F5> :call system("clip.exe", getreg("0"))<CR>

It will work in normal mode only because of noremap.

Not the answer you're looking for? Browse other questions tagged or ask your own question.