如何在 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 <C-c> :w! ~/.vimbuffer \| !cat ~/.vimbuffer \| clip.exe <CR><CR>
Edit2:下面的@Tropilio 使用系统事件在 cmets 中有一个更清晰的方法。我已经用了一年了。
【讨论】:
出于某种原因,它对我不起作用。它在选择的最开始插入两个字符:|
(冒号和管道字符),并且不会将内容复制到 Windows 剪贴板。当.vimbuffer
中有内容时,我在vim 中输入:!cat ~/.vimbuffer \| clip.exe <cr>
,我得到以下错误:cat: '|' : no such file or directory
和cat: clip.exe: No such file or directory
这可能是因为你在 vim 内部使用了命令。如果您只是想将~/.vimbuffer
的内容复制到剪贴板,请使用:!cat ~/.vimbuffer | clip.exe <cr>
- 您不必转义|来自 vim 的 char(带有 ),仅在 .vimrc
中。如果它仍然不起作用,请告诉我。
我可以确认这适用于 Windows 10 上的最新 WSL。Microsoft Windows [版本 10.0.17134.286]
谢谢,这行得通!但是由于某种原因,每当我使用<C-c>
命令时,都会出现屏幕闪烁几次的故障......
我现在使用不同的方法,也许它对你也有用。我使用了一个自动命令,每次我拉一些文本时都会自动触发:autocmd TextYankPost * call system('echo '.shellescape(join(v:event.regcontents, "\<CR>")).' | 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】:下面是映射
在正常模式下cy
、cyy
和cY
(=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.exe
和 powershell.exe [Set|Get]-Clipboard
在用户体验上都相形见绌。例如,clip.exe
只支持复制,但无法解决粘贴问题。虽然 Powershell Get-Clipboard
cmdlet 允许我们从 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
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<C-R>"
不会立即起作用。这也将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 10 上的 Git bash 上为标准输入注入 EOF?
如何在 Windows 上的 Git Bash 中退出“git diff”的结果? [复制]
在Windows上的Ubuntu上用Bash更新Python库