2009/02/24

打造自己的VIM: 樹狀檔案列表 NERD Tree

在VIM中,提到樹狀的檔案列表一定會讓人馬上想到[NERD Tree]。下圖為它的一個截圖,左邊紅框圈起處就是window of NERD Tree。[這裡]是作者提供的一個demo,看完demo就能完全知道這個plugin在做啥了。



NERD Tree的特色有:
  • 樹狀顯示檔案及資料匣
  • 資料匣或檔案的書籤
  • 以各種不同方式開啟檔案 (split of buffer)
  • 快速移動至各種節點
  • 可自訂NERD Tree window的位置
  • 支援滑鼠 (都在用VIM了,誰還在用滑鼠)
  • 過濾檔案內容
  • 檔案系統的操作 (刪除/移動檔案等等)

安裝方式自己參閱[官網]。


快速鍵及目錄定義

一個在Tools底下的目錄及F5開啟/關閉NERD Tree

an 50.20 &View.File\ Viewer<Tab><F5> <ESC>:NERDTreeToggle<CR>
map <F5> <ESC>:NERDTreeToggle<CR> " Toggles NERD Tree view (file viewer)



常用指令彙整


" ----------------------------
" 基本操作
o: 開檔/資料匣/書籤
x: 關資料匣
O: 開資料匣包含子資料匣
X: 關資料匣包含子資料匣
D: 刪除書籤

" ----------------------------
" 巡訪樹快速鍵
P: 到根目錄
p: 到母節點
K: 到第一個兄節點
J: 到最後一個兄節點
Ctrl+j: 到下一個兄節點
Ctrl+k: 到上個兄節點

" ----------------------------
" 檔案系統
C: 改變根目錄至所選資料匣
u: 改變根目錄至上一層的根目錄
U: 改變根目錄至上一層的根目錄且原來的目錄開著
cd: 改變工作目錄到現在所選目錄

" ----------------------------
" 書籤指令
:Bookmark <name>
:BookmarkToRoot <name>
:RevealBookmark <name>
:OpenBookmark <name>
:ClearBookmarks [<name>]
:ClearAllBookmarks


2009/02/17

打造自己的VIM: 檔案搜尋 FuzzyFinder

小弟在為我心愛的VIM找如何快速尋找檔案的plugin時,不小心找到一個超強的plugin,[FuzzyFinder],FuzzyFinder的功能只能說強到爆炸,有了它真是為了VIM的愛好者帶來了巨大的便利性。

FuzzyFinder它能夠幫我們快速找到好幾種東東,那些東東包含了:
  • Buffer (已開啟的檔案)
  • File
  • Tagged file (找在tag裡頭的檔案)
  • Most recently used(MRU) files (最近開過的檔案)
  • Directory (快速切換工作目錄)
  • Bookmark (使用FuzzyFinder建立及使用書籤)
  • Tag (模糊比較tag檔內的keyword)
  • MRU-Command (最近使用過的指令)

它的安裝方式請自己去官網下載.vim,再將.vim放到plugin裡面。以下我將只介紹如何使用它來找檔案及找tag功能,而其它功能因為用法太類似,所以各位就自行抓回去好好享受用它來開檔的快感吧。


File Mode

使用:FuzzyFinderFile指令來開啟FuzzyFinder的file mode,接著便能輸入一些pattern,FuzzyFinder就會幫我們找到類似的檔名,亦或者可以按下方向鍵的上下或Tab和Shift-Tab來直接選擇檔案。如下圖:



若是在資料匣上按下Enter,FuzzyFinder會幫我們自動補齊資料匣名,若是在檔案上則會直接開啟檔案,而開啟檔案的方式還有很多種,各位可以自己去參考文件,或是文章下面的指令彙整有稍微提到。

剛才的搜尋只限定在同一資料匣內,若我們想在搜尋資料匣內包含子資料匣內的檔案的話我們可以使用**\的wildcard,舉例來說,若我要在當前資料匣包含所有子資料匣內找1.txt這個檔案,我就可以打**\1.txt。(**這個符號不只針對FuzzyFinder是這個意思,在VIM中的一些其他地方,像某些built-in function也是這個意思)。下圖是我在arch資料匣找所有的.S檔案。


Tag Mode

FuzzyFinder的Tag mode有2種用法,一是不帶參數,第二則是帶參數。不帶參數如下圖,


它的用法跟File mode差不多,一樣先執行:FuzzyFinderTag,接著輸入tag來找tag檔內的關鍵字。但使用這種模式前,請先確認自己有tag file,若是不知道如何產生tag file,可以參考我[之前的文章]安裝並設定ctags,接著再參考[另一篇文章]產生tag file。

以上是第一種用法。第2種用法是有帶參數的,其用法為:FuzzyFinderTag 關鍵字。這邊我會加上快速鍵Ctrl+\,因為在某些時候FuzzyFinderTag會比Ctrl+t好用。快速鍵的語法如下:

map <silent> <C-\> :FuzzyFinderTag! <C-r>=expand('<cword>')<CR><CR>

