vi/vim使用進階: quickfix

:help quickfix
:help :make
:help 'makeprg'
:help 'errorformat'
:help 'switchbuf'
:help location-list
:help grep
:help :vimgrep
:help :grep
:help starstar-wildcard 

以前讀武俠小說,看到武林高手們都是從來劍不離手的。使用vim寫程序,你也可以做到這一點,:-)

vim由一個程序員開發,而且爲更多的程序員所使用,所以在vim中加強了對軟件開發的支持,quickfix模式的引入就是一個例子。所謂quickfix模式,它和Normal模式、Insert模式沒什麼關係,它只是一種加快你開發速度的工作方式。

Quickfix模式的主要思想是保存一個位置列表,然後提供一系列命令,實現在這個位置列表中跳轉。

位置列表的產生可以從編譯器的編譯輸出信息中獲得,也可以由grep命令的輸出信息中獲得,我們上篇文章所介紹的cscope命令,也可以產生位置列表信息(:help ‘cscopequickfix’)。

[編譯]

通常,我們在開發過程中,經常要寫代碼,編譯,修改編譯錯誤,這個過程會數十遍上百遍的重複。如果你是根據編譯器輸出的錯誤信息,打開出錯的文件,找到出錯的行,然後再開始修改,那效率未免太低下了。

利用vim的quickfix模式,可以大大加快這一過程,你可以在vim啓動編譯,然後vim會根據編譯器輸出的錯誤信息,自動跳到第一個出錯的地方,讓你進行修改;修改完後,使用一個快捷鍵,跳到下一個錯誤處,再進行修改,方便的很。

爲了做到這一點,你首先要定義編譯時所使用的程序,對大多數使用Makefile的項目來說,vim的缺省設置”make“已經可以滿足要求了。如果你的項目需要用一個特殊的程序進行編譯,就需要修改’makeprg‘選項的值。

大家在學編程時大概都讀過”hello world”程序,我們就以這個簡單的例子爲例,講一下quickfix模式的用法。

該程序的內容如下,裏面包含了三個小小的錯誤:

/* hello world demo */
#include <stdio.h"
int main(int argc, char **argv)
{
    int i;
    print("hello world\n");
    return 0;
} 

我們可以爲這個程序寫個小小的Makefile文件,不過爲了演示’makeprg‘的設置方法,我們並不用Makefile,而直接設置’makeprg‘選項,如下:

:set makeprg=gcc\ -Wall\ -ohello\ hello.c 

上面的命令會把hello.c編譯爲名hello的可執行文件,並打開了所有的Warnning。如果編譯命令中有空格,需要使用’\‘對空格進行轉義,上面的例子就使用了’\‘轉義空格。

我們設置好’makeprg‘選項後,輸入下面的命令就可以編譯了:

:make 

在使用”:make“時,vim會自動調用’makeprg‘選項定義的命令進行編譯,並把編譯輸出重定向到一個臨時文件中,當編譯出現錯誤時,vim會從上述臨時文件中讀出錯誤信息,根據這些信息形成quickfix列表,並跳轉到第一個錯誤出現的地方。

對於我們上面的程序來說,光標會停在第三行,也就是第一個出錯的位置,vim同時會提示出錯信息。如果你沒看清出錯信息,可以輸入”:cc“命令,vim會更次顯示此信息,或者乾脆使用”:cw“命令,打開一個quickfix窗口,把所有的出錯信息顯示出來,見下圖:

現在我們知道錯在哪兒了,修正一下,然後使用”:cn“命令(或者在Quickfix List對應行上輸入回車)跳到下一個出錯的地方,以此類推,直到修正全部錯誤。

好了,千辛萬苦,我們的hello world終於工作了。乍一看這個例子,似乎Quickfix並沒有提高什麼效率,但如果你的錯誤出現在多個不同目錄的不同文件裏,它可以幫你省很多時間,使你可以集中精力在修正bug上。

