Vim Packages

Vim 8 有兩個我覺得比較大的新功能,一是開始有Asynchronous I/O,二是開始有官方的 package 機制了,這篇主要想介紹這官方的 package 機制,眾所周知,以前 Vim 實在很難管理自己裝的 Vim script 和 plugin(後文以 plugin 為主),因為原始的設計是自己把檔案丟到runtime 目錄下的對應位置,裝的東西一多,就會開始混亂起來,最常發生的就是越來越多垃圾,不知道還需不需要用,再來就是可能會有檔名重複的情形,所以升級某個 plugin 遇到有檔名重複時,直接覆蓋過去可能也會出錯,這個問題直到 Tim Pope 推出pathogen.vim後才被解決,pathogen 是藉由修改runtimepath變數(有點像是系統的PATH環境變數,可以有多個路徑)來讓不同的 Vim plugin 可以放在各自的子目錄內,從此一舉解決了 Vim plugin 的管理問題,當然現在很多人用的Vundleneobundlevim-plug等,基礎原理應該都是一樣的。

Vim 8 推出的 package 機制,雖然其基本原理也是增加 runtimepath,不過它其實定位和 pathogen 不一樣,設計上是再高一個階層,不過也因此和 pathogen 的路徑設計不相容,pathogen 之類的都是把 plugin 分目錄放到~/.vim/bundle這,例如:

~/.vim/bundle/html5.vim
~/.vim/bundle/yajs.vim

然後會去把這些路徑加到runtimepath內(有些 plugin 是全自動、有些要設定、有些可以加條件),寫成 glob 型式大概是~/.vim/bundle/*,不過新的 package 定義上是數個 plugin 的組合,所以一個 package 下是可能有多個 plugin 的,放 package 的路徑一樣在~/.vim下面,預設在~/.vim/pack,也可以修改packpath來換位置,不過東西不是直接放進去就好了,一開始會被加進去 runtimepath 的路徑實際上是~/.vim/pack/*/start/*,在這個 glob 表示式中,第一個*是 package 層,第二個*則是 package 裡面的 plugins,例如我可以建立一個自己在編輯 JavaScript 時用的 plugin 組合,就先叫 my-js 好了,我就把東西都丟到~/.vim/pack/my-js/start/*,大概像是:

~/.vim/pack/my-js/start/yajs.vim
~/.vim/pack/my-js/start/javascript-libraries-syntax.vim
~/.vim/pack/my-js/start/simple-javascript-indenter

至於中間的start則是表示啟動就會去讀進來的意思,類似於以前 pathogen 的流程,而除了start之外,還有一個路徑是opt,是 optional 的意思,放在opt下面的 package 不會在啟動時就讀進來,而是要下packadd指令,例如packadd foo就會去找~/.vim/pack/*/opt/foo/這些位置有沒有東西可以用,文件上提供的一個使用情境是根據 Vim 版本決定要讀入哪一個 optional plugin,可以用 Vim script 做一些判斷來決定要讀那些,或是使用者自己執行 packadd,不過我思考一下是覺得後者的情境似乎不太有用,所以這個設計主要的目標應該還是做一些自動化判斷並讀入 plugin 為主吧。

當然,package 也可以只包一個 plugin,理論上可以直接這樣發佈 Vim plugin,不過現在這樣發佈,就會不相容於目前使用量最大的 pathogen 架構,所以我也還沒看過有人這樣直接發佈的,像 vim-css3-syntax 就還是用舊的資料匣架構,但是在 README 內加上對應 Vim package 的安裝方式,這是我目前覺的對於 Vim package 普及化的最大阻力;另外還有一個缺點是,如果完全用 Vim package 機制來裝 plugin,那其實也沒有地方紀錄你安裝了那些東西,和最早的時候,或是單純只有 pathogen 時一樣,要裝新機器什麼的就有點麻煩。目前我是覺得 Vim package 還不會很快普及,它比較像是出來取代 pathogen 的功能,應該接著要等有基於 Vim package 的 package manager 出來才會開始有普及的機會吧。