配置好了,以後就只需在要查的關鍵字上按下Ctrl+\便能用FuzzyFinderTag來查詢,下圖是個範例,我在unwind_init函式上按下Ctrl+\則FuzzyFinderTag便直接開始查詢我要找的關鍵字。




指令彙整

以下我整理了一些關於FuzzyFinder的指令:

:FuzzyFinderBuffer " launchs Fuzzyfinder as Buffer mode.
:FuzzyFinderFile " launchs Fuzzyfinder as File mode.
:FuzzyFinderDir " launchs Fuzzyfinder as Directory mode.
:FuzzyFinderMruFile " launchs Fuzzyfinder as MRU-File mode.
:FuzzyFinderMruCmd " launchs Fuzzyfinder as MRU-Command mode.
:FuzzyFinderBookmark " launchs Fuzzyfinder as Bookmark mode.
:FuzzyFinderTag " launchs Fuzzyfinder as Tag mode.
:FuzzyFinderTaggedFile " launchs Fuzzyfinder as Tagged-File mode.


開啟選擇選項可以以下面這幾種模式:
<cr> - opens in a previous window.
<c-j> - opens in a split window.
<c-k> - opens in a vertical-split window.
<c-]> - opens in a new tab page.


其他:
<c-l> or <c-o> " To Switch the mode without leaving Insert mode.
<c-t> " If you want to temporarily change whether or not to ignore case
<c-e> " 暫時關閉pop視窗
<c-x><c-u> " 重新打開pop視窗
:FuzzyFinderRemoveCache " 刪除Cache資料



快速鍵及目錄

小弟新增以下幾個常用功能為快速鍵,將這些加入自己.vimrc吧。

map ff <esc>:FuzzyFinderFile<cr>
map fcd <esc>:FuzzyFinderDir<cr>
map fba <esc>:FuzzyFinderAddBookmark<cr>
map fbl <esc>:FuzzyFinderBookmark<cr>
map fu <esc>:FuzzyFinderBuffer<cr>
map <silent> <c-\> :FuzzyFinderTag! <c-r>=expand('<cword>')<cr><cr>
map <c-f12> <esc>:!ctags -R --c++-kinds=+p --fields=+iaS --extra=+q .<cr>


目錄部分則是,加在Tools裡頭,截圖如下:



其script為以下那幾行,各位可以加在自己的.vimrc也可以加在menu.vim,或是有人懶得自己加,可以直接抓我的[menu.vim]回去用。
an 40.310.10 &Tools.F&uzzyFinder.&File<tab>ff <esc>:FuzzyFinderFile<cr>
an 40.310.10 &Tools.F&uzzyFinder.Tag&File <esc>:FuzzyFinderTaggedFile<cr>
an 40.310.20 &Tools.F&uzzyFinder.&Dir<tab>fcd <esc>:FuzzyFinderDir<cr>
an 40.310.30 &Tools.F&uzzyFinder.&Bookmark<tab>fbl <esc>:FuzzyFinderBookmark<cr>
an 40.310.40 &Tools.F&uzzyFinder.&BookmarkAdd<tab>fba <esc>:FuzzyFinderAddBookmark<cr>
an 40.310.50 &Tools.F&uzzyFinder.B&uffer<tab>fu <esc>:FuzzyFinderBuffer<cr>
an 40.310.60 &Tools.F&uzzyFinder.&Tag <esc>:FuzzyFinderTag<cr>
an 40.310.70 &Tools.F&uzzyFinder.MRU-&File <esc>:FuzzyFinderMruFile<cr>
an 40.310.80 &Tools.F&uzzyFinder.MRU-&Command <esc>:FuzzyFinderMruCmd<cr>
an 40.310.90 &Tools.F&uzzyFinder.-SEP1- <nop>
an 40.310.100 &Tools.F&uzzyFinder.ClearCache <esc>:FuzzyFinderRemoveCache<cr>


打造自己的VIM: 源碼追蹤(ctags+cscope)及預覽視窗SrcExpl

Windows上重量級的源碼追蹤程式Source Insight,其最重要的功能之一就是他能依據程式內的函式名、結構名或其他源碼內使用之關鍵字,快速跳躍至該關鍵字的宣告或定義處。

超強編程軟體 - VIM - 也有這種能力。我們用VIM doc裡的文件來解釋一下什麼叫根據源碼關鍵字跳到定義處。如下圖:





我 們在write_block函式內用到write_line,若我們想看一下write_line的定義,在VIM裡只需將游標移到write_line 上,按下Ctrl+]就可以跳到該函式處。更進一步,在write_line裡頭用到write_char,我們也只需在write_char上按下 Ctrl+],又能再跳到write_char定義處。這樣的功能在追蹤大型的程式時是很方便的功能,在VIM要有這樣的能力只需一些小小的設定就能達 到。

本文參考2份VIM document,分別為[usr_29]及[tagsrch]。


ctags安裝及使用


要使用源碼追蹤的功能預設是必需在工作目錄下存在一個檔名為tags的檔案,該檔案會紀錄源碼內所有的關鍵字出現位置,tags file的產生可藉由ctags這支程式,ctags的安裝方法我在之前的文章[TagList]已經有介紹過了,所以這裡不再累述,需要安裝的人請參考那篇文章。

