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

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

【问题讨论】:

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

标签: bash vim windows-subsystem-for-linux


【解决方案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 中复制和粘贴。

或者,你可以试试:

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

【讨论】:

【解决方案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 Userthis 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 键并使用鼠标选择要复制的文本。然后转到主机上的任何文本编辑器并粘贴;您选择的文字应该在那里。

            【讨论】:

              猜你喜欢
              • 2011-04-27
              • 1970-01-01
              • 2017-08-25
              • 2017-09-10
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多