vim可以同時記住最新的10個錯誤列表,也就是說你最近10次使用”:make“命令編譯所遇到的錯誤都保存着,可以使用”:colder“和”:cnewer“命令,回到舊的錯誤列表,或者到更新的錯誤列表。

在quickfix模式裏經常用到的命令有:

:cc                顯示詳細錯誤信息 ( :help :cc )
:cp                跳到上一個錯誤 ( :help :cp )
:cn                跳到下一個錯誤 ( :help :cn )
:cl                列出所有錯誤 ( :help :cl )
:cw                如果有錯誤列表,則打開quickfix窗口 ( :help :cw )
:col               到前一箇舊的錯誤列表 ( :help :col )
:cnew              到後一個較新的錯誤列表 ( :help :cnew ) 

更多的命令,以及這些命令更詳細的解釋,請參見手冊。

對於經常用到的命令,最好提供更方便的使用方法,在我的vimrc中的定義:

autocmd FileType c,cpp  map <buffer> <leader><space> :w<cr>:make<cr>
nmap <leader>cn :cn<cr>
nmap <leader>cp :cp<cr>
nmap <leader>cw :cw 10<cr> 

現在使用”,<space>“(先按,再按空格)就可以編譯,使用”,cp“和”,cn“跳到上一個和下一個錯誤,使用”,cw“來打開一個quickfix窗口。這下順手多了!

如果你希望跳轉到出錯的文件時,使用一個分隔的窗口打開,請參閱’switchbuf‘選項的值。

在vim7中,每個窗口都可以擁有自己的位置列表,這樣,你就能夠同時打開多個位置列表了,而quickfix列表在整個vim中只有一個。你可以使用位置列表來顯示編譯錯誤信息,具體命令參閱手冊:”:help location-list“以及”:help :lmake“。

[GREP]

我們在程序員的利器 – cscope中講過,cscope可以做爲一個快速的grep程序使用,對於我們的軟件項目,用cscope生成一個數據庫,可以大大加快查找字符串的速度。但cscope需要事先生成一個數據庫,對一些簡單的查找,不需要專門爲之生成數據庫,這時候可以使用grep。

Grep的名字來源於”g/re/p”,”re”是正則表達式(regex)的意思,”p”是打印,也就是把匹配正則表達式的行打印出來。

vim既可以使用外部的grep程序,也可以使用內部集成的grep功能。

使用集成的grep命令非常簡單,通常使用格式爲:

:vimgrep /main/gj **/*.c 

在上面的例子裏,我們使用vim內部集成的grep功能,在當前目錄及其子目錄樹的所有c文件中查找main字符串,如果一行中main出現了多次,每個匹配都計入;在查找到後,不立即跳轉到第一個匹配的地方。

使用內部集成的grep功能速度要比外部grep慢一些,因爲它會打開每個文件,對其進行檢查,然後關閉;但集成的grep支持vim增強的正則表達式,可以利用它進行更爲複雜的查找。它也支持vim擴展的文件通配符表示方式,見”:help starstar-wildcard“。

vimgrep查找到的結果,也會放在quickfix列表中。下圖是在vim 7.0的源代碼目錄中執行上面的命令生成的quickfix列表:

我們可以使用上面介紹的quickfix模式的命令,來查看這些匹配。

你也可以用外部的grep程序來查找,如果你的系統中所用的不是標準的grep程序,那麼就需要修改’grepprg‘選項,詳情請參閱手冊。

使用外部grep的語法與grep程序相同,請參閱grep的手冊。

無論使用內部的vimgrep,還是使用外部的grep,vim都允許你將查找到的結果放在與窗口相關聯的位置列表,要了解詳細信息,”:help :lvimgrep“及”:help :lgrep“。

在我的vimrc中,定義下面的鍵映射,利用它可以在當前文件中快速查找光標下的單詞:

nmap <leader>lv :lv /<c-r>=expand("<cword>")<cr>/ %<cr>:lw<cr> 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章