產生tags方式,必需先切換工作目錄至源碼根目錄下,並輸入下面指令(在命令提示字元下則不要輸入:!喔):

:!ctags -R --c++-kinds=+p --fields=+iaS --extra=+q .

如此就會產生一名為tags的檔案在此目錄下,是不是很容易呀。

另 外,還有一種情形值得一提,有時源碼庫是很大一包,每次執行ctags產生tags file可能會需要一段不短的時間,而我們維護的程式可能只是這一大包源碼庫的其中一個小小的資料匣,因此我們有時會只希望更新我們維護的資料匣,而不是 一大包的源碼庫。這種情形可以只在源碼的所在位置產生一個local tags file,並且再藉著tags option將local tag file加入tag搜尋檔案中。

首先在目前編輯檔案所在位置產生tags:

:!ctags -R --c++-kinds=+p --fields=+iaS --extra=+q -f "%:p:h\\tags" "%:p:h"

因 為tags option預設為./tags,tags (輸入:set tags即會顯示出來),因此只要產生local tags file即會自動被加入tag搜尋檔案中,不需再做設定tag搜尋檔案的工作。在網路上可以查到許多教各位如何將STL的header加入tags搜尋檔 案中,它的方法也是先在STL源碼庫內使用ctags產生tags file,接著再設定tag option。

有了tags files我們便可以開始追蹤源碼了,追蹤源碼我較常用到這幾個功能,當然這些功能有不少被後後的快速鍵給取代掉了:

Ctrl+] " 根據游標所在位置的字串常做關鍵字,跳進去(快速鍵:tj)。
Ctrl+t " 跳出來。
:tselect " 當有多個關鍵字在tags file中被找到時,可用tselect來選。
:tags " 查看現跳到那裡了快速鍵:ta)。
:tnext " 跳到下一個被找到的tag(快速鍵:tn)。
:tprev "跳到前一個被找到的tag(快速鍵:tp)。



cscope安裝及使用


cscope與ctags十分類似,只是它有些功能是ctags所沒有的(cscope似乎可以完全取代ctags ??),所以我在這裡就稍微提下它的安裝及用法。

首先要安裝cscope.exe跟之前安裝ctags一樣,也是使用cygwin即可安裝它的windows版本,這裡我就不再贅述。另外對於VIM有人已經製作了它的keymapping及自動載入cscope reference file(cscope.out)的script [cscope_maps.vim],將它下載後放至vim72\plugin裡即可。

如同ctags,cscope也要建立一個cscope.out的參考檔。建立方式如下:

cscope -Rbkq

除了讓它自己去搜尋所有檔案,你也可以自己指定一份檔案列表,我們可以先用find(cygwin, NOT windows find)找出所有.cpp及.h的檔案再讓cscope.exe去讀取。如下:

find . -name "*.h" -o -name "*.c" -o -name "*.cc" > cscope.files
cscope -Rbkq cscope.files


以下為cscope_maps.vim提供的功能及對應的按鍵:

Ctrl+\ s "s表Symbol,列出所有參考到游標所在字串的地方,包含定義和呼叫。
ctrl+\ g "g表Global,與ctags的Ctrl+]相同。
ctrl+\ c "c表Call,列出所有以游標所在字串當函數名的地方。
ctrl+\ t "t表Text,列出專案中所有出現游標所在字串的地方。
ctrl+\ f "f表File,以游標所在字串當檔名,開啟之。
ctrl+\ i "i表Include,以游標所在字串當檔名,列出所有include此檔的檔案。
ctrl+\ d "d表calleD,以游標所在字串當函式名,列出所有此函式呼叫的函式。


若想知道其他更詳細的用法可以參考:cs內的內容。

ps. 若是出現"沒有cscope連線",這應該是你的工作目錄下沒有cscope.out檔案,若是想不想關掉VIM卻想自行加入cscope連線,可以參考:cs connect指令。

參考資料: http://www.yuanma.org/data/2006/0908/article_1487.htm

快速鍵設定

我設定了2個快速鍵來建立global and local tags file,分別為Ctrl+F12及F12。以及多個快速鍵來來方便tag的使用,其設定如下:

map :!ctags -R --c++-kinds=+p --fields=+iaS --extra=+q -f "%:p:h\\tags" "%:p:h"
map :!ctags -R --c++-kinds=+p --fields=+iaS --extra=+q .
map :!cscope -Rbkq
nmap :exec "tjump ".expand("")
nmap :exec "ts ".expand("")<>CR>
nmap :exec "tnext"
nmap :exec "tprevious"


預覽視窗 SrcExpl

狂熱於使用VIM的開發人員至此還不是很滿意,他們想為什麼我們不分割一個視窗來做源碼預覽的效果,[SrcExpl]也就因此誕生了。它的截圖如下:



呼 叫SrcExpl預覽視窗為指令:SrcExplToogle,以上圖為例原先在編輯init/main.c,在叫出SrcExpl預覽視窗後,當我們移 到任意的關鍵字上,SrcExpl預覽視窗就會自動將查詢到的tags顯示在視窗內。上圖為游標在boot_cpu_init()後,預覽視窗即馬上顯示 函式定義。