Vim Filename Complete

Vim Filename Complete,

Vim 有一個內建的自動補完功能是針對檔案名稱的,使用的方法是<C-X><C-F>,我目前在維護的autocomplpop也有支援這種補完模式,只要輸入./後就會自動幫忙觸發,不過我比較有機會觸發到是在使用 ECMAScript 6 的 import 和 CSS 的 import 時,不過常常就是發現他查看的路徑不太對,不是拿目前編輯檔案的位置做為起點的,研究過後發現是因為 Vim 找檔案的起點是看他的工作目錄($PWD),加上我會使用ctrlp這種工具,所以實際上在編輯的檔案通常是不在工作目錄下,對於這個問題,其實我覺得最理想的解決方式是 Vim 應該要提供兩種模式來決定要從那邊開始找,不過目前似乎沒這個計畫,唯一在文件是有提到的是未來可能會支援path的設定,理論上,如果有支援的話,應該就可以解決問題了,因為預設的path值包括了.,不過目前還沒有相關時程,就只能自救了。

最簡單的方法,其實就是開啟autochdir,這個選項打開後就會自動在切換 window 時也更改工作目錄,不過這個選項是為了相容早期系統才提供的,文件也有說可能會和部分 Vim Script 不相容,實際上我也有找到一些不相容的 Vim Script,所以想避免,就搜尋了一下其它可能的解決方法,在 StackOverflow 上有看到一篇,裡面有兩個人提供了解法,第一個是用autocmd,然後在進入 insert mode (在這時候才有機會用到檔名補完的功能)時自動開啟autochdir,離開時自動關閉autochdir,不過這樣的方式(感覺上)還是不太安全,因為還是用到autochdir,所以下面有另外一個方法改用lcd,作法是改成修改 Key Mapping 的方式,改的 mapping 是./<C-X><C-F>,不過這樣對我來說又不合用,因為我用 autocomplpop 的話,不會真的打<C-X><C-F>,所以基本上觸發不到這事件,所以我就決定把這兩種解法合併起來,改成用autocmd加上lcd

:autocmd InsertEnter * let save_cwd = getcwd() | execute 'lcd %:p:h'
:autocmd InsertLeave * execute 'lcd' fnameescape(save_cwd)

進入 insert mode 時改變該 window 的工作目錄,離開 insert mode 時把工作目錄還原。這是我目前認為影響最小的調整方式,不過其實可能執行一次lcd換工作目錄就夠了,沒深入研究 autochdir 所產生的問題,不過我推測是影響到 Vim Script 建立的 window 的工作目錄,像是 NERD Tree 之類的側邊欄那種,總之目前這樣運作還算正常,接下來就是等 Vim 加上path的支援吧(或是有人送 patch)。


Native True Color Vim

因為最近 Vim 8 發佈了,所以就又研究一下現在最新的 True Color Vim 安裝方法,結果發現已經併進 master branch 許久了,然後從7.4.1784開始,也不用加特別參數來編譯,只要--with-features的值是big或是更大的huge就會把這功能編譯進去,所以現在就不用 ZyX 維護的版本了,目前用的編譯指令為:

git clone https://github.com/vim/vim.git

cd vim
cd src && make autoconf && cd ..

./configure \
  --enable-gui=no \
  --without-x \
  --enable-multibyte \
  --with-tlib=ncurses \
  --enable-cscope \
  --with-features=huge \
  --disable-nls \
  --enable-perlinterp \
  --enable-pythoninterp \
  --enable-rubyinterp

make
make install

然後現在也不需要guicolors的設定,好像直接就生效了,顏色畫出來和之前的 ZyX 的版本似乎有一點差異,我想應該現在新的版本是比較正確才是。追蹤這功能追了這麼久,總算也是告一段落了,感覺...好像也沒什麼特別的感覺...


YAJS.vim and Vim Syntax Highlight

上個週末在香港 Open Source Conference分享的主題,第一次使用英文分享,結果表現不太好,不知道上場前喝點啤酒會不會比較好就是...

