title: WSL 中的 VIM 與 Windwos 剪切板通信
date: 2019-05-28 13:52
categories: linux
tags: [vim,操作系統(tǒng)]
keywords:
mathjax: false
description:
WSL(Windows Subsystem for Linux)真香鼓寺,然而還是存在一些瑕疵噪馏。比如 WSL不是使用的系統(tǒng)剪切板,與系統(tǒng)剪切板通信充易,進行復(fù)制粘貼瓦宜,是一個很棘手的問題纺念。本文談?wù)劷鉀Q這個問題的一些方法敦捧。
WSL(Windows Subsystem for Linux)真香刘陶,然而還是存在一些瑕疵动壤。比如 WSL不是使用的系統(tǒng)剪切板,與系統(tǒng)剪切板通信锅风,進行復(fù)制粘貼酥诽,是一個很棘手的問題。本文談?wù)劷鉀Q這個問題的一些方法遏弱。
說明
環(huán)境如下
- Windows 10: 1709
- WSL: Ubuntu 1904
說明
-
<c-r>
代表組合鍵ctrl
+r
-
<cr>
代表回車鍵 -
<f1>
可以從 1到12盆均, 代表F1
-
^J
代表換行的控制字符,而不是^
,J
的連接漱逸,在 linux 上 換行為^@
,
在 VIM 輸入控制字符泪姨,比如^M
,需要按下<c-r><c-m>
前言
在網(wǎng)上看到最新的 Windows 版本支持用 ctrl+shift+c/v 進行復(fù)制粘貼饰抒, 或者有的可以在 shell 窗口>屬性>選項中開啟這個功能肮砾。
我這個不行。
而且 vim --version | grep clipboard
沒有 加號(系統(tǒng))寄存器袋坑, 再加之懶得重新編譯 vim(開啟 featured) . 所以我只有另尋解決辦法.
在命令行下仗处,已經(jīng)有很好的解決方法: 可以右擊進行復(fù)制(先選中)和粘貼
另外 也可以使用 ctrl+c 復(fù)制(有兩個功能,分別是中斷和復(fù)制)
vim 下就比較麻煩了枣宫。我嘗試了很多種方法婆誓,從操作的舒適程度,以及實現(xiàn)效果來選擇出最終最優(yōu)的解決方法: 通過運行 windows 的 paste.exe
, clip.exe
程序進行復(fù)制粘貼
復(fù)制
從 VIM 中 復(fù)制文本到 Windoes 剪切板也颤。
寄存器
通過 VIM 寄存器實現(xiàn): 將 visual 模式下選中的文本復(fù)制到 vim 寄存器洋幻,然后將寄存器內(nèi)容通過 shell 處理進入到剪切板。
首先選中(在 visual 模式下)翅娶,用"ay
將內(nèi)容保存到 a
寄存器文留,然后在命令行模式下 !echo <c-r>a \| /mnt/c/Windows/System32/clip.exe
(執(zhí)行 shell 命令好唯。 a 寄存器的內(nèi)容直接 作為參數(shù)文本傳遞(命令行模式下, <c-r>再接寄存器名字,可以將寄存器內(nèi)容拷貝過來)
然而拷貝的文本很可能不能直接在shell 下作為參數(shù)燥翅,有特殊字符骑篙,比如"
,$
等等。
所以要進行轉(zhuǎn)義森书,用 vim 的 escape
函數(shù) (我試了shellescape
, 效果不怎么好)
把上面的操作映射到按鍵下靶端, 我映射的是 ;y
, 就得到如下的 vim 鍵盤映射
在 visual 模式下選中,依次按下 ;y
即可復(fù)制
map ;y "ay: let @a="'".escape(@a,"\\'\"")."'" <cr>:!echo <c-r>a \|"/mnt/c/Windows/System32/clip.exe"<cr>
然而在復(fù)制多行時,寄存器中會包含換行控制字符^J
或^@
,^M
拄氯,這在傳遞到shell 中時執(zhí)行會截斷這個參數(shù)(在參數(shù)還沒有輸入完全按下 enter 回車),所以有時不會成功躲查。
而且有些字符 escape 也很難轉(zhuǎn)換為 shell 的原文本參數(shù)
所以它浅,這個方法行不通
新建文件
由于寄存器難以傳到 shell 作為參數(shù)译柏, 我就想到可以把寄存器的內(nèi)容復(fù)制到一個新的 文件 buffer 中, 然后將文件內(nèi)容拷貝到剪切板姐霍,然后刪除文件鄙麦。
如下,每個 <cr>
分隔開 兩條 命令镊折,
在 visual 模式下選中胯府,依次按下 ;y
即可復(fù)制
map ;y "ay: vs vim-copy<cr>"aP:wq<cr>:call system("/mnt/c/Windows/System32/clip.exe < vim-copy && rm vim-copy")<cr><cr>
各部分解釋如下
-
"ay
: 復(fù)制選中區(qū)域到a
寄存器 -
vs vim-copy
: 新建文件vim-copy
到新窗口 -
"aP:wq
: 拷貝a
內(nèi)容到 文件并保存退出 -
call system("...")
: 執(zhí)行 shell 命令, shell 命令的內(nèi)容就是復(fù)制 文件內(nèi)容到剪切板恨胚,再刪除文件
這個辦法可以很好地復(fù)制骂因, 唯一的缺點就是打開新buffer 窗口,再關(guān)閉赃泡,屏幕畫面變化大寒波,看著不舒服:astonished:
write命令
write 命令縮寫為 w, 直接使用就是 保存緩沖區(qū)
他后面可以接shell 命令與 shell 交互
如
:w !echo
這是對于整個文件升熊,也可以選擇一部分俄烁,
而進入 visual 模式下選中,再按下:
级野, 則進入命令行且將選擇的位置也輸入進命令行
這是可以 直接 傳遞給 clip.exe
程序页屠。 執(zhí)行后,選中的部分備剪切掉了蓖柔,可以按 u
恢復(fù)
在 visual 模式下選中辰企,依次按下 ;y
即可復(fù)制
map ;y : !/mnt/c/Windows/System32/clip.exe<cr>u
這也是最優(yōu)的方法了,如果你有更好的方法况鸣,歡迎賜教牢贸。
粘貼
從 Windows 剪切板 粘貼到 VIM
pastetoggle
如果 VIM 沒有設(shè)置set mouse=a
, 那么可以直接右擊粘貼,設(shè)置了之后要按住 shift
再右擊粘貼
然而這樣存在問題懒闷,就是 vim 設(shè)置了autoindent,它會錯誤的將粘貼進的文本進行縮進十减, 而不是粘貼原文栈幸。
這個辦法可以 set paste
, set nopaste
解決帮辟,設(shè)置了paste
后速址,就可以原文粘貼,
而這樣輸入命令切換很麻煩由驹, 可以set pastetoggle=<f12>
芍锚,或者其他按鍵,這樣按一次就可以切換 paste 狀態(tài)蔓榄。
這樣比平常的 paste 動作 要多一個pastetoggle
操作并炮,所以不好
windows paste 程序
在 了解到上面 復(fù)制時使用的 clip.exe
程序,我就在想是不是 windows 有也專門paste
的程序 (這個程序是和 cmd 交互的甥郑,加之逃魄, wsl 也可以執(zhí)行 exe
程序)
很遺憾,windows 沒有
但是令人高興的是澜搅,一個網(wǎng)站上有伍俘,點擊這里下載, 然后解壓放到 C:Windows/System32
目錄下
使用 vim 的 read 命令進行與 shell 的交互, 即將 shell命令執(zhí)行的輸出 讀到當前 buffer
映射如下
在任何模式下按下 ;p
即可粘貼
map ;p :read !/mnt/c/Windows/System32/paste.exe <cr>i<bs><esc>l
map! ;p <esc>:read !/mnt/c/Windows/System32/paste.exe <cr>i<bs><esc>l
后面的 i<bs><esc>l
執(zhí)行退格操作勉躺,以便接著當前的行 粘貼癌瘾。不然會 paste 到新的一行.
綜上所述,最終解決方案為:
點擊這里下載, 然后解壓放到 C:Windows/System32
目錄下
再在 .vimrc
文件中增加如下映射
map ;y : !/mnt/c/Windows/System32/clip.exe<cr>u
map ;p :read !/mnt/c/Windows/System32/paste.exe <cr>i<bs><esc>l
map! ;p <esc>:read !/mnt/c/Windows/System32/paste.exe <cr>i<bs><esc>l
WSL 真香饵溅,強烈推薦入坑 :grimacing:
還想起一個 瑕疵妨退, WSL 不支持32 位的程序, 不過可以安裝 qemu 等解決蜕企。
另外 windows terminal 在今年 6月中旬也會來到咬荷,值得期待。