說老實話,我大部份的時候很喜歡這個套件,但對於大project我很討厭它。主要原因是對於很大的project時,它tag檔很大,如果我開著這個功能我整個VIM都頓頓的,整個用起來很煩。各位看倌還是自己視情形用它吧

另外,呼叫SrcExpl預覽視窗,我也定義快速鍵F7

map :SrcExplToggle

2009/02/12

VIM tip: 單行註解一整個區塊

在C/C++或是其它有單行註解(//)語法的程式中,程式員有時會因為某些原因而不使用多行註解(/* */),為了能快速使用單行註解註解一整個程式區塊,VIM有人寫了一些plugin來幫助註解。但實際上,有些小方法能快速在一片區域前快速加入一些字。

以下有一段程式,假設我們要在210到215行插入註解為 "; Rickey modifies "。


我們先用區塊選擇將210到215行選起來,Windows為Ctrl+Q,Linux上為Ctrl+V,如下圖:



選起來後進入插入模式,按i,並輸入要插入的註解


最後按ESC離開便完成了。 (傑克!這真是太神奇了)

打造自己的VIM: 函式列表 TagList

[TagList]對於程式員而言是個不個貨缺的plugin。它提供了檔案內的結構、define及函式列表,並能讓使用者快速跳到這些變數的定義處。安裝TagList的過程中,除了將TagList抓下來,放到$VIM資料匣內,另外使用者必需提供一支外部程式ctags。本文將介紹在windows XP環境下如何安裝ctags及TagList的配置。


安裝

在將TagList解壓縮放到$VIM資料匣後,在Windows XP下我們必需再安裝ctags,小弟是用cygwin的安裝方式。進入[cygwin的首頁]後,在首頁下方會看到一個setup.exe的程式下載處,抓下來執行後便開始安裝了,安裝的過程中我們要選擇從網路上取得套件、套件取得的server、安裝位置等,最後一步則是選擇套件,選擇套件記得一定要選ctags,它位於Devel下,如下圖(若是有需要,你可以一便在Devel下找到gcc及make的套件來安裝),之後點選下一步後就開始安裝了。(在ubuntu下安裝因為太簡單,應該就不用介紹了)



安裝完後,ctags會放在c:\cygwin\bin下,接著我們就設PATH變數好讓TagList找得到ctags程式,在「我的電腦」上按右鍵選內容,其它步驟請看下圖。


接著我們打開「命令提示字元」應該打ctags應該就能執行ctags了。


配置TagList

快速鍵我是用F6,所以我在vimrc加入:

map <F6> <ESC>:TlistToggle<CR>

Menu我則是加在View底下,Menu加的方法請參考我以前我的[文章]。另外,底下是一些我覺得比較有機會用到TagList變數,我列在下方,後面都有註解,所以就自己看一下吧。

let Tlist_Show_One_File = 1 " Displaying tags for only one file~
let Tlist_Exist_OnlyWindow = 1 " if you are the last, kill yourself
let Tlist_Use_Right_Window = 0 " split to the right side of the screen
let Tlist_Sort_Type = "order" " sort by order or name
let Tlist_Display_Prototype = 0 " do not show prototypes and not tags in the taglist window.
let Tlist_Compart_Format = 1 " Remove extra information and blank lines from the taglist window.
let Tlist_GainFocus_On_ToggleOpen = 0 " Jump to taglist window on open.
let Tlist_Display_Tag_Scope = 1 " Show tag scope next to the tag name.
let Tlist_Close_On_Select = 0 " Close the taglist window when a file or tag is selected.
let Tlist_Enable_Fold_Column = 0 " Don't Show the fold indicator column in the taglist window.
let Tlist_WinWidth = 40


以上都都設定完後,以後只要按下F6就可以叫去TagList了,如下圖。




2009/02/11

打造自己的VIM: QuickFix 編譯視窗

QuickFix視窗(之後簡稱QF)在VIM裡是一個很方便的功能,它最常見的功能是將編譯時的輸出訊息導入到QF中,在QF中,我們可以快速切換至編譯錯誤的檔案及錯誤行上。除了這個功能外,我們亦可用一些plugin將搜尋字串或檔案的結果輸出到QF內,以方便我們快速瀏覽。

本篇文章,將簡介如何將QF用在編譯除錯及常見指令彙整,最後我將為QF做一些更方便快速鍵。本篇文章參考自VIM document [quickfix]


QF簡介

在編譯程式時,不管在Linux平台或Windows平台,make是最常使用到的專案管理工具之一。VIM則提供了一個:make的指令去呼叫外部make,可能是gmake或nmake來協助編譯程式並輸出到QF視窗中。與:make有關的選項,各位可以參考:options中第23大項的內容,如下圖或VIM document [quickfix]。



接著,我將由一個C的hello world帶領各位使用QF。因為編譯時會呼叫到外部指令,gcc或make,所以請各位在開始前先確定自己的shell(cmd.exe or bash)可以正確執行gcc及make。我的環境是Windows XP及Cygwin(包含make及gcc),並且在環境變數PATH加入了cygwin bin的路徑。

首先,我們先寫一個有問題的hello world,如下圖,在第6行處有一個變數未宣告。接著我們輸入

:make a

其中:make為VIM指令,a為檔名不包含副檔名。在這裡make與nmake會有差別,nmake必需輸入a.exe,這是由於兩種make程式的predefined rule不同的關係。按下enter後,a.c的視窗下方就會自動彈出QF視窗(若是沒彈出來,自己輸入:copen指令),且包含了錯誤訊息,接著各位可以再試:cnext或:cprev的指令來切換下一個或前一個錯誤訊息,在切換的過程,若檔案或行號不同,它會自動幫我們跳到該處。


對於一般的小程式(只有一份source code,不用複雜的compile和link),這樣的功能應該就夠了,對於稍有規模的專案則寫一個makefile就是必需的了,至於makefile要怎麼寫,各位就自己去查一下了,網上資源一堆。


指令彙整

我只列出我常用的。

:make " 編譯程式

:copen " 打開QF視窗
:cclose " 關閉QF視窗

:cnext " 移到下一個錯誤
:cprev " 移到前一個錯誤

:cnewer " 若有多個QF buffer,移到下一個錯誤訊息列表
:colde " 若有多個QF buffer,移到前一個錯誤訊息列表



快速鍵

跟QF有關的指令真是又多又長,若是用了前幾篇的[自訂目錄]的話,應該可以發現我加了幾個快速鍵,如下圖,我將依此目錄我有修改的部份一個個講解。這些分別為:
  • QuickFix switch
  • Newer List
  • Older List
  • Next Error
  • Previous Error
這些東西可以視自己的需要加到vimrc裡。


QuickFix Switch

切換QF視窗不只指令長,打開關閉也要用不同指令,實在是非常麻煩,所以小弟寫了一個小function及一個map便可用F8鍵來做切換QF的功能。

map <F8> <ESC>:call QFSwitch()<CR>
function! QFSwitch()
redir => ls_output
execute ':silent! ls'
redir END

let exists = match(ls_output, "[Quickfix List")
if exists == -1
execute ':copen'
else
execute ':cclose'
endif
endfunction

其它指令

因為其他都只是alias而已,我直接列出來我的設定。

map <F8> <ESC>:QFSwitch<CR>
map <S-F8> <ESC>:colder<CR>
map <C-F8> <ESC>:cnewer<CR>
map <C-n> <ESC>:cnext<CR>
map <C-p> <ESC>:cprev<CR>




2009/02/10

QTTabBar: 為windows檔案總管加上快速鍵

在公司實在沒辦法的情況下,只能在windows上工作,windows的檔案總管不像nautilus一樣,有很方便的tab功能,因此我google找到了這個軟體,它不只為檔案總管加了tab,它還提供了一些自訂的快速鍵,這對於我未來會分享的VIM有點關係,所以我先跟大家分享一下這個軟體。

[QTTabBar]網上一堆介紹我也不簡介了,畢竟我不會寫的比他們好。我只用幾張圖說明如何利用檔案總管,快速在當前目錄開啟VIM(快速鍵Ctrl+Alt+V)。如果有人不想看如何設定,我把我的設定檔放在[],需要的人安裝完QTTabBar後,把設定檔抓回去再雙點它就可以用我的設定了。







題外話,在gnome檔案總管nautilus也可以達到類似功能,我的方法是自己寫個開啟VIM在當前目錄的script放在自己的nautilus script資料匣,以後要開VIM則按鍵盤上的打開popup menu鍵,接著按S到script的menu item,最後再用方向鍵選擇script即可。等我把VIM系列寫完,再跟大家分享。


VIM tip: Pipe 使用外部命令處理VIM內資料

部分內容參考自[Daily VIM: Piping Buffers],完整的VIM doc請參考[change]

想使用外部指令來處理VIM內容,關鍵在於"!"這個filter command,舉例來說現在讀取VIM內的文字並交由外部程式sort處,可以這樣做:

:% ! sort

其中%是表文本內容(?)(應該是檔名吧? 有誰知道這個從vim doc那來的),最後的輸出結果也將目前文本內容全部取代。再舉一個例子,這個例子是用cat來加行號:

:% ! cat -n

有時我們是要由外部命令讀取資料進來,而且不想將外部指令的結果取代掉所有文本內容,這時我們可以用":r"這個命令。舉例來說,將ls輸出到游標所在處:

:r ! ls

再回到剛才cat的例子,我們若想插入文本內容,卻又不想取代掉現在文本內容,我們可以這樣做:

:exec ":r ! cat -n ".expand("%")

exec是叫VIM做這個命令,命令內容為後面那一串,其中expand("%")表示目前編輯的檔案檔名,所以這個命令在未儲存檔案時不能用的喔~~

打造自己的VIM: Folding


對於比較多行的程式,有時候源碼褶疊能隱藏函式或結構的定義,而只顯示函式的宣告,下圖是源碼折疊的一個簡單例子。



在VIM中,源碼折疊可以分成多種方法,我這裡只簡單介紹我會用到的幾種折疊方式,隨後會再介紹跟程式折疊有關的指令。本篇文章共參考到2份VIM document,分別為[user_28]及[fold]

折疊方式

我常用的折疊方式有3種,第1為syntax,簡單的說就是根據語言讓VIM幫你自動折疊程式,我大都使用這種。第2種為marker,很多VIM的script(plugin)都會採用這種,它是根據使用者在文檔中加入的特殊符號來折疊,VIM預設是用"{{{"及"}}}"來作為標示,並且為了讓這種標示不影響程式/文檔運行,通常這些標示會放在註解內,我們看一下下面2個例子。



這個例子太簡單,相信大家看一下就懂。而底下的另一個例子則在標示後面增加了一個號碼來說明這是第幾層的折疊



Mark這種折疊方式,我通常是用在整理某些特殊的比較沒有規則的文檔。

第三種折疊方式為為indent,這是根據縮排來折疊,這種折疊方式用在python這種程式,特別好用。

設置折疊的方式為foldmethod這個option

:set foldmethod=syntax

你可以把它加在vimrc裡,如果你常需要折疊功能的話。若你是像我一樣,偶爾用它,那就等文檔打開後再輸入這個指令,但這個指令也太長了,所以它有縮寫,像是上面的例可以取代成

:set fdm=syntax

此外,我比較常用的option為有這幾個foldnestmax(fdn)及foldcolumn(fdc)。foldnestmax它會限制最多折疊幾層,畢竟有時折疊太多層也很煩人,如下面這個指令它最多會折疊3種。

set foldnestmax=3

foldcolumn這個option則是設定在VIM最左邊預留一塊foldcolumn的空間顯示折疊情形,如下圖。




常用指令

zi      "啟用/關閉折疊

zo      "打開折疊
zc      "關閉折疊
zO      "打開所有折疊
zC      "關閉所有折疊

zx      "更新折壘,即除了游標所在折疊不關,其他都關掉




2009/02/09

打造自己的VIM: 書籤及游標移動

有在用ultraEdit或pspad等編輯器的人,應該都知道我們可以設置一些標籤(編號通常由1到0)在檔案的某些地方,這些標籤可以讓使用者快速回到設置標籤的位置。

在VIM裡當然也有這個功能且更強大,但就某方面來講,也可以說以便利性或是上手速度來說也較不容易。今天這篇文章會由簡入難,先跟大家簡述一下VIM的書籤功能,接著再介紹如何使用VisualMark來打造一個簡單易用的書籤環境,最後會跟各位分享我在VIM裡常用的游標移動功能,這些功能能讓各位更快的將游標移到自己想到的位置。

有關VIM document裡有關游標移動的章節為[motion],關於[書籤]的部分請參考這裡。


VIM的書籤功能

VIM的書籤分成2大類,1)同檔案內可以編號由a-z,2)跨檔案可以由編號A-Z,這兩類的差別是第一種在每個檔案內都有自己的書籤a-z,第二種則是所有檔案共享,換句話說,你可以由檔案A藉著書籤的方式跳至該書籤的所在檔案。