這個主題本來是想要投 COSCUP 的,主要是想介紹一下之前在做yajs.vim時遇到的比較有印象的問題,在這之前先介紹一下 Vim Syntax Highlight 的機制,因為這些問題很多都和 Vim 的 Syntax Highlight 機制的設計關係很大,然後最後就是有一個還沒辦法解的問題,這個問題就是 yajs.vim 目前還沒辦法完美的 highlight 有 default parameter 的 arrow function。


Vim Syntax and Regexp Note

前陣子為了寫更好的 Vim syntax 還去學了 compiler 的課程,雖然沒上完不過也對怎麼解析語法理解不少,不過其實 Vim syntax highlight 系統為了效能問題,有不少限制,沒辦法真的和 compiler 的 parse 原理完全互通,其中兩個限制影響比較大,第一個是沒辦法有完整的 AST 並解析其語意,因此除非寫得非常繁複,一定會有無法正確 highlight 的地方,例如 comment,不是說 comment 不能正確標示,問題是 comment 可以插入在很多地方,像是參數序列的中間,function關鍵字和後面()的中間等等,幾乎是可以放空白字元的地方就可以放 comment,然後不會影響程式語意,本來,不考慮註解時,我可以用skipwhiteskipempty然後加上nextgroup就可以指定下一個 token 是什麼,以 JavaScript function declaration 來說:

function fn (a) {}

這樣的程式碼我把他拆成四個部分,function keyword、function name、function parameter、function body,然後用 Vim syntax 語法設定:

syntax keyword javascriptFuncKeyword function nextgroup=javascriptFuncName skipwhite
syntax match   javascriptFuncName    contained /\k\+/ nextgroup=javascriptFuncParam skipwhite
syntax match   javascriptFuncParam   contained /([^()]*)/ nextgroup=javascriptFuncBody skipwhite
syntax region  javascriptFuncBody    contained start=/{/ end=/}/

除了 function keyword 外都有contained,用途是讓該 rule 不會在 TOP region 下生效,一個好處是減少 TOP region 下要檢查的 rule 數量,另一個好處是有些相同的 token pattern,但是其實語意上是不一樣的,可以盡量用這種機制拆分開來,到這裡都還很美好,但是加上 comment 後問題就變複雜了,先簡單寫一下 comment 的 syntax rule:

syntax region  javascriptComment     start=/\/\*/ end=/\*\//

然後 comment 可以放在哪些地方呢:

function /*cc*/ fn (a) {}
function fn /*cc*/ (a) {}
function fn (a) /*cc*/ {}

也就是本來 nextgroup 連接的地方都可以插入個 comment,可是只要插入了 comment,後面的 token 就不會被正確 highlight,因為 comment 的 rule 沒有 nextgroup,所以他的部分結束後就會回到用 TOP region 的情境,而後面應該符合的 rule 都有設上contained,所以就沒機會對到。當然現在要解決這個問題也不是沒方法可以避開,但是非常不好看,就是如下的設計:

syntax keyword javascriptFuncKeyword function nextgroup=javascriptFuncName,comment1 skipwhite
syntax match   javascriptFuncName    contained /\k\+/ nextgroup=javascriptFuncParam,comment2 skipwhite
syntax match   javascriptFuncParam   contained /([^()]*)/ nextgroup=javascriptFuncBody,comment3 skipwhite
syntax region  javascriptFuncBody    contained start=/{/ end=/}/

syntax region  comment1     start=/\/\*/ end=/\*\// nextgroup=javascriptFuncName,comment1 skipwhite
syntax region  comment2     start=/\/\*/ end=/\*\// nextgroup=javascriptFuncParam,comment2 skipwhite
syntax region  comment3     start=/\/\*/ end=/\*\// nextgroup=javascriptFuncBody,comment3 skipwhite

