如何在 VIM 中共用系統剪貼簿,vim-copycat 簡介

最近到新公司工作後認識了一個 Vim 的同好,George Li,說他是 Vim 同好太對不起他了,他根本是「Vim 末期重度患者」,他對我以前做過的一個小 project 很感興趣,所以最近就花了一些時間跟他一起改進了一下這個 project,剛好最近發現 vim 內建的 clipboard 共用功能沒辦法在沒啓用 +xterm_clip 的狀況下使用,所以就把 copycat 這個 project 修了一下,做了一個 vim plugin,用來擴充 vim 的剪貼簿功能。

從 copycat 開始說起

由於我是個 terminal 重度使用者,所以常常桌面上就只有 terminal 和 browser 而已,有時候要從從終端機複製東西很麻煩,所以就做了 copycat 這個東西,讓一些常用的東西可以存在 copycat 裏面,下個指令就複製到剪貼簿,舉凡像是英文地址、中文地址、信用卡卡號之類的,你都可以存在這東西裏面,用的時候只要知道記得他的 id,舉例來說,英文地址的 key name 我存成 eng-addr,我只要下 copycat eng-addr,我的剪貼簿裏面自動複製了我的英文地址,讓我省掉打字的麻煩。

契機,set clipboard=unnamed

剛好前一陣子發現了國外有人分享了這個用法,才知道 Vim 裏面其實支援把 Vim 的「*」 register 對應到系統的剪貼簿,很高興的我就寫了一篇網誌分享到臺灣的 vim 社群裏面,結果發現預設的 Vim 不管是在 Mac OS X 或是 Linux 底下,都沒有啓用 xterm_clip 這個 tag,所以這個方法不適用。

唯一的解決方法重新編譯你的 Vim,最快的就是下載 gvim 或是 macvim 用裏面的 binary,但是很多人覺得這樣很麻煩,畢竟常用機器 ok,但是你總不能到處編譯別人電腦的 Vim 吧?

所以 copycat 計劃重生,目標是「只要你的系統有 Python,就能夠讓 vim 能夠共享系統的剪貼簿」,所以我們的工作變成了兩個:

  • copycat: command-line tool,可以讓你把東西複製進自定義的剪貼簿中,或是系統的剪貼簿,當然也可以取出。
  • vim-copycat: 利用 copycat,讓 vim 的剪下(d 系列指令)、複製(y 系列指令)、貼上(p)都能夠從 copycat 中指定的剪貼簿中拿取內容。

由於我從來沒有寫過 vim plugin,我這個人一向都從做中學,所以我就先去 contribute 了我平常最愛用的 vim plugin 之一 jedi-vim,這是一個可以動態讀取你現在的 python 環境(不管是 global 或是 virtual environment 都可以)的自動完成工具,他另外還有提供一些 Go To Definition 或是 Go To Documentation 的功能,只是他每次開,都是另外新增一個 buffer 把你目前的螢幕蓋掉,還得要用 buffer 用的熱鍵 才能弄回來很不方便(不能夠一邊寫一邊對照),剛好看到有人在開 issue,所以就開始了我人生第一次的 vim plugin contributin。

這個作者也回得很勤勞,連 spec 都想好了,然後一直在線上回應我,很令人感動,受到大大的眷顧我一定要努力才行,於是接下來...

「如果你有空的話,可以順便幫我更新文件嗎?」

文件?當然沒問題,寫東西少文件怎麼可以,vim 的 documentation 其實有特殊格式,所以剛好來學學怎麼寫也不錯,所以我就二話不說就完成了文件部分的更新。

「如果你有空的話,可以順便寫一下 test 嗎?」

test?好啊,沒寫過,順便學學 vim 的 test 要怎麼寫,寫 vim test 的困難點在於,你必須要在腦海裏想像一個 vim 打着你預設的內容,做了你特定的功能,每個視窗、遊標、字元停在螢幕上哪裏你都要搞清楚,我建議還是真的開着一個 vim,一邊寫測試內容,這樣比較不會失誤就是了。

所以我就提供了一個包含文件、測試、feature 的 pull request,但是我不小心把 pull request 送到 master 去了,不過作者說沒關係,他會幫我改拉進 dev,後來發現他就直接 merge 到 master 了,我以爲作者搞錯了,趕快在上面問他,他說因爲你提供了良好的 test,我覺得這個 pull request 夠穩定可以直接進到 master,做完之後還被作者稱讚,「要是每個 patch 都跟你這樣就好了...」,真是讓我 >////< ,不過這樣總算是可以開始了,大概知道要怎麼開始寫 vim 的 plugin 了。

(其實我覺得是作者大概是忘了,code review 完就直接不小心 merge 進去 master 了。)
(有圖有真相,作者真的有這樣說:jedi-vim/pull/191

然後我原本是用 argparse 來處理 argv,原本寫的落落長,但是 George 改接了 mosky 的 clime 後一切都變簡單了,感謝 mosky。

回到 vim-copycat

OK,所以我們如期完成了目標,希望可以讓大家來試用,首先跟大家介紹一下怎麼裝這個 vim-copycat。

安裝 copycat

因爲我們需要存取系統的剪貼簿,所以我們需要 copycat 這個 library,讓 python 可以存取系統剪貼簿,安裝方式很簡單,只要透過 pip 就可以了:

sudo pip install copycat-clipboard

(因爲後來發現 copycat 被用走了,所以只好改用 copycat-clipboard。)

安裝 vim-copycat plugin

首先你必須先到 vim-copycat Repository,複製 clone 用的網址,然後把這個東西放到你的 vim 目錄下,非常非常建議使用 Vundle 或是 Pathogen

如果你用 Vundle
Bundle 'georgefs/vim-copycat'
如果你用 pathogen
cd ~/.vim/bundles
git clone https://github.com/georgefs/vim-copycat

然後到你的 ~/.vimrc 下面,加入這行:

let g:copycat#auto_sync = 1

現在回 vim 你就會發現你的 vim 已經共用系統剪貼簿啦,重編譯 out!

更多的 vimrc 設定
let g:copycat#auto_sync = 1

如果你想要把 vim 的剪貼簿跟 copycat 的剪貼簿綁在一起的話,就把這個 setting 設定成 true。

let g:copycat#clip = 'vim'

預設值是 '',也就是系統剪貼簿,但是你如果想要獨立一個剪貼簿出來,但是 copycat 又可以存取的話,可以另外設定,假設我設定 'vim',還是有個好處,就是不同的 vim process 變成可以互通囉,但是系統剪貼簿不會被影響。

另外還有這兩個

let g:copycat#overwrite_ctrlkeys = 1
let g:copycat#reg = ''

可以到 Github Repository 上去看囉!

有建議也可以到 Issue Tracker 裏面開 issue,我和 George 很樂意跟大家討論。

comments powered by Disqus