書籤設置的方法為

m{a-zA-Z}

舉例來說在normal mode底下輸入ma,即會設置書籤a。而輸入mA則是建立跨檔案書籤。

跳到書籤處的方式為

`{a-zA-Z}

"`"為1左邊的那個鍵。

顯示書籤則為

:marks

使用後大家或許會發現VIM的書籤的有個致命的缺點,就是他不會在每行的最左邊顯示這裡有設置書籤及書籤編號,這個缺點可以用[ShowMarks]這個Plugin來改善,此外ShowMarks也提供一些不錯用的快速鍵,有需要的人自己看一下他們網頁,自己稍微試一下吧。


VisualMark

[VisualMark]是另一個VIM書籤Plugin,請看下圖,它提供了2個功能,一是反白有書籤的行(圖362行及369),二是逐一(根據行號)跳至書籤位置。這是我常用的功能,我也把他加入到我的功能表了。並且在vimrc加入這些key mapping。

"<F9> mark: in plugin filesmap
<F9> <Plug>Vm_toggle_signmap
<c-F9> <Plug>Vm_goto_next_signmap
<s-F9> <Plug>Vm_goto_prev_sign





游標的瞬間移動


我以前幾乎不用這些游標移動的功能,後來發現螢幕愈來愈大光按著j (即向下),從螢幕第一行要移到最後一行挺痛苦的,所以我這裡稍微跟大家分享我自己常用的有關游標移動的快速鍵。