如此可以確保 comment 插入也不會讓後面的 token 沒 highlight,但是這樣的設計,實際寫起來會非常繁瑣,完全不想去研究 JavaScript 中會有多少類似的狀況。其實我是覺得 Vim syntax 應該是希望盡量都用前後獨立的 rule 來 highlight,盡量不要有前後相依的關係存在,就不會有上面的問題,也可以讓 highlight 過程比較單純,理想上是從頭開始,一個 token 一個 token 各自獨立的 highlight,不過是事情當然沒這麼簡單,第二個想記錄下來的事情也和這個有關係。

假設目前 highlight 處理中,parse 到一個=,然後看到一組小括號(a),連起來如下:

= (a)

這時你會覺得(a)是什麼呢?是小括號,裡面是一個 expression 然後回傳變數a嗎?相信很多人會這樣認為,如果他後面是接分號的話:

= (a);

但是其實也可能是這樣子的:

= (a) => {}

ES6 的 arrow function,也就是說,如果一個 token 一個 token 解析,一定無法直接知道目前 token 代表的正確意義,所以 compiler 把程式碼轉成 AST 的時候,有時候會先往後面看一下來判斷現在的 token 到底是什麼意義。然而 Vim syntax 系統並沒有這種能力,嚴格來說,是可以用 match 來達成,不過還是很受限制。再來則是往前看的問題,我在設定運算子的 match rule 的時候,會希望嚴謹一點,本來想在兩邊加上 word boundary 的 pattern,在 Vim 裡面是\<\>,不過測試幾回發現,我的字元本身不是文字字元的話,這個 pattern 是沒有用的:

/\<word

這樣是有效的,但是下面想要 match==的會沒用:

/\<==

所以變成要自己寫往前看的 regexp,在 Vim 裡面有兩種類似的東西可以用,分別是\zs\@<=,通常,\zs效能比較好,會推薦使用,他的用途是標註你的 regexp 的 match 的起點,當然同時也有一個\ze是終點:

/abcd\zsefgh\zeijkl

上面這串 regexp 的目標是efgh,但是他的前後分別是abcdijkl,實際執行時會去找abcdefghijkl這串字串,完整比對到之後,只會回中間的efgh作為 match 的範圍,這設計要做一些操作的時候就會有差,像是文字取代。本來我就想要用這個來做 syntax,可是就發現還是不生效,所以改成用\@<=試試看:

/\(abcd\)\@<=efgh\@=\(ijkl\)

就發現成功了,想了許久才理解其原因,然後才瞭解,真的往前看的是\@<=\zs並沒有往前看,兩者最大的差異在於 pattern match 操作的起點,一般的使用大概感覺不太到差異,不過像是 syntax highlight 這種一個 token 一個 token 逐步處理的就會有差,當目標是efgh時,通常處理進度到e這個位置時,前面的abcd已經被處理過了,所以這時候會和 regexp 比對的字串就變成efghijkl,使用\zs的話,因為它還是要完整比對到abcdefghijkl,起點是a,就不會和efghijkl相符,但是用\@<=的話,pattern 的起點是efghe,這樣就可以 match 到目前剩餘的字串了。

前面說的個 token 一個 token 逐步處理的問題還有一個情形也讓我困擾很久,不過這次不是東西被用掉,問題是沒被用掉。這個狀況發生在巢狀結構的 region,像是 JavaScript 的 block:

syntax region  javascriptBlock start=/{/ end=/}/

然號要讓 block 裡面可已有 block 就要用contains

syntax region  javascriptBlock start=/{/ end=/}/ contains=javascriptBlock

