因為現在主要都是在寫 javascript 為主,所以這兩天調整 Vim 主要目標都是為了 javascript,這篇整理一下使用的 plugin 和相關設定,不過在開始前,請先把 Vim 升級到 7.2,套件沒有的話自己編譯也可以。
syntax/indent
Vim 雖然有內建支援 javascript 的縮排和語法標籤,不過另外都有人維護比較完整的版本,而且不只一種,我沒詳細比較,只是挑看起來比較有在維護的:
- JavaScript syntax : Better JavaScrirpt syntax support
- Javascript Indentation : Indentation for Javascript
照說明把檔案放到正確的位置即可,另外雖然有 jQuery 的 syntax ,不過我安裝後發現會和 The NERD Commenter 衝突,而且看一下內容覺得也沒做的很好,就沒用了。縮排的部份也有人是用外部程式來處理,詳細可以 vim-taiwan 上的 討論 ,我目前是還沒覺得有需求。
自動完成
這部份就比較麻煩了,在自動完成我使用了 snipMate ( 以前 用 snippetsEmu ,不過都沒更新了,而且內建的 snippets 少很多),還有 autocomplpop ,兩者安裝都很簡單,就解到 .vim 目錄下,或是用 c9s 大大寫的 Vimana ,snipMate 別忘了先 hack 一下 讓它支援 autocomplpop ,autocomplpop 雖然新版已經有幫不少檔案格式設定好預設的行為了,包括 html 和 css,但是卻不包含 javascript,所以還要自己設定一下,在 vimrc 裡面加上以下的設定:
let g:acp_enableAtStartup = 1
let g:acp_completeOption = '.,w,b,u,t,i,k'
let g:acp_behaviorSnipmateLength = 1
let g:acp_behaviorKeywordCommand = "\<C-n>"
let jsbehavs = { 'javascript': [] }
call add(jsbehavs.javascript, {
\ 'command' : "\<C-x>\<C-u>",
\ 'completefunc' : 'acp#completeSnipmate',
\ 'meets' : 'acp#meetsForSnipmate',
\ 'onPopupClose' : 'acp#onPopupCloseSnipmate',
\ 'repeat' : 0,
\})
call add(jsbehavs.javascript, {
\ 'command' : g:acp_behaviorKeywordCommand,
\ 'meets' : 'acp#meetsForKeyword',
\ 'repeat' : 0,
\ })
call add(jsbehavs.javascript, {
\ 'command' : "\<C-x>\<C-o>",
\ 'meets' : 'acp#meetsForKeyword',
\ 'repeat' : 0,
\})
let g:acp_behavior = {}
call extend(g:acp_behavior, jsbehavs, 'keep')
這樣編輯 javascript 時應該就會做正確的跑出自動完成的候選選項,包括 snipMate、關鍵字自動完成、和 omni 自動完成(好像有翻成全補完的),順便提一下,Vim 7.2 大部分檔案格式不用去設定 omnifunc ,幾乎都會指到自己的預設函式,不過 html 卻沒有,還要自己加下面這行到 vimrc :
autocmd FileType html set omnifunc=htmlcomplete#CompleteTags
而且最好依照我 上一篇的建議 修改一下。
code 檢查
再來是設定讓 jslint 檢查 javascript 程式碼,用的是 jslint.vim ,要記得先安裝 spidermonkey ,然後照說明把檔案移動到 ~/.vim 裡面,這樣就可以執行 :JSLint 來檢查程式碼了,不過一開始一定會發現它對所有的全域變數都發出錯誤訊息,這時可以加上一些設定參數放到 ~/.jslintrc ,我的設定檔內容(其實就是 jslint.vim 提供的範例):
/*jslint browser: true*/
/*global jQuery $ */
第一行是說這些 code 是網路用的,用瀏覽器來執行,所以在這種環境下會出現的全域變數就不會被當成錯誤,第二行則是你自己定義會使用到的全域變數,這個範例是加上了 jQuery 的兩個全域變數,這些設定也可以加在 js 檔案裡面,其他的設定參數請看 官方說明 。不過每次都要執行 :JSLint 也是蠻麻煩的,所以可以設一下快速鍵,另外也可以設定存檔時自動檢查:
map <F12> :JSLintLight<CR>
map <F11> :JSLint<CR>
autocmd FileWritePost,BufWritePost *.js :JSLint
壓縮
最後就是壓縮了, 以前有寫過個 function ,因應 closure-compiler 的出現和建議,現在有作些修改:
function Yuic ()
let cwd = expand('<afile>:p:h')
let nam = expand('<afile>:t:r')
let ext = expand('<afile>:e')
if -1 == match(nam, "[\._]src$")
let minfname = nam.".min.".ext
else
let minfname = substitute(nam, "[\._]src$", "", "g").".".ext
endif
if filewritable(cwd.'/'.minfname)
if ext == 'js' && executable('closure-compiler')
cal system( 'closure-compiler --js '.cwd.'/'.nam.'.'.ext.' > '.cwd.'/'.minfname.' &')
elseif executable('yuicompressor')
cal system( 'yuicompressor '.cwd.'/'.nam.'.'.ext.' > '.cwd.'/'.minfname.' &')
endif
endif
endfunction
autocmd FileWritePost,BufWritePost *.js :call Yuic()
autocmd FileWritePost,BufWritePost *.css :call Yuic()
至於怎麼裝 yuicompressor 和 closure-compiler 就因系統而異了。
其他
其他還有兩個不是針對 javascript 的 plugin ,不過寫程式時蠻有用的,分別是 The NERD Commenter 和 Align ,The NERD Commenter 是快速註解用,Align 則是對齊用,例如一連串的變數初值指定,可以用 :Align = 來把等號左右兩邊的程式碼對齊,美觀不少。