h "左
j "下
k "左
l "右

"這類移到我多到在選擇單字時
w "移動到下一個單字字首
W "移動到下一個單字字首,移動更多(某些標點符號不停)
e "移動到下一個單字字尾
E "移動到下一個單字字尾,移動更多(某些標點符號不停)
H "移到螢幕首
M "移到螢幕中
L "移到螢幕尾

zz "將目前所在行移到螢幕中
zt "將目前所在行移到螢幕第一行
zb "將目前所在行移到螢幕最後一行

* "往前找出游標所在字串 (按 n、N 繼續找)
# "往後找出游標所在字串 (按 n、N 繼續找)
gd "將游標所在字串視為 local 變數,找到定義此 local 變數的地方 (如果有的話)


% "找披配的括號
[[ "找函數的開頭
]] "找下一個函數的開頭

2009/02/07

打造自己的VIM: 多檔編輯TabBar

看圖比較快,如下圖,[Tabbar]就是上面那個檔案列表視窗。Tabbar的操作包含了:
  • 切換至下個視窗 Ctrl-Tab
  • 切換至上個視窗 Ctrl-Shift-Tab
  • 切換至第n個視窗(n為數字0-9) Alt-n
  • 用滑鼠雙點Tab名,像下圖的[2:iliad.h]
