如何在 Windows 上的 Bash 的 vim 中“复制到剪贴板”?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/44480829/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 16:12:27  来源:igfitidea点击:

How to "copy to clipboard" in vim of Bash on Windows?

bashvimwindows-subsystem-for-linux

提问by nbystndr

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

我曾经用来"+y将文本复制到系统的剪贴板,但它在 Windows 上的 Bash 的 vim 中不起作用。

回答by davidanderle

Since neither "*y nor "+y (...) work, an alternative is the following:

由于 "*y 和 "+y (...) 都不起作用,因此替代方法如下:

Add this to your .vimrcand create a file called ~/.vimbuffer

将此添加到您的.vimrc并创建一个名为~/.vimbuffer

" copy (write) highlighted text to .vimbuffer
vmap <C-c> y:new ~/.vimbuffer<CR>VGp:x<CR> \| :!cat ~/.vimbuffer \| clip.exe <CR><CR>
" paste from buffer
map <C-v> :r ~/.vimbuffer<CR>

Higlight any text using visual or visual-block and press ctrl-c. Paste copied text outside your terminal using the usual method or paste copied text to any vim pane using ctrl-vin normal or visual mode.

使用视觉或视觉块突出显示任何文本,然后按ctrl-c。使用通常的方法将复制的文本粘贴到终端之外,或者使用ctrl-v普通或可视模式将复制的文本粘贴到任何 vim 窗格中。

Ctrl-cyanks the selected text, overwrites ~/.vimbufferwith the selected text, runs a UNIX command to pipe out the data from ~/.vimbufferto clip.exe.

Ctrl-c洋基选定的文本,重写~/.vimbuffer与所选择的文本,从运行UNIX命令到管出来的数据~/.vimbuffer,以clip.exe.

Any further improvement (e.g.: making command silent) is much appreciated!

任何进一步的改进(例如:使命令静音)都非常感谢!

Edit:command can now copy strings with any length, not just whole lines. Old command:

编辑:命令现在可以复制任意长度的字符串,而不仅仅是整行。旧命令:

vmap <C-c> :w! ~/.vimbuffer \| !cat ~/.vimbuffer \| clip.exe <CR><CR>

vmap <C-c> :w! ~/.vimbuffer \| !cat ~/.vimbuffer \| clip.exe <CR><CR>

回答by ifconfig

To copy to the clipboard from within vim in Bash on Windows 10, hold Shiftand drag the cursor over text. then press enter

要从 Windows 10 上的 Bash 中的 vim 复制到剪贴板,请按住Shift并将光标拖到文本上。然后按enter

A selection should look like this before pressing enter:

在按下之前,选择应如下所示enter

Selection should look like this before pressing ENTER

在按 ENTER 之前,选择应如下所示

EDIT: This only works with text that fits on the screen all at once; it cannot be used to copy blocks of text that span many 'screens'

编辑:这仅适用于一次性适合屏幕的文本;它不能用于复制跨越许多“屏幕”的文本块

回答by Top Cat

If you don't want to set up an X server, this method will allow you to copy selected text to your clipboard using the clip.exeprogram which comes shipped with Windows.

如果您不想设置 X 服务器,此方法将允许您使用clip.exeWindows 附带的程序将所选文本复制到剪贴板。

The code snippets below can be placed in your .vimrcfile.

下面的代码片段可以放在您的.vimrc文件中。

First create a helper function which will return the currently selected text as a string. We can use this function to pipe highlighted text into clip.exe:

首先创建一个辅助函数,它将当前选定的文本作为字符串返回。我们可以使用此函数将突出显示的文本通过管道传输到clip.exe

func! GetSelectedText()
    normal gv"xy
    let result = getreg("x")
    return result
endfunc

The systemfunction will allow us to call native programs and pipe parameters into them. The snippet below sets up two key mappings; the first line will allow Ctrl+Cto be used for copying text and the second will allow Ctrl+Xfor cutting text:

system函数将允许我们调用本机程序和管道参数。下面的代码段设置了两个键映射;第一行将允许Ctrl+C用于复制文本,第二行将允许Ctrl+X用于剪切文本:

noremap <C-C> :call system('clip.exe', GetSelectedText())<CR>
noremap <C-X> :call system('clip.exe', GetSelectedText())<CR>gvx

After saving the changes to your .vimrcfile you should be good to go.

将更改保存到.vimrc文件后,您就可以开始使用了。

If you are going to be using your .vimrcon multiple systems, I suggest wrapping these mappings in an ifstatement to check if clip.exeactually exists:

如果您打算.vimrc在多个系统上使用您的,我建议将这些映射包装在一个if语句中以检查是否clip.exe确实存在:

if !has("clipboard") && executable("clip.exe")
    noremap <C-C> :call system('clip.exe', GetSelectedText())<CR>
    noremap <C-X> :call system('clip.exe', GetSelectedText())<CR>gvx
endif

The above will also allow Vim to ignore those key bindings if it has direct access to the system clipboard.

如果 Vim 可以直接访问系统剪贴板,上述内容还将允许 Vim 忽略这些键绑定。

You might also want to add keybindings for when vim does have access to the clipboard, like so:

您可能还想为 vim 可以访问剪贴板时添加键绑定,如下所示:

if has("clipboard")
    vnoremap <C-X> "+x
    vnoremap <S-Del> "+x

    vnoremap <C-C> "+y
    vnoremap <C-Insert> "+y

    map <C-V>       "+gP
    map <S-Insert>      "+gP

    cmap <C-V>      <C-R>+
    cmap <S-Insert>     <C-R>+
endif

Which will come in handy if you are using Vim natively on Windows or are using vim-gtkon a Linux system.

如果您在 Windowsvim-gtk上本地使用 Vim 或在 Linux 系统上使用,这将派上用场。

回答by Mitchell P

If you only care about copying complete lines, you can use Vim's ability to pipe the file contents to an external program. So you can do

如果您只关心复制完整的行,您可以使用 Vim 的功能将文件内容通过管道传输到外部程序。所以你可以做

:w !clip.exe

:w !clip.exe

to pipe into clip.exe. If you need specific lines, say 2 through 10, you can just do :2,10w !clip.exe.

管道进入clip.exe. 如果你需要特定的行,比如 2 到 10,你可以只做:2,10w !clip.exe.

See Piping buffer to external command in Vim

参见Vim 中的管道缓冲区到外部命令

回答by reker

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.

如果你想使用捆绑在 WSL 中的 vim,你只能使用 vim 本身提供的剪贴板,这意味着你只能在 vim 中复制和粘贴。

Or, you can try:

或者,您可以尝试:

  1. Install VcXsrvand run it.
  2. export DISPLAY=localhost:0in your WSL Bash.
  3. Run vim-gtk or vim-gnome(or any other GUI Apps) and try Clipboard across Linux and Windows.
  1. 安装VcXsrv并运行它。
  2. export DISPLAY=localhost:0在你的 WSL Bash 中。
  3. 运行 vim-gtk 或 vim-gnome(或任何其他 GUI 应用程序)并尝试跨 Linux 和 Windows 的剪贴板。

回答by Pavel Sapehin

Combining the information above, it's possible to copy simple text from any register to a clipboard without using any keybinding (what can be more convenient in some cases). For example, if you want to copy last yanked text to the windows clipboard, enter the following command (start typing):

结合上述信息,可以在不使用任何键绑定的情况下将简单文本从任何寄存器复制到剪贴板(在某些情况下会更方便)。例如,如果要将上次拉取的文本复制到 Windows 剪贴板,请输入以下命令(开始输入):