這時候就會發生奇怪的現象了,因為外面的 region 包括了頭尾的括號,然後進入 block 內要做 syntax match 的時候,一開始的{又 match 到 block,結果 Vim 就直接覺得這已經是第二層的 block 了,雖然好像有其它機制讓他不會一直循環下去變成無限多層,不過這樣還是會造成後面的 code 有被判斷錯誤的機會,因為 block 的開關不 match,這裡的關鍵也是要讓{}被處理掉,進入 region 內部就不會跑到上一層的起點,而這裡要用的就是matchgroup

syntax region  javascriptBlock matchgroup=bracks start=/{/ end=/}/ contains=javascriptBlock

如此就都會正常了,因為這樣的設定會讓{}直接被當成bracks這個 group,然後就被當成已經被解析過的 token,從它的下一個 token 繼續 highlight 分析,但是千萬不要另外加上bracks的 syntax rule,剛好又 match 到 region 的起點和終點:

syntax match   bracks  /[{}]/

這樣的話也會發生其它的怪異現象,總之 nested region 的重點在於,要用 matchgroup,然後不要用和 matchgrouop 同樣名稱,同樣 pattern 另外又設定一組 rule。

最後一個要紀錄的則是 Vim syntax 裡面的優先度,基本上是 keyoword 優先度最高,也就是有 match 到 keyword 的話,你的 match pattern 就都無效了,所以像是 JavaScript 裡面,label 雖然不可以用關鍵字,像是continue:就不合法,但是因為會先 match 到continue關鍵字,所以就很難用 syntax highlight 來標出這種錯誤,而在 keyword 比對完之後,才輪的到 region 和 match,兩者是同樣權重,但是後定義的優先,而且不受containsnextgroup裡面的順序影響,搞清楚優先順序在做細部的 syntax highlight 的時候還蠻重要的。另外要順便說說 region contains 和 nextgroup 的差異,nextgroup 其實還蠻不錯的,他不是限制下一個 token 一定是哪些東西,而是改變優先順序,先檢查完 nextgroup 裡面的東西,再檢查該 region 下的其它可能性,region contains 就不一樣了,該 region 裡面只有在 contains 裡面的東西會出現,另外還要特別注意一點,region 的處理並不管該 region 能不能正確的關閉,只要 match 到起點,就會把 region 打開,然後剛剛有提到,region 和 match 是同樣權重的所以就要非常注意:

syntax match  javascriptLabel       /\k\+:/
syntax region javascriptLabelblock  start=/\k\+: {/ end=/}/

這樣兩條 syntax highlight rule 然後配上下面的程式碼:

abcd: {
  var ii = 1 + 1;

var jj = 2 + 2;

要注意我的 block 其實沒有結束,但是結果 Vim 只會 match 到 label block 那條規則,而且由於一直找不到 region 的結束點,所以下面的var jj那行也是被認為在 block 內。

最後的最後要推薦一下gerw/vim-HiLinkTrace這個 Vim plugin,可以很完整的 trace syntax highlight 的狀況。


Latest True Color Vim

上次文章的安裝方法已經過時了,更新一下:

hg clone https://bitbucket.org/ZyX_I/vim
cd vim
cd src && make autoconf && cd ..

./configure \
  --enable-gui=no \
  --without-x \
  --enable-multibyte \
  --with-tlib=ncurses \
  --enable-cscope \
  --with-features=huge \
  --disable-nls \
  --enable-perlinterp \
  --enable-pythoninterp \
  --enable-rubyinterp \
  --enable-termtruecolor

make
make install

其實就是現在 ZyX 自己維護的 git repo 已經是有把 True Color 支援的 code merge 進來的版本,只是現在的最新版設定上有些修改,差異在不一定會直接輸出 true color 的色碼 sequence 了,要 Terminal Type 是xterm的時候才有。如果不是xterm的時候則需要加上設定檔,告訴 Vim 要怎樣輸出色碼的 sequence:

let &t_8f="^[[38;2;%lu;%lu;%lum"
let &t_8b="^[[48;2;%lu;%lu;%lum"

其中的^[是控制碼,就像是 BBS 著色一樣,不能直接打,Vim 的話要用 Ctrl + v + [ 三個按鍵同時按來輸入。這兩個設定項目因為是 ZyX 版才有,所以如果是跑普通的 Vim 的話,啟動時會跑出警告,可以用:help xterm-true-color看看比較詳細的說明。

最後 iTerm2 雖然已經出 2.0 了,不過 True Color 的正式支援是放在 3.0,所以目前要在 Mac 上用 True Color Terminal 還是需要抓 nightly 版的 iTerm2。


JavaScript Parameter Complete

前陣子在 FB 上說過突然有想做的 Vim Plugin 已經開發的差不多,所以把 1.0 放上了,這個又是自動補完的 plugin,架構設計上是沒針對 JavaScript,不過目前我只有針對 JavaScript 做好補完選項,這個 Plugin 一開始是為了處理Web Crypto API,這組 API 在做加解密的時候是需要指定演算法,不過演算法的名稱裡面,有一些有-在裡面,像是SHA-256之類的,以前這種字串的關鍵字,還可以加到 syntax 裡面,然後用 syntax complete 來處理,不過-不是 JavaScript 的關鍵字,會被忽略掉,為了處理這個問題,就開發了這個 complete function,簡稱jspc.vim

這個 complete function 的功能自動補完各種函數內的字串參數,像是剛剛提到的 crypto algorithm,還有各種事件名稱,Media Type 等,其實越做發現越多這類的選項,目前支援的東西包括:

  • Web Crypto Algorithm Name
  • Event Name for DOM, jQuery, Backbone
  • HTTP Methods for XHR, fetch
  • HTTP Headers, some values
  • Locales for Intl
  • HTML Tag Name for DOM API
  • Image Type for canvas.toBlob, canvas.toDataURL

這個 function 的原理還蠻簡單的,如果抓到游標位置看起來在字串內(以下用底線代表游標位置):

n.addEventListener('cl_

然後就會往前找看看這是不是一個 function call 的內部,是的話去看看 function name,像是上面的範例就會找addEventListener,然後就去內部先定義好的表單找看有沒有候選的項目,有的話就會根據字串內容去做過濾後然後給回來。

如果前面有其他參數是不會受影響的,不過 function name 和字串要在同一行,然後除了 JavaScript 的語法用(做為判斷是不是 function call 之外,其實還有支援 CoffeeScript 那種只用空白接餐處的寫法:

n.addEventListener 'cl_

其實判斷方法很簡單,就是找空白前面不是,的話就是了,一時還想不到是不是有其他種語言的 function call 的語法跳脫這兩種寫法的,我想應該可以支援大部分的程式語言了,不過裡面的候選資料還需要人來做苦工,所以我只弄了 JavaScript 的 Web 相關的東西,然後同時給 CoffeeScript、LiveScript、TypeScript 用,安裝方法就照用 Pathogen 那套裝法就可以了裝起來直接用,因為實做上是把原本的 omni complete function 包起來,所以不用特別做什麼設定,就可以和其它自動補完的輔助工具合作,像是vim-autocomplpopneocomplcache.vim,其實本來是獨立一個 function 的,但是這樣要和 Neo Complete Cache 整合太難了,乾脆就走 Vim 的 omnicomplete 路線,結果意外的方便,最後就是有什麼問題歡迎提出摟~


Vroom

這次 COSCUP 因為講的是 Vim 的主題,就想說要用 Vim 來做投影片,第一個想到的是 OSDC 常客 Ingy 做的Vroom,這個套件也是他幾年前在 OSDC 用的,因為當年有聽他的 Talk 所以有印象,還算蠻簡單學的,安裝可以用 cpan 或是 cpanminus,然後看他的文件格式就可以開始寫投影片了,我還做了一個Vroom syntax,因為看著單色的文件看久了還蠻煩躁的,我想未來也有人會想要用 Vim 來做簡報,所以就花了些時間把它弄的比較完美,以後應該就會有其他人用的上了吧。


JavaScript on Vim

今天在 COSCUP 講的 JavaScript on Vim 投影片因為是用Vroom做的,所以沒有 PDF 可以上傳到 SlideShare 和 Speaker Deck,不過他有內建生成 html 版,所以我開了個gh-pages來放著讓大家看,按鍵盤空白鍵是下一頁,Backspace 是上一頁。

這次有超過時間,事前練習也超過一點,不過這次正式上場講的還比較慢,結果總時間就不夠了,算是意外,所以只好補充一下最後面我想要說的。如果你要學 Vim Script,除了看教學外,有個很重要的東西就是 Vim Document,一定要學著如何閱讀,包括怎麼搜尋、怎樣在文件連結中穿梭等等,Vim 的文件是我看過的程式文件中數一數二詳細的,幾乎是把 Vim 的所有細節都寫在內了,有些時候你的問題可能用 google 搜尋不到,但是其實文件內都已經有記載了,所以學習讀他真的很重要。

會後有聽眾跑來跟我說 Vim 可以輸入:help ctrl然後還不要按 enter,改按 CTRL + D,會變成用 ctrl 當關鍵字搜尋所有的 help document 連結關鍵字,我覺得這功能應該是蠻有幫助的,所以在這邊補充一下。


True Color Terminal Vim on OSX

True Color 指的是紅綠藍三原色每個顏色都用 8bit 來記錄色階,總共有 2 的 24 次方種顏色,一般台灣是稱為 1677 萬色,也就是現在主流的電腦螢幕顏色數,不過終端機介面,一直以來都是活在 16 色和 256 色的世界,所以我一直都是只能用 256 色的 Vim,雖然 GVim 有支援 True Color,不過我用 GVim 實在很不習慣。

前陣子在usevim上看到24-bit Vim這篇文章,讓我對 True Color 的 Vim 環境燃起了一線希望,大概的狀況是據說有個 ISO-8613-3 有設計了 TrueColor 的 notation,就長的很像 BBS 上色語法,但是有三個數值。所以只要大家都有支援,就可以看到 1677 萬色的終端機了,而所謂的大家都有支援,指的是:

  1. 命令列軟體輸出有支援,這邊需要的就是 Vim 能支援輸出 ISO-8613-3 所定義的語法
  2. Terminal 軟體有支援,看到 ISO 語法能呈現對應的顏色,以 OSX 上來說,我用的是iTerm 2

24-bit Vim 這篇文章說的是 Vim 有位 ZyX 有實做了 True Color 支援,而當時有個叫Konsole的 KDE Terminal 支援 True Color,所以要是你是用 KDE,就可以有 True Color 的 Vim 環境了,只是我用的環境幾乎都還是 OSX 為主。最近 iTerm 2 的作者在 Twitter 上說他們的 24-bit color 支援 merge 到 master了,本來我一直在等 beta 版的更新,不過今天突然想到,可以去找nightly build,然後去抓了測試用的 perl 檔來測試,發現真的可以用,下面兩張圖,上面那張是不支援的版本,下面的是支援的。

256 color terminal

true color terminal

接下來,就是 Vim 了,這部分我花了不少時間才弄出來,簡單說就是抓ZyX 的 Vim來自己 compile,不過也不是 clone 下來直接編譯就好,要換 branch 加上 config 等等:

hg clone https://bitbucket.org/ZyX_I/vim
cd vim
hg update 8abaeea8b2e5
cd src && make autoconf && cd ..

./configure \
  --enable-gui=no \
  --without-x \
  --enable-multibyte \
  --with-tlib=ncurses \
  --enable-cscope \
  --with-features=huge \
  --disable-nls \
  --enable-perlinterp \
  --enable-pythoninterp \
  --enable-rubyinterp \
  --enable-termtruecolor

make
make install

照理說上面這段複製貼上執行就可以了,然後,編譯安裝完,進入 Vim 可以執行version看看 termtruecolor 這個選項有沒有打開,有的話,那還差一步,就是在 .vimrc 裡面加上一行把設定打開:

set guicolors

然後你的 Terminal Vim 就會去使用 GVim 用的顏色設定了,以solarized為例,上面是 256 色的,下面是 True Color:

256 solarized

true color solarized

其實,差異蠻大的,讓我蠻意外,最後我找了一些以前沒辦法看到真相的 Vim color 來用,目前暫時是用jellybeans

true color jellybeans

至於 iTerm 2 和 Vim 官方何時會支援呢,前者比較樂觀,下次 release 就有了,後者的話,大約半年前 Bram 有說會加到 TODO,不過到目前的 7.4 看來都還沒有認真要面對它的樣子...


此類別所有文章