安裝方式請至[他們的網頁]看一下唄。




此外,我在用他們的plugin時,有時會不小心在-TabBar-的window內,按到切換檔案的鍵(像是剛剛提到的Ctrl-Tab, Ctrl-Shift-Tab...),降會要被切換到的檔案顯示在-TabBar- window中,若是想避免這種情形,其實是可以加一個自動指令及函式在vimrc裡,這個指令會在當window切換時自動被執行,加法如下:

autocmd! BufEnter * nested call Test()
func! Test()
if bufname("%") == "-TabBar-"
wincmd j ; 跳到下面的視窗
endif
endfunction


但是這樣寫會造成滑鼠雙點Tab名切換視窗的功能失效,要用的人自己斟酌一下。

(2009/2/9 新增)

在使用TabBar還有一個情形也是十分困擾我的,每次下:bd刪除buffer時,時常下個被顯示的buffer不會按照順序,舉例來說,假使我現在看第4個buffer,若是我用:bd將它將它關掉,下個被打開的視窗通常不會按照一定的規律跳到第3或第5個buffer,這個壞處是有時要關一個以上的buffer,不能一直:bd的按,把大於某個號碼的視窗全部關掉。所以我加了一個小函式及快速鍵在vimrc,它能在關掉buffer後,一定跳到前一個buffer,程式如下。

map <C-F4> <ESC>:call CloseTab()<CR>
func! CloseTab()
let s:buf_nr = bufnr("%")
echo s:buf_nr
exec ":Tbbp "
exec ":bdelete ".s:buf_nr
endfunction


(2009/3/11 新增)

TabBar裡其實有一些設定很少被提到,但是卻很實用,若需要更多的說明可以自己打開tabar.vim來看看,大概在100出頭行的地方,亦或是直接在code裡的某處。我這裡提一些看起來比較有用到的。

g:Tb_MaxSize (Default = 1)
有時開的檔案太多,TabBar視窗會容不下那麼多檔案同時在一行內被顯示,但是使用者(我)會希望它可以分成2行被顯示,這時只要將這個值設定2就行。

g:Tb_TabWrap (Default = 0)
若開啟檔案數超過一行可顯示且g:Tb_MaxSize又設成大於1時,超過一行可顯示的字會折到下一行而造成最後一個檔案標籤斷了,若設成1則它不會讓標籤斷掉,會直接讓行尾標籤放到下一行行首。

g:Tb_SplitBelow (1 = below, 0 = above(Default))
將TabBar視窗放在上面or下面

g:Tb_VSplit (0:top, 1:left)
將TabBar放在上面or左邊


我自己是設定這些值
let g:Tb_MaxSize = 2
let g:Tb_TabWrap = 1

2009/02/05

打造自己的VIM: 修改目錄(功能表)

本篇文章是[Make vim more powerful cont. and prolog]系列的第一篇。這篇文章要分享我修改vim目錄的一些分得,保括了修改目錄的方法、指令、希望修改的地方,最後將會貼一些修改後的圖及我的設定檔給各位取用。

VIM目錄基本上都會有一串數字來代表他的位置,舉例來說Close這個menu item所在的位置為10.330,如下圖所示,若想要再插入一個目錄在它底下其位址可介於10.330到10.335之間。若想在10.330處插入一個子目錄則是位址可以由10.330.0開始到10.330.9999。



指令

跟目錄有關的指令,基本上我只用到:anoremenu(abbr. :an)這個指令,它是用來插入一個目錄,而且不能remap。譬如說我想插入一個指令
  1. 在10.320的位置
  2. 第一層的menu item name為File且快速鍵為f
  3. 第二層的menu item name為Open Tab ...且沒有快速鍵
  4. 提示的指令為:tabnew
  5. 真正執行的指令為:browse tabnew
這個指令如下:

:an 10.320 &File.Open\ Tab\.\.\.<TAB>:tabnew :browse tabnew<CR>

要注意的是有些特殊字元必需用"\"來跳脫,像是"."或" "。另外<TAB>是換行的意思。

此外,若是想插入一個分隔線則指令如下:

:an 10.400 &File.-SEP2-

其中-SEP2-,同一階的目錄下名字必需不同。

若是想知道更多指令,亦或是針對不同mode出現的目錄,就自行參考[vim document usr_42]。此外,如果有人有興趣瞭解script基本語法,像是流程控制、變數型態、變數類型等等,可再自己看一下[vim document usr_41]。


目錄設定檔在哪?

可以用:version指令找到,截圖如下:



我想要改成...

在修改前,先列一下我們想要修改的地方吧:
  • 加入我自己的快速鍵
  • 把不會用到的功能刪掉
  • 一些我認為它擺錯地方的目錄移到正確的地方