:call system('clip.exe', '

Now press Ctrl+r, followed by a register +. It will paste a text from the specified register. Next, close the single quote and the parentheses. The command will look like:

现在按Ctrl+ r,然后是寄存器+。它将粘贴来自指定寄存器的文本。接下来,关闭单引号和括号。该命令将如下所示:

:call system('clip.exe', 'a text from 0 register')

Press Enter, done!

Enter,完成!

回答by Enno

Below are mappings

下面是映射

  • in normal mode cy, cyyand cY(=Clipboard Yank) that copy, respectively, the given text object, line(s), rest of the line from the cursor position to the clipboard, and
  • in visual mode Ythat copies the visual selection to the clipboard,
  • 在正常模式下cycyycY(=Clipboard Yank) 分别复制给定的文本对象、行、从光标位置到剪贴板的行的其余部分,以及
  • Y将视觉选择复制到剪贴板的视觉模式下,

independent of whether Vim is started in WSL or not.

与 Vim 是否在 WSL 中启动无关。

nnoremap                    cy                   "+y
nnoremap                    <sid>(mgu)   m`_
onoremap                    <sid>(gu)        g_
nnoremap                    <sid>(ggg)   g``
nmap         <expr>     cyy                  '<sid>(mgu)cy' . v:count1 . '<sid>(gu)' . '<sid>(ggg)'
nmap                            cY                   cy<sid>(gu)

xnoremap Y  "+y

if has('unix') && executable('clip.exe')
    " From :help map-operator
    function! SendToClip(type, ...) abort
        if a:0
            " Visual mode
            normal! gv"+y
        elseif a:type ==# 'line'
            normal! '[V']"+y
        elseif a:type ==# 'char'
            normal! `[v`]"+y
        endif

        call system('clip.exe', @+)
    endfunction

    nnoremap <silent> cy            :set operatorfunc=SendToClip<cr>g@
    xnoremap <silent> Y             :<C-U>call SendToClip(visualmode(),1)<cr>
endif

回答by Andrey Kaipov

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.

因此,有很多答案,即使在跨网络的问题,像这样一个超级用户,而这一项就Vi和Vim的,不幸的是我有任何不满意他们的,所以这里的一个不同的答案。

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.

如果我们使用 Neovim,那很容易。我们可以在How to use the Windows clipboard from WSL下关注他们的常见问题解答。本节的其余部分只是上下文。

By setting set clipboard=unnamedplusas 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.

通过设置set clipboard=unnamedplus好像我们在 X11 下的常规 Linux 系统上,我们告诉 Neovim 在拉取和粘贴时使用系统寄存器作为我们的默认剪贴板。根据 Neovim 的运行位置,它会选择合适的提供程序与这些系统寄存器进行交互。对于 v0.4.3,可以在provider#clipboard#Executable 中找到如何选择该提供程序

While this solution requires installing an external binary win32yank.exe, I'm personally very satisfied with it as both clip.exeand powershell.exe [Set|Get]-Clipboardpale in user experience to it. For example, clip.exeonly supports copying, but fails to address the pasting issue. And while the Powershell Get-Clipboardcmdlet 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.

虽然这种解决方案需要安装一个外部二进制win32yank.exe,我个人非常满意,它都clip.exepowershell.exe [Set|Get]-Clipboard用户体验到它苍白。比如clip.exe只支持复制,无法解决粘贴问题。虽然 Powershell Get-Clipboardcmdlet 允许我们从 Windows 剪贴板粘贴到 Vim 中,但它会保留 Windows 行尾,因此^M粘贴后到处都是 s 。此外,它是一个超小的二进制文件,只需安装在我们的 WSL 发行版中即可;Windows 方面没有任何内容。

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
mv /tmp/win32yank.exe ~/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:

如果我们只是使用普通的 Vim,我们仍然可以使用win32yank.exe,但我们必须手动实现 Neovim 通常为我们做的事情。即,以下内容:

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.

首先将剪贴板设置为默认寄存器 ( @"),因为如果 Vim 是在没有剪贴板支持的情况下编译的,就像我的默认 Ubuntu WSL 发行版一样,系统寄存器甚至可能不会启用。副本使用 autocmd 将默认寄存器传递给win32yank,并粘贴拦截粘贴以将系统剪贴板分配给默认寄存器。

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:

这有效,但如果我们每次都必须快速执行几次连续的猛拉和粘贴,它会明显紧张。我们可以通过去抖动来改善 yank:

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!

但这将需要 Vim 8,如果您必须升级,我建议您改用 Neovim。尝试实现正确的缓存和去抖动会让人头疼!