How to “copy to clipboard” in vim of Bash on Windows?

前端 未结 9 1010
执念已碎
执念已碎 2020-12-13 00:38

I used to use \"+y to copy text to system\'s clipboard, but it doesn\'t work in vim of Bash on Windows.

相关标签:
9条回答
  • 2020-12-13 01:37

    So there's a lot of answers, even on cross-network questions like this one on Super User, and this one on Vi and Vim, and unfortunately I'm not satisfied with any of them, so here's a different answer.

    Neovim

    If we're using Neovim, it's easy. We can follow their FAQ under How to use the Windows clipboard from WSL. The rest of this section is just context.

    By setting set clipboard=unnamedplus as if we were on a regular Linux system under X11, we tell Neovim to use the system registers as our default clipboard when yanking and pasting. Based on where Neovim is running, it chooses an appropriate provider to interact with these system registers. For v0.4.3, how that provider is chosen can be found at provider#clipboard#Executable.

    While this solution requires installing an external binary win32yank.exe, I'm personally very satisfied with it as both clip.exe and powershell.exe [Set|Get]-Clipboard pale in user experience to it. For example, clip.exe only supports copying, but fails to address the pasting issue. And while the Powershell Get-Clipboard cmdlet allows for us to paste into Vim from our Windows clipboard, it'll retain Windows line-endings, so there will be nasty ^Ms everywhere after pasting. In addition, it's a super small binary and only has to be installed within our WSL distro; nothing on the Windows side.

    curl -sLo /tmp/win32yank.zip https://github.com/equalsraf/win32yank/releases/download/v0.0.4/win32yank-x64.zip
    unzip -p /tmp/win32yank.zip win32yank.exe > /tmp/win32yank.exe
    chmod +x /tmp/win32yank.exe
    sudo mv /tmp/win32yank.exe /usr/local/bin/
    

    Vim

    If we're just using regular Vim, we can still use win32yank.exe, but we have to manually implement what Neovim would normally do for us. That is, the following:

    set clipboard=unnamed
    
    autocmd TextYankPost * call system('win32yank.exe -i --crlf', @")
    
    function! Paste(mode)
        let @" = system('win32yank.exe -o --lf')
        return a:mode
    endfunction
    
    map <expr> p Paste('p')
    map <expr> P Paste('P')
    

    First set the clipboard to the default register (@") as the system registers might not even be enabled if Vim was compiled without clipboard support like on my default Ubuntu WSL distro. Copies use an autocmd to pass the default register to win32yank, and pastes intercept the paste to assign the system clipboard to the default register.

    This works but it's noticeably jittery if performing several successive yanks and pastes quickly as we have to shell out every time. We can improve the yank by debouncing it:

    autocmd TextYankPost * call YankDebounced()
    
    function! Yank(timer)
        call system('win32yank.exe -i --crlf', @")
        redraw!
    endfunction
    
    let g:yank_debounce_time_ms = 500
    let g:yank_debounce_timer_id = -1
    
    function! YankDebounced()
        let l:now = localtime()
        call timer_stop(g:yank_debounce_timer_id)
        let g:yank_debounce_timer_id = timer_start(g:yank_debounce_time_ms, 'Yank')
    endfunction
    

    But this will require Vim 8, and if you have to upgrade, I'd recommend to just go with Neovim instead. Trying to implement proper caching and debouncing would be a headache!

    0 讨论(0)
  • 2020-12-13 01:37

    If you want use vim that bundled within WSL, you can only use the Clipboard provided by vim itself, which means you can only copy & paste within vim only.

    Or, you can try:

    1. Install VcXsrv and run it.
    2. export DISPLAY=localhost:0 in your WSL Bash.
    3. Run vim-gtk or vim-gnome(or any other GUI Apps) and try Clipboard across Linux and Windows.
    0 讨论(0)
  • 2020-12-13 01:41
    vmap <silent> <leader>y :w !clip.exe<CR><CR>
    "---------------------- :w !clip.exe
    " The core command, thanks to Mitchell's answer.
    "---------------------------------- <CR><CR>
    " The first <CR> closes the command;
    " the second <CR> suppresses "Press ENTER or type command to continue".
    "--- :h map-silent
    " This fix the flicker caused by external commands and <CR><CR>.
    "------------ :h leader
    " `:echo mapleader` to view your leader key.
    

    Standing on the shoulders of giants, I'm using the above solution now.

    0 讨论(0)
提交回复
热议问题