修改後的結果...

Edit menu: 擴充了Find的指令,像是Find Files or Find in Files,還有一些有關設定的都放在這。


Tools menu: 加了不少自己工具,像是Code Trace、Virsual Mark等等,這些功能在之後的文章才會介紹。


View menu: 又加了不少特殊功能,F5到F7都是,這些都後面幾篇文章會介紹。



結論

「師父引入門,修行在個人」學習vim也是這樣,有心想要修改自己目錄的人都應該要自己開一下$VIMRUNTIME\menu.vim有看看,並且視自己的需求打造自己的編輯器,改過一些東西后就會發覺原來改目錄那麼簡單。所以,還等什麼,快點把你的設定檔打開吧!

我的設定檔:http://sites.google.com/site/fcwunctu/vim

2009/02/04

VIM tip: 將tab取代成space及程式縮排方式

最近找到一個vim的網站 Daily VIM,是關於一些vim tips,裡頭有些東西還不錯,近期如果有空應該會轉錄一些我覺得比較有用的到我這來。

過去將全文裡的tabs取代成space我多半用取代的方式:

:%s/\t/ /cgi

另一作法,vim控制tab距離是靠tabstop (option),若是要根據tabstop來轉換tab成space,可以用這個方法:

:set expandtab
:retab!


其中,tabstop的值可以用類似這種指令來控制:

:set tabstop=2

稍微提一下,expandtab不是只用到這裡,若是想在編輯時自動將tab轉換成space可以用此命令。而取代所有tab成space的命令是retab這行。

在縮排程式時,有另一個常用的情形是這樣,將某行右移一個tab距離,即在normal mode時,輸入>>。若要左移則輸入<<。若要縮排一個區塊則可用V先選擇欲縮排的區塊,再輸入一個<>即可。當然,若是想要多縮幾個tab距離則可以按.來重覆上一個動作。這裡的一個tab距離寬度是用shiftwidth這個option來控制的。

另外,還有一種自動縮排的功能"=",跟之前一樣先選擇一塊區塊用V鍵,再輸入=則自動完成縮排。

2009/02/03

打造自己的VIM

一年前寫了一篇關於vim的文章[Make vim more powerful], 那篇文章裡介紹了許多scripts或是小技巧,但現在來看這些scripts or tips都有一些更好的方法來取代之。此外,再加上最近因為開始了我的第一份"正式"的工作,所以我花了點時間,又重新修改我的vim環境,讓他更適合現 在的工作。這篇文章主要要介紹大都以之前那篇文章以底,並再做些更新,最後會再附上我目前的設定給大家參考。

以下是我所做的所有增加或修改,並且在後面列出快速鍵(如果有的話):
  1. [menu修改]
  2. [多檔編輯TabBar]
  3. [檔案總管 NERD Tree] (F5)
  4. [多檔字串搜尋 EasyGrep] (f/)
  5. [檔案搜尋 FuzzyFinder] (ff)
  6. [Folding 程式碼摺疊]
  7. [Marks 書籤及游標移動] (F9)
  8. [QuickFix 編譯視窗] (F8)
  9. [函式列表 TagList] (F6)
  10. [源碼追蹤ctags+cscope及預覽視窗SrcExpl] (F7)
  11. [源碼補齊 SuperTab OmniCppComplete Code_Complete]
  12. [YouCompleteMe 源碼補齊,最近改用這個]
因為功能不少,所以我也順便修改了menu,除了把我自己增加的功能放到menu裡(提醒用),也把原本gvim那不合理(我自認為)的MenuItems排列大搬家了一下,所以首先我會先介紹menu如何修改,並接序的主題儘量以menu來以一貫之。

除了這些內容外,關於VIM的文章還有VIM tip系列,要找到他們可以直接從右邊的搜尋欄輸入vim tip即可找到他們,當然這些內容會持續的更新。


最後,我的設定檔可以在[這裡]抓,需要的人請自行取用。

2009/02/01

Ubuntu: convert wav file to mp3

最近想在每天坐捷運時練練英文,我自認為英文讀寫的能力還不錯(比起聽說,聽說應該是爛到爆),所以買了一本比較注重生活會話的雜誌來每天閱讀,不知道這股拚勁什麼時候會消磨光 :)。那本雜誌的會話光碟是給wav檔,我的ipod nano沒法放那種檔案,所以只好先來轉檔了。(ipod nano是我可愛的女友送我的,大概用了2個禮拜,心得是"頗爛"。原因由iTune不好用,放歌很麻煩,音質不好)

前面都是廢話,跟本篇的主題一點關係都沒有。在Ubuntu中轉wav檔成mp3檔很簡單,先安裝lame
sudo aptitude install lame
接著再使用lame指令來轉,像是
lame -h -b 128 1.wav 1.mp3
上面是第一個方法,再介紹另一個方法,在ubuntu 8.10中的nautilus中己經有script可以幫助轉檔了,安裝這個套件 nautilus-script-audio-convert,再右鍵點選欲轉檔的檔案,選Scripts->ConvertAudioFile,接著steps by steps就完成轉檔了。