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

Posted

技术标签:

【中文标题】如何在 Windows 上的 Bash 的 vim 中“复制到剪贴板”? [关闭]【英文标题】:How to "copy to clipboard" in vim of Bash on Windows? [closed] 【发布时间】:2017-11-12 19:57:16 【问题描述】:

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

【问题讨论】:

你不能。如果你想在 Windows 上支持剪贴板,请使用 GVim。 "* 寄存器在 git bash 中为 vim 解决了问题。例如。复制当前行:"*yy(然后 ctrl-v 进入例如您的 Web 浏览器 URL 字段)。或者反过来:(例如,在复制 URL 之后),将其粘贴到您当前的 vim 文件中:"*p 【参考方案1】:

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

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

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

【讨论】:

这会从控制台复制文本,而不是在 vim 中。 正确,但我不知道有什么方法不正确。 (如果你想使用 WSL 附带的 stock vim) vim 对我(非 Windows)系统的帮助声称 "* 是正确使用的寄存器。 对,但它需要以不同的方式安装 vim,vim-gnome 而不仅仅是vim 耸耸肩 我想他们认为在 WSL 下运行的 vim 根本不需要真正与 Windows 集成。【参考方案2】:

如果你想使用 WSL 中捆绑的 vim,你只能使用 vim 本身提供的剪贴板,也就是说你只能在 vim 中复制和粘贴。

或者,你可以试试:

    安装VcXsrv 并运行它。 export DISPLAY=localhost:0 在您的 WSL Bash 中。 运行 vim-gtk 或 vim-gnome(或任何其他 GUI 应用程序)并尝试跨 Linux 和 Windows 的剪贴板。

【讨论】:

根据 WSL GitHub-Issue,这应该可以工作。也可以在这里查看:github.com/Microsoft/WSL/issues/892#issuecomment-275873108【参考方案3】:

由于 "*y 和 "+y (...) 都不起作用,因此可以选择以下方法:

将此添加到您的 .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>

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

Ctrl-c 抽出所选文本,用所选文本覆盖 ~/.vimbuffer,运行 UNIX 命令将数据从 ~/.vimbuffer 管道输出到 clip.exe.

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

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

vmap &lt;C-c&gt; :w! ~/.vimbuffer \| !cat ~/.vimbuffer \| clip.exe &lt;CR&gt;&lt;CR&gt;

Edit2:下面的@Tropilio 使用系统事件在 cmets 中有一个更清晰的方法。我已经用了一年了。

【讨论】:

出于某种原因,它对我不起作用。它在选择的最开始插入两个字符:|(冒号和管道字符),并且不会将内容复制到 Windows 剪贴板。当.vimbuffer 中有内容时,我在vim 中输入:!cat ~/.vimbuffer \| clip.exe &lt;cr&gt;,我得到以下错误:cat: '|' : no such file or directorycat: clip.exe: No such file or directory 这可能是因为你在 vim 内部使用了命令。如果您只是想将~/.vimbuffer 的内容复制到剪贴板,请使用:!cat ~/.vimbuffer | clip.exe &lt;cr&gt; - 您不必转义|来自 vim 的 char(带有 ),仅在 .vimrc 中。如果它仍然不起作用,请告诉我。 我可以确认这适用于 Windows 10 上的最新 WSL。Microsoft Windows [版本 10.0.17134.286] 谢谢,这行得通!但是由于某种原因,每当我使用&lt;C-c&gt; 命令时,都会出现屏幕闪烁几次的故障...... 我现在使用不同的方法,也许它对你也有用。我使用了一个自动命令,每次我拉一些文本时都会自动触发:autocmd TextYankPost * call system('echo '.shellescape(join(v:event.regcontents, "\&lt;CR&gt;")).' | clip.exe') 这不会导致任何闪烁或延迟。【参考方案4】:

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

:w !clip.exe

通过管道进入clip.exe。如果你需要特定的行,比如 2 到 10,你可以这样做

:2,10w !clip.exe

见Piping buffer to external command in Vim

【讨论】:

【参考方案5】:

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

下面的代码sn-ps可以放在你的.vimrc文件中。

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

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

system 函数将允许我们调用本机程序并将参数传递给它们。下面的 sn -p 设置了两个键映射;第一行将允许 Ctrl+C 用于复制文本,第二行将允许 Ctrl+X用于剪切文本:

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

将更改保存到您的 .vimrc 文件后,您应该可以开始了。

如果您要在多个系统上使用.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

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

您可能还想在 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

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

【讨论】:

比接受的 imo 更好的解决方案,因为不需要缓冲文件。感谢分享!【参考方案6】:

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

:call system('clip.exe', '

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

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

Enter,完成!

【讨论】:

【参考方案7】:

下面是映射

在正常模式下cycyycY(=Clipboard Yank)分别复制给定的文本对象、行、从光标位置到剪贴板的行的其余部分,以及 在视觉模式Y 下,将视觉选择复制到剪贴板,

与 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

【讨论】:

【参考方案8】:

所以有很多答案,即使是像this one on Super User 和this one on Vi and Vim 这样的跨网络问题,不幸的是我对其中任何一个都不满意,所以这里有一个不同的答案。

Neovim

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

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

虽然此解决方案需要安装外部二进制文件 win32yank.exe,但我个人对它非常满意,因为 clip.exepowershell.exe [Set|Get]-Clipboard 在用户体验上都相形见绌。例如,clip.exe 只支持复制,但无法解决粘贴问题。虽然 Powershell Get-Clipboard cmdlet 允许我们从 Windows 剪贴板粘贴到 Vim,但它会保留 Windows 行尾,所以粘贴后到处都是讨厌的 ^Ms。此外,它是一个超级小的二进制文件,只需要安装在我们的 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
sudo mv /tmp/win32yank.exe /usr/local/bin/

Vim

如果我们只是使用普通的 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')

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

这很有效,但是如果快速执行几次连续的拉动和粘贴,就会明显感到紧张,因为我们每次都必须掏空。我们可以通过去抖动来改进 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

但这需要 Vim 8,如果您必须升级,我建议您只使用 Neovim。尝试实现适当的缓存和去抖动将是一件令人头疼的事情!

【讨论】:

甚至适用于 WSL2。至少对于 neovim 用户来说,这是最好和最简单的答案。 mv /tmp/win32yank.exe ~/bin 将 .exe 重命名为 bin 并将其放在 ~ 中。你确定你不是指mv /tmp/win32yank.exe /usr/local/bin/win32yank.exe(对于 Ubuntu)? 我可以确认它适用于 WSL2但是,您需要注意: 1. 您应该专门配置 neovim 以使用 win32yank.exe。问题是,如果您现在(或以后安装)具有更高优先级的任何其他选项(xclip 等),那么它们将优先,您的剪贴板将无法工作/停止工作。 2. neovim 在执行剪切/删除等操作时可能会开始滞后(最多 5 秒)。这可能是由于 Win 和 Linux (hyper-v) VM 之间的通信造成的。 Vim 部分使用vim-nox 为我工作。这是我尝试的第四个解决方案。 (我还没有为去抖动而烦恼) 请注意,将剪贴板内容读入寄存器的是 p/P 命令。这意味着您不能使用这两个命令中的任何一个直接访问寄存器之前。特别是,i&lt;C-R&gt;" 不会立即起作用。这也将xp 的行为更改为就地。【参考方案9】:
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.

站在巨人的肩膀上,我现在正在使用上面的解决方案。

【讨论】:

【参考方案10】:

添加关注.vimrc:

autocmd TextYankPost * if v:event.operator ==# 'y' | call system('/mnt/c/Windows/System32/clip.exe', @0) | endif

为方便起见,如果需要,您可以通过ctrl + c添加复制

vmap <C-c> y

【讨论】:

【参考方案11】:

对我有用的只是:

按住 Shift 键并使用鼠标选择要复制的文本。然后转到主机上的任何文本编辑器并粘贴;您选择的文字应该在那里。

【讨论】:

以上是关于如何在 Windows 上的 Bash 的 vim 中“复制到剪贴板”? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

Windows下Git Bash中VIM打开文件中文乱码

如何在 Windows 10 上的 Git bash 上为标准输入注入 EOF?

如何在 Windows 上的 Git Bash 中退出“git diff”的结果? [复制]

在Windows上的Ubuntu上用Bash更新Python库

Windows上的rtorrent:-bash:wget:找不到命令

如何在 Windows 上的 Git Bash 终端下向 EOF 发出信号以关闭标准输入? Ctrl-D 不起作用