關於補全的方面要說的的確很多, 這里選擇分為兩個章敘述. 如果你想學vim, 你需要有很強的耐心, 如果你想鍛煉這種耐心, 你可以試着先看完我之前的文章. 好了, 下面繼續我們的vim補全吧.
vim補全1中曾經提及到supertab在更換版本后和UltiSnips成功共用tab的解決方案, 在此之前主要的敘述主要在做一件事情:將vim的tags補全和字典補全從supertab的補全功能中分離出來, 讓supertab只負責一件事情:就近補全. 這樣子做似乎沒有必要, 因為我們完全可以將他們全部放到supertab接管的tab鍵上來, 下面要說的就是為什么我們需要這樣做.
從最初的敘述中不難看出的想要實現最快最智能的補全的需要實現的幾個功能:優秀的補全列表排列算法,可預見性的補全列表結果,高速的補全列表建立.優秀的補全算法這一點上其實vim也有比較好的插件, 從很早依賴與tags的Autocomplpop和omnicppcomplete到后來比較出名的neocomplcache,再到后來相當智能的YouCompleteMe,最后到我現在留下的clang_complete. 下面就一一看一下這些插件的特點.
首先是Autocomlpop和omnicppcomplete他們都是通過tags生成補全列表的,同時對tags的內容做過更加精確的分析可以實現諸如c++的一些類成員補全的高級功能. 不過由於tags文件本身的限制, 這種補全在實用性方面並不是太好. 他們都是比較早的vim補全插件.
后來出現的一個neocomplcache插件比較出名, 網絡上介紹他的文章很多. 主要的特點是通過在打開文件的時候一次性建立補全信息的緩存來提高補全速度. 這個插件我曾經使用過一段時間, 首先是打開文件的時候由於necocomplcache需要建立緩存, 如果文件比較大的話你將明顯感覺到卡頓. 現最新的neocomplcache 已經改名為neocomplete,新的neocomplete通過lua的支持解決了啟動時建立緩存的過慢的問題. 當然他也需要更加高版本的vim的支持. 緩存一旦建立完成就比較快了. 補全列表幾乎全部是瞬間彈出, 可是這么高的補全速度不見得是好事, 如果你設置了necomplcache的自動彈出功能. 你將發現,這個彈出功能在很多不需要彈出的地方依然工作, 由於彈出速度相當的快,很多時候你在快速的移動光標的時候他都可見縫插針的彈出補全, 這個么積極的補全最終讓我選擇了關閉他的自動補全. 在需要的時候通過按鍵觸發. 這個觸發鍵自然會被想到映射到tab鍵上, 網絡上的確有這樣做的實現方案. 很明顯neocomplete是不能和supertab共存的. 這問題並不是太過嚴重並且我曾經翻遍網絡后在一個外文網站上找到了讓neocomplcache和UltiSnips共存的方法. 可是最為嚴重的的問題是neocomplete和clang_complete沖突. 因為他們同時調用vim提高的全能補全函數接口. 調用同一個接口的結果是一個插件總是壓制另一個插件導致被壓制插件完全沒有觸發的能力.這種沖出似乎完全沒有辦法解決. 而clang_comlete又有很多我無法替代的優秀特性. 最終我還是選擇了放棄neocomplcache.
關於YouCompleteMe就更加奇葩了, 首先是他無法和clang_complete,supertab,neocmplcache共存. 其次是他需要clang3.3的支持, ubuntu目前默認支持比較完整的clang3.0,這包括clang3.0相關的libclang庫(這個庫可以加快clang_complete的速度) 不知道是不是由於clang沒到3.3的問題, 在我成功編譯安裝了YouCompleteMe之后clang支持的所有補全特性一個都沒有出來過. 官方文檔之說YouCompleteMe是支持UltiSnips的,在使用中我也發現補全列表中有UltiSnips觸發關鍵字的身影,可惜的是在選擇這個些觸發關鍵詞之后簡單的按enter鍵是無法展開UltiSnips的代碼補全塊的.百度后得出的解釋是這里需要設置UltiSnips的展開鍵映射到<tab>鍵之外的其他鍵上並在補全列表中選擇觸發關鍵字之后通過這個重新映射的展開鍵來展開.可惜, 我沒倒騰到這一步就已經把YouCompleteMe卸載了, 因為他的clang特性在我的ubuntu12.04中始終沒有成功過! 另外, 這個插件在編譯之后竟然達到了60M的大小!我其他vim配置加起來20M都不到, 真是佩服.,這么大的容量明顯在編譯YouCompleteMe的時候clang3.3是下載了的, 可是誰能告訴我, 為什么clang的特性一個都沒實現呢.
上面四個補全工具一一被淘汰之后, 最后剩下的唯一一個自動補全就是clang_complete了, 這是一個比較難控制的插件, 好在他和supertab以及UltiSnips並不沖突. 在ubuntu下使用clang_complete首先你需要下載clang編譯器和libclang庫. 下載命令如下:
sudo apt-get install clang libclang1 libclang-dev
安裝好clang編譯器環境之后clang_complete就可以正常工作了.clang_complete主要實現了兩個很重要的功能, 第一個是clang_complete可以動態的檢測代碼中語法錯誤, 這些語法錯誤是建立在clang編譯器時時編譯的結果的基礎上的,因此相當准確. 其實clang_complete通過分析clang時時編譯的結果實現比較高級的補全. 其中默認情況下clang_complete在". , ->和::"三個標識符后面自動觸發. 這個這些標識符在C和C++中代表這指針的間接訪問, 類對象成員變量和成員函數的調用等.這些地方的補全在簡單的關鍵字檢索方式很難實現精確的補全. clang_complete借助與calng編譯器時時編譯結果中的元素信息實現了這類補全的精確補全. 這個功能在補全C代碼中的結構體, C++中的類對象時變得超級實用.
clang_complete的配置選眾多, 網絡中有很多地方可以找到一些現成的配置.但這些配置大多是類似的, 我按照網絡上能找到的配置放在vimrc中以后發現vim變得不穩定. 首先是vim在某些情況下比較容易崩潰. 比如#include代碼的中出現錯誤時就容易直接閃退. 又比如在寫c代碼時經常會收到vim被致命信號ABRT中斷的問題. 很明顯這些不穩定是clang_complete在clang后台時時編譯代碼后動態解析編譯結果並將編譯錯誤顯示到vim的時候出現了無法解析的內容所致.這是一個嚴重的問題. 因為你不知道vim會什么時候崩潰, 崩潰后之前編寫后沒保存的代碼將會丟失, 又一個坑字了得! 好在一天實在受不了clang的隨時駕崩之后. 我開始查看clang的幫助文檔. 在幫助文檔的幫助下終於解決了這個問題.下面是關於calng_complete全局變量配置的一些意義和功能解說:
g:clang_complete-auto_select 該變量置1時,calng_complete在彈出補全列表之后會自動選擇第一個選項但不會生效, 置2時自動選擇首選項后同時將該項生效.
最初我將該變量設置為1, 后來發現這個選擇完全可以使用默認的0, 因為在彈出補全列表之后你可以通過tab實現相同的效果.
g:clang_complete_copen 該變量控制語法錯誤檢查后是否打開quickfix窗口列表. 默認值是0表示不打開. 如果你不想在編碼時時不時看到quickfix窗口的彈出, 這里保持默認設置即可.
g:clang_hl_errors 該變量控制是否高亮顯示clang檢測到的語法錯誤, 這個功能相當實用. 默認值是1表示打開, 如果你希望用到clang_complete的智能語法檢測功能.這里保持默認設置即可.
g:clang_periodic_quickfix 這個變量是上面崩潰問題的關鍵, 網絡上的配置為實現clang_complete對當前代碼的時時語法檢查, 這里大多將其設置成了1, 這個變量控制着是否定時刷新quickfix里的錯誤信息. 在該變量等於1時,只要我們的光標在vim中保持三秒不動, clang_complete就會在后台給我們刷新clang時時編譯出來的結果. 這個功能的本意是好的. 可是clang_complete在刷新quickfix的時候似乎對某些錯誤無法正確的解析, 這就導致了vim突然的退出和致命錯誤提示. 很明顯為了避免vim突然的退出導致的編輯內容丟失. 這里一定要保持默認設置.
g:clang_close_preview clang_complete在補全的時候默認是可以打開補全預覽的,所謂的補全預覽就是在vim的上面展開一個小的名為"草稿"窗口, 里面顯示的是當前補全列表中選擇內容的完整內容預覽, 這個功能並不實用, 因為補全列表中的內容已經相當詳細了, 突然打開的草稿窗口只會給編輯帶來不順暢感.因此這里建議將其設置為1來關閉預覽功能.
g:clang_snippets_engine clang_complete的補全帶有一定的snippets功能, 所謂的snippets功能就是當補全內容是一個函數的時候clang_complete在補全確認后會首先定位到函數的第一個參數區並讓用戶修改, 修改完畢之后你可以通過回到普通模式(我這里通過`鍵返回普通模式)后使用tab鍵跳轉到下一個變量區繼續修改.clang_complete的說明文檔中似乎表示支持Ultisnips的snippets功能, 也就是如果我們安裝了UltiSnips並在這里將clang_snippets_engine設置成UltiSnips我就可以通<<vim之補全1>>中提及的ii和II來跳轉可修改區. 可惜的是我嘗試過這里設置成UltiSnips結果是snippets功能紊亂. 最后還是保持了默認的普通模式tab鍵跳轉的方式. 好在這個方式還是相當方便的.
g:clang_snippets 這個變量似乎是用於開啟clang_complete的snippets功能的, 而clang_complete的這個選擇默認值是0,因此這里可以設置成1
g:clang_use_library 這個變量用於開啟通過libclang庫來加快clang_complete的反應速度. ubuntu在安裝了libclang1 和 libclang-dev庫之后就可使用libclang庫了. 所以這里明顯是需要打開的.
g:clang_user_options 這一項用於對編譯器的一些設置, C語言編輯下這里不需要設置, C++開發時可以在其中添加必要的參數.
g:clang_complete_macros 似乎是用來補全宏什么的, 暫時不太清楚到底有啥作用, 將其設置為1暫時沒有發現問題.
綜合上面的描述, 最終我們的對clang_complete的配置可以歸結為一下幾句話, 將其寫到vimrc中即可:
"clang_complete插件設置
let g:clang_snippets=1
let g:clang_use_library=1
let g:clang_close_preview=1
let g:clang_complete_macros=1
"let g:clang_user_options='-stdlib=libc++ -std=c++11 -IIncludePath'
上面的設置我們關閉了quickfix的定時更新功能. 這是為了防止vim意外崩潰而做的設置, 可是這也將導致clang_complete無法自動時時的顯示語法錯誤了. 是否clang_complete提供給我們的強悍的語法檢查功能就無法使用了呢? 非也, 幫助文檔中提到我們可以通過手動調用函數的方式來觸發quickfix的更新.也就是說任何說后我們希望看到clang時時編譯之后的語法錯誤提示, 我們只有手動調用這個函數即可. 當然,每次看個語法錯誤提示還要手動調用個函數當前不是我的風格. 通過將這個函數的調用捆綁在快捷鍵上是我慣用的伎倆, 可是捆綁在那個快捷鍵上好呢? 我的設計是和共用保存快捷鍵. 這樣的共用設計實現了任何時候刷新quickfix內容之前文件總是被保存過了, 首先是這樣的手動更新vim崩潰的可能性變得很小, 其次即便崩潰了,也沒關系, 因為我們剛剛保存過! 在我的vimrc中保存用的快捷被映射到了alt+w上因此我們只要添加下面的配置就可以實現保存和clang_complete語法檢測共用alt+w組合的效果(為了防止在普通文件保存時觸發ClangUpdateQuickFix函數而出現錯誤提示,這里配置成只在c和cpp類型的文件中觸發該函數調用):
imap ^[w <esc>:call Smart_save()<cr>a
imap <a-w> <esc>:call Smart_save()<cr>a
nmap ^[w <esc>:call Smart_save()<cr>
nmap <a-w> <esc>:call Smart_save()<cr>
func! Smart_save()
exec "w"
if &filetype == 'c' || &filetype == 'cpp'
call g:ClangUpdateQuickFix()
endif
endfunc
注意其中的^[w 是通過在插入模式下先按下ctrl+v再按下alt+w產生的特殊字符,這種方式輸入的alt+w是ubuntu的gnome-terminal終端唯一能識別的alt組合鍵的配置方法, 關於alt鍵的映射問題可以通過 :help map-alt-keys 和 :help map 以及 :help alt 來獲得相關幫助.
和clang_complete相關的配置還有一個是
set completeopt=menu,longest 這是一個相當有效的設置. 這在后面的字典補全的地方會有說明,這里暫時就不做解釋了.
最后要提及和calng_complete的相關的設置是項目根目錄下.clang_complete文件. 這個文件是我們手動建立的. 假設你當前編輯的項目源碼中包含了一個自己定義的頭文件,而這個頭文件並不再當前源文件所在的文件夾中而是在項目根目錄的子目錄include下面, 很明顯,如果不告訴clang這個我們自己的頭文件的位置所在, clang在時時編譯我們的當前的源文件的時候將總是提示我們的頭文件找不到. 為了解決這個類問題, 我們需要配置項目根目錄的.clang_complete文件. 這個文件中可以設置所有和編譯器相關的參數. 示例如下:
-w
-I include
-I lib/ipc
-I lib/unix
-I lib/net
-w 表示不對編譯時的warning報錯和高亮, 如果你希望代碼更加嚴重, 最好不要在這里加入-w, 如果你不想消除代碼中的worning有不想每次查看語法錯誤的時候都看到這些worning被高亮, 那么可以在這里添加-w
-I 后面跟的是目錄名表示告訴編譯器到那里去找到我們自己定義的頭文件.
clang_complete補全對應着優秀的補全必要特性中的高級算法. 另一個必要特性是可遇見性的補全結果.這個特性主要是為了提高補全的命中率和盲補的可能性. 在VAX中由於算法比較復雜, 補全的可預見性也被算法接管, 但vim中就不是這樣了, 因為vim沒有這么智能. 雖然和其他的IDE相比vim在補全的智能程度上的確有所不及.但是真所謂笨鳥先飛, 傻人有傻福.(^_^). vim的作者在設計vim的時候很明顯也意識到了這一點, 既然程序本身不能做到高度的智能, 那么我們就需要將一部分需要智能區分的工作交給用戶, 要知道人永遠要比計算機更加的智能. vim為此設計了多達15種補全模式, 為的就是將不同場景中的補全分開並且將觸發各種補全的時機交給用戶, 也就是希望用戶可以智能的先過濾到一部分完全不必要的補全來達到提高補全精度的目的. 這十種補全中我們需要關注的只有幾個, 下面要說的就是最后要上場的四個vim自帶的補全配置, 這些補全在<<vim之補全1>>中最開始就提到過. 首先要說的是tags補全, 由於tags補全對項目中不在上下文和buffer中的關鍵字補全行之有效並且tags補全大多時候是可以預測的(可預測指到在我們知道什么時候時候后需要觸發的tags補全). 因此, 我們有必要將其保留, tags補全分析到這里最后需要考慮的就是怎么能更加簡單的調用它. vim大多數捕全面是通過ctrl+x加上另一組ctrl組合鍵觸發, 沒調用一次補全需要按四個鍵, 很明顯這是不合適的. 為此,我們需要想出更好的調用方式. 不過, 在思考這個問題之前我們需要解決另一個更加棘手的問題: 不知道是不是插件沖突的問題, 在我根據上面的表述將supertab和UltiSnips成功的共存之后, 出現了一個嚴重的問題: 在插入模式下輸入ctrl+x組合鍵的時候, vim會自動輸入下面的字段:
=<SNR>53_ManualCompletionEnter(
)
很明顯這是某個地方映射了ctrl+x鍵並且沒有正確執行的結果. 定位的我們安裝的supertab.vim文件中, 搜索<c-x>, 很快728行(你可能不在這一行).找到了如下代碼:
imap <c-x> <c-r>=<SID>ManualCompletionEnter()<cr>
在這一行的開頭添加"將其注釋掉, 清除所有.vim/view目下的所有記錄, 打開文件重新輸入<ctrl+x><ctrl+]>, tags補全成功被調出.
supertab的映射問題解決之后我們可以繼續考慮上面的需求. 我們需要盡量用最少和最容易操作的按鍵來觸發補全的調用.補全的觸發鍵首先是ctrl和alt組合鍵不能用, 因為在我的<<vim之快速跳轉>>中有提及,ctrl的組合鍵首先是有一部分被vim默認占用后不可重新映射, 另有一部分如組合鍵直接不能實現映射. 其他能用的ctrl組合鍵大多用於實現vim的跳轉和定位. alt組合鍵在操作上並不流暢,比較適合做操作並不頻繁的各種功能映射. 其次, 補全的觸發鍵必須在插入模式直接觸發, 這樣
又導致這里的映射不能像普通模式那樣通過單鍵來實現.
ctrl,alt,單鍵都不能做映射, 難道補全就不能實現更好的重映射了嗎? 非也, 之前提過vim有一個神奇的雙鍵映射功能. 由於vim有一個按鍵等待模式, 因此即便的實在插入模式下雙鍵映射依然可以很好的工作, 比如我們的在插入模式下用jj做映射,任何時候我們在插入模式下快速的輸入jj鍵都可以觸發這個映射. 你可能會問題, 這樣一來我不是不能輸入連續的兩個jj了嗎?非也, vim對所有的用戶輸入如果在功能上無法是未決的, 那么vim會進入輸入等待模式,這個等待時間默認是1秒, 在你輸入一個字符后的1妙內,vim會等待你輸入第二個字符來確定輸入的功能. 如果在這一秒內你沒有輸入第二個字符來觸發某個映射.那么vim就會認為你是希望單純的輸入第一個字符. 因此在1秒后你的字符會轉換為正常的字符並上屏.這樣一來, 如果我們對jj做了映射, 我們有希望輸入兩個連續的jj的話就很容易實現了, 我們只要在輸入第一個j之后等待大約1妙再輸入下一個j就可以了.如果你不了vim多字符映射功能, 那么你很可能會為在某天你從別人那借鑒了某些設置之后發現自己vim的輸入變得莫名奇妙的卡頓了.實際上這種卡頓在大多數情況下是不會影響我們正常編輯的, 只要我們編輯的的內容沒有和雙字映射重疊, 我們大可不必理會這樣的停頓, 你的編碼速度有多快就寫多快吧.放心, vim會跟上你的編輯速度的. 當然這里在做雙鍵映射的時候也不能做任意的組合, 某些在你編碼或編輯中出現頻率很高度組合是不適合做雙字映射的.比如方便又按的"ll"就不適合編程的人用來做映射."ll"在很多很常用的的單詞中出現(malloc是最多的一個),因此如果你用他來的做映射,那么你不得不在每次輸入malloc的都時候都要停頓一次,並且這種停頓往往被我們一氣呵成的打出一個malloc所誤傷! 第二個雙字映射需要注意的是要盡量使用那些盡量容易操作的組合, "jj"組合要遠比"pp"組合好按的多. 最后一個需要注意的時候最好只用幾個特定的按鍵來產生各種不同的組合來的映射.因為只要一個按鍵在你的vim配置中有一個相關開頭的映射, 我們在任何時候輸入這個按鍵都會看到卡頓現象. 如果你把鍵盤上的26個字母和其他字符全用雙字映射了一遍, 那么每個按鍵在任何時候按下的時候都會被卡頓. 我想應該不會有人會喜歡中樣的輸入體驗的.綜合上面的敘述, 我的雙字映射中大多用到了"jkl"和"JKL"這六個字符做組合映射. 這里我挑選了相當好按鍵的"kk"來做為tags補全的觸發映射.
你可能會說"jj"鍵比"kk"鍵更加易於操作, 為什么不用它來做為tags補全的映射呢? 答案是我們還有一個比tags補全使用更加頻繁有效的補全方式, 那就是字典補全! 這個補全在vim中的默認觸發鍵是<ctrl+x><ctrl+k>, 在我之前敘述中多次提到過字典補全, 可見他的功效之高, 首先說明字典補全的原理:我們在一個任意名字的文件中用空格做為關鍵詞寫下多個詞組, 這些詞組是我們希望用於補全的詞組. 在.vimrc通過下面的方式告訴vim我們的字典在哪里:
set dictionary+=~/.vim/tab/C.dic
我將所有的個人補全字典全部放在了~/.vim/tab目錄下, 出了用於c語言補全的C.dic還有針對c++的cpp.dic和針對於網絡編程開發net.dic等等, 這些字典完事是我們自己設計的因此字典的名稱,字典內容以及字典的分類方式完全取決於我們個人. 如果我們用c語言的同時還需要使用網絡方面的開發接口, 這里可以在vimrc繼續添加如下內容:
set dictionary+=~/.vim/tab/net.dic
字典在路徑指定給vim之后插入模式下任何時候我們通過<ctrl+x><ctrl+k>觸發字典補全,vim都會按照vimrc中添加的順序來檢索所有存在的字典文件. 單個文件中vim的檢索順序是從文件頭順序到文件尾.
字典補全的原理是很簡單的, 第一次看到你可能會覺得字典補全沒有什么特別,也沒什么強大的地方. 不過下面對字典補全優點的分析可能會讓你改變這個看法.首先, 字典補全的字典是我們自己設計的, 這將給予我們的是最為靈活的補全列表定制功能. 使用vim的人大多是程序員, 而程序員使用的語言有很多, 也許你和我一樣是一個普通的c語言的使用者. 也可能你是一個php工程師或着使用python做開發. 無論你是用什么語言, 字典補全總是可用的. 因為你php的工程師完全可以自己定制一個php.dic供自己使用.其次字典補全可以讓步補全的精度提到非常高的一個高度. 現在假設你和我一樣都是C語言程序員, 但我的開發主要是做網絡信息采集和處理, 而你的開發是用c語言來寫驅動程序.這么一來即便我們用的是完全相同的語言, 我的C.dic也可能和你的c字典大不相同, 因為我可能永遠不會用到驅動程序里的接口函數, 你也可能完全不管任何應用開發使用的函數.補全字典可以做到補全列表的高度定制化, 任何你用不到的關鍵詞都可以被你排除在外, 等到哪天你需要用到它時, 再添加和修改字典補全也是很容易的. 這種完全按需求的定制字典可以保證補全列表中基本沒有冗余的內容. 第三個補全字典的優點是便於切換,這在之前已經提到, 我們完全可以定制補全種類的字典的在不同場合單獨或組合使用. 字典補全的第四個優點是補全的結果是可預測的. 這個特性相當的實用, 因為它可以讓字典補全實現盲補(我自己發明的詞, 在<<vim之補全1>>中有提及). 盲補就像盲打一樣是所有補全中最快的一個, vim在檢索補全字典中的內容時總是按照從頭到尾的順序掃描並排列結果的. 一來只要字典中的關鍵詞順序沒有變. 補全出來的結果也不會變, 二來我們任何時候都可以通過修改補全字典中關鍵字的內容和順序來讓補全列表的結果變得更加合理高效.字典補全最適合用於各種編程語言或普通編輯中那些不變的語法關鍵詞, 這些語法類的關鍵詞首先是固定不變的, 其次是高頻率的出現. 比如C語言中語法關鍵子struct這個關鍵詞出現的頻率相當的高, 如果我們使用就近補全或者是tags補全等其他方式的話, 補全列表的結果會因上下文內容的變化而產生化, 這樣我們不得不在每次的觸發中下意識的去查找.而字典補全則完全不同, 如果你吧sturct在C.dic中放置在非常靠前的地方, 那么你將能夠確定每次通過s觸發字典補全的時候首選詞總是struct, 這樣就實現了盲補的特點. 字典補全的最后一個優點是對一些有規律的很長的帶有體系特點並且往往很長的接口函數和接口關鍵詞的的補補全行之有效.下面是我的C.dic中關於linux線程的字典記錄:
pthread_t
pthread_create() pthread_exit()
pthread_keycreate() pthread_keydelete()
pthread_join() pthread_self()
pthread_setpecific() pthread_getspecific()
pthread_cleanup_push() pthread_cancel()
pthread_detach() pthread_equal()
pthread_attr_t
pthread_attr_default() pthread_attr_init()
pthread_attr_getschedparam() pthread_attr_setcheparam()
pthread_attr_setscope() pthread_attr_setdetachstate()
PTHREAD_
PTHREAD_CANCELED
PTHREAD_PROCESS_
PTHREAD_PROCESS_PRIVATE PTHREAD_PROCESS_SHARED
PTHREAD_SCOPE_
PTHREAD_SCOPE_SYSTEM PTHREAD_SCOPE_PROSESS
PTHREAD_CREATE_
PTHREAD_CREATE_DETACHED PTHREAD_CREATE_JOINABLE
cond_attr
pthread_cond_
pthread_cond_init() pthread_cond_destroy()
pthread_cond_broadcast() pthread_cond_singal()
pthread_cond_timewait() pthread_cond_wait()
pthread_delay_t
pthread_delay_np()
pthread_mutex_t
pthread_mutex_init() pthread_mutex_destroy()
pthread_mutex_lock() pthread_mutex_unlock()
pthread_mutex_mutex() pthread_mutex_trylock()
pthread_mutexattr_setptype() pthread_mutexattr_setpshared()
pthread_mutexattr_init() pthread_mutexattr_destroy()
PTHREAD_MUTEX_
PTHREAD_MUTEX_NORMAL PTHREAD_MUTEX_ERRORCHECK
PTHREAD_MUTEX_RECURSIVE PTHREAD_MUTEX_DEFAULT
PTHREAD_MUTEX_INITIALIZER
sched_param {
sched_priority
}
sched_
pthread_once_t
PTHREAD_ONCE_INIT
這個不怎完善的線程接口字典有很多規律性的特點 他們大多以pthread_和PTHREAD_開頭后面往往還有一些子字段,它們中大多數比較長而顯得不那么友好, 如果你總是一個一個去打的話,即便利用就近補全只打首次, 你也會覺得很麻煩. 這里利用字典補全當我們利用字典補全在任何時候通過pth觸發, 出現在補全列表首的將會是pthread_這個開頭總會是正確的, 我們在他的后面再加上一些子字段的關鍵字繼續補全就會將補全精確定位到我們需要的結果上.這個補全相當的好用.
你可能會覺得制作這個補全字典比較麻煩, 首先是你可以在感覺到某個高頻詞需要加入字典的時候將其添加進來. 你也可以在看相關書籍的時候作為一種總結性的筆記邊看邊把他們加入到字典. 這種方法比較系統, 也可以幫助我們學習. 總之, 這些字典是日月累起來的分散到零散的工作時間中去之后, 你會發現制作他們基本上沒有額外的時間開銷.
在我的vimrc中利用"jj"這個雙字映射中算是最容易操作的映射來觸發字典補全, 另外還設置了"JJ"來觸發路徑補全. "JK"來觸發頭文件補全(在<<vim之快算跳轉>>中曾經把"jj"和"kk"用於上下移動, 這里更新為補全觸發. 由於在編碼中從成對的標點最后右移跳出標點的操作相當的頻繁,因此保留了"jk"右移和"kj"左移的功能). 綜上所述, 下面給我的vimrc相關映射配置片段:
imap kj <left>
imap jk <right>
imap jj <c-x><c-k>
imap kk <c-x><c-]>
imap JJ <c-x><c-f>
imap JK <c-x><c-i>
vim補全相關的內容最后還有一個小小問題需要討論一下, 這個問題是vimrc中completeopt的設置帶來的. 首先是completeopt用於控制補全列表的顯示方式, 主要是三個, menu方式表示展開補全列表, longset方式表示在補全列表中存在公共的最長字串時將其直接上屏, preview表示打開預覽窗口. 第一個menu一般是必選的, 第三個preview因為沒有多少苦實質的用處,使用后反而會在的補全不時的給你在窗口上方彈出個"草稿"窗口而打亂了我們輸入節奏, 因此建議不要使用. 問題出在第二個longest上面, 這是一個比較糾結的補全顯示方式, 他的優點是,如果你輸入向上面擁有公共字串的pthred_類型的補全時, longset開啟之后pthread_會在
你觸發補全時就上屏, 並且由於這時沒有選擇任何一個補全列表中選項, 因此當我們繼續輸入之后子字段時補全列表會很自然的更新到更加精確的補全列表上來. 如果longset關閉, 那么觸發后會默認選擇第一個選項, 如果上面的列表中第一個詞pthread_t修改為pthread_ 那么會在出現pthread_之后很自然的繼續輸入mu等來繼續精確選擇諸如pthread_mutix_init的選擇可是問題出在繼續輸入mu等子字段后補全列表會自動關閉, 我們必須通過再次使用"jj"來重新彈出補全列表. 這個樣每個具有子字段的補全必須使用至少四個j才輸入完畢. 這在輸入上完全沒有longest開啟時那么自然. 可是如果真的設置longest方式, 如果我們輸入諸如struct這樣
完全沒有公共字符串的單詞時又會變得麻煩, 因為他不會默認給你選擇補全列表中的第一個選項. 這在輸入時又變得的不那么自然了, 這么一折騰longest變得相當蛋疼. 開也不是, 關也不是. 這個問題我酷似冥想了好幾天無果...之后只想出了一個可以稍微方便一點的辦法就是將上面字典中ptheard_這樣的公共字串寫成pthread_t這樣的多一個單詞的關鍵詞並且關閉longest, 這樣一來在輸入pth觸發字典補全之后會選中第一選項pthread_t, 如果我們想輸入phread_mutix_init就先刪除一個單詞t, 這個時候補全列表上不會選擇任何一個選項, 之后當我們再輸入mu時補全列表是不會關閉的, 我們就可以省去一次"jj"的觸發輸入. 當然, 這種輸入只能稍微的讓補全變得更加平滑一點, 並不是解決的根本辦法. 如果那位讀者有更好的解決辦法希望可以給予回復或發郵件告訴我, 個人將不甚感激.
我的郵箱如下:pangchol@163.com
好了, vim補全相關的內容我暫時就研究到這里, 終於寫完了, 最后來做一個總結:
我們擁有自己的補全字典, 在寫項目代碼時首先在vimrc指定正確的補全字典. 將前輩的代碼和自己的函數庫等加入自己的項目中. 利用f12鍵隨時建立或更新tags和cscope. 我們需要最學會UltiSnips的代碼塊補全定制方式, 在必要的時候修改~/.vim/vunder/UltiSnips/UltiSnips目錄下相關的代碼塊補全模板來定制符合項目和個人需求的代碼塊補全. 我們需要認真定制和記憶這些代碼塊補全的觸發關鍵詞, 在任何時候都可以通過輸入這些觸發關鍵詞后輸入Tab鍵來觸發代碼塊補全功能. 任何時候如果需要補全一個上下文或其他打開的緩沖區中出現過的單詞, 我們都可以通過Tab鍵觸發就近補全(只要注意不要輸入了和代碼塊補全觸發關鍵詞相同的內容來觸發即可). 這個單詞在上下文中離光標越近越容易實現盲補.如果一個函數或者變量名等存在於前輩的代碼或者函數庫中, 我們可以通過"kk"鍵來觸發tags補全來比較精確的找到他們. 任何時候如果你想輸入語法中的關鍵字或者編程語言中的標准庫接口等都可以通過"jj"來觸發字典補全(已經定制好的)高速而精確的實現,標准接口函數名往往在第一次使用時通過字典補全觸發,之后大多使用就近補全更加快速高效. 而數量不多詞組簡單但又出現頻率極高的語法關鍵字(諸如: struct static等)我們最好總是采用字典補全, 認真設計你補全字典盡量保證越高頻的語法關鍵在字典補全的越前面. 你將發現發多時候你輸入他們都是在盲補!如果你需要輸入系統中的路徑你可以試着使用"JJ"觸發路徑補全. 如果你確定一個關鍵子存在於當前文件包含的某個頭文件中, 你也可以試着通過"JK"來觸發頭文件補全. 最后, 任何時候clang可以支持時時編譯的編程語言中(C,C++,object-c等), 在我們輸入".","->","::"后clang_complete會自動通過clang的編譯分析來得到補全精度相當高的結構體成員或類成員的補全.如果我們希望查看一下當前編輯的程序有沒有語法錯誤,你也使用alt+w來保存后自定觸發clang_complete的語法錯誤分析和高亮功能,clang_complete的語法錯誤高亮功能只在類型為c或cpp的文件中被觸發.
后記:
2013-1214
最近幾天在使用vim跳轉的時候發現ctrl+]的跳轉有些詭異, 很多時候都不會跳轉的關鍵字的定義上. ctrl+]在默認情況下被用作ctags三跳轉. 通過:h CTRL+]查看相關的幫助文檔才知道ctrl+鼠標左鍵和ctrl+]的功能相同ctrl+鼠標右鍵和ctrl+t的功能相同(哎, vim到底還有多少好東西我還沒有知道呢?), 這時再測試ctrl+左鍵的跳轉, 詭異的現象出現了, ctrl+左鍵竟然和ctrl+]的跳轉結果不相同! 我來個去, vim幫助文檔寫錯了?? 仔細想了想幫助文檔應該不會有錯, 這樣可能的問題應該是ctrl+]被某個插件替換了. 想想自己的所有插件中可以實現跳轉的功能的除了cscope就是剩下clang_complete了, cscope之前沒有問題, 所以目標首先鎖定在clang_complete上, 通過:h clang_complete查看它的幫助文檔后原因就找到了, clang_complete默認將ctrl+]和ctrl+t作為跳轉到聲明的快捷映射了. ctrl+]本來的功能是跳轉到定義! 原因找到之后就很容易解決了, 在vimrc添加如果內容將clang_complete的跳轉映射修改到不用的鍵位上(鍵盤上的映射組合都快用完了, 想再找一個好用的快捷鍵不容易啊, 最后只能用ctrl+P和ctrl+T了):
let g:clang_jumpto_back_key="<C-T>"
let g:clang_jumpto_declaration_key="<C-P>"
這樣映射之后, ctrl+]將保持原有的通過tags跳轉到定義位置的功能. 如果cscope存在的情況下,vim的ctrl+]默認會先搜索cscope中的數據庫.在定義跳轉上tags的跳轉要比cscope准確一點(tags幾乎用作定義跳轉). 為了上vim的ctrl+]默認先搜索tags文件. 我們需要在vimrc添加如下配置:
set nocst
我們可以在vimrc添加專門用於cscope的定義跳轉映射以便在ctrl+]跳轉失敗的情況下使用cscope試試.關於這方面的討論, 更具體的內容可以在我的<<vim之tags>>中找到.
如果鼠標就在身邊, 其實ctrl+鼠標左鍵和ctrl+鼠標右鍵的組合要比ctrl+]和ctrl+t更加方便一點.
如果你真的需要跳轉的一個關鍵字聲明的地方可以通ctrl+P(注意是大寫的P)來實現. ctrl+t 和ctrl+T都可以實現遞歸的跳回到之前位置的功能.
在這次ctrl+]功能修正的過程中還發現了一個坑爹的問題, 很久之前我就發現vim中有些快捷鍵組合是絕對不能用來做映射, 如果用了后果就是vim徹底凌亂. 這樣的組合鍵典型例子有: ctrl+[, alt+[, alt+] . 一直以來知道的他們不能使用, 但具體原因並不明了. 今天在配置ctrl+]的時候意外的留意到vim如果直接輸入ctrl+[ 輸入提示中出現的^[符號, 而這個^[符號是特殊的組合鍵的轉譯起始字符並且<esc>鍵也被vim當作^[來處理. 同時alt鍵的組合鍵由於在gnome-terminal中會轉譯成<esc>開頭的特殊組合鍵,因此又會用^[來代替, 我來個去, 這么多的鍵位重合, vim不凌亂才怪哦...
2013-1216
這幾天使用vim發現即便通過alt+w來在保存之后調用ClangUpdateQuickFix()函數來手動觸發語法錯誤檢測. vim還是出現頻繁崩潰的問題. 實在受不了了只能再次求助百度谷歌. 在網上海搜了一翻之后在clang_complete作者的github上找到了一些相關的問題討論. 不過可惜的是沒有找到具體的解決方法. 仔細觀察討論的內容發現似乎最新的clang_complete修復了不少容易崩潰的問題. 在看看自己vimrc中vunder對clang_complete的下載源設置:
Bunder 'vim-scripts/clang_complete'
vim-scripts在github上是一個專門存放vim.org下插件拷貝鏡像的地方, 也就是指我當前的clang_complete是發布在vim.org上的最后的一個版本. 仔細看看clang_complete作者的github發現在Rip-Rip/clang_complete目錄下,也就是指這里的版本可能要比vim.org上最新的版本要新. 於是將上面的源配置修改為:
Bundle 'Rip-Rip/clang_complete'
重新清理和更新了clang_complete之后崩潰的問題暫時還沒有遇到了, 希望的真的是版本的問題吧.
最后在作者git的討論中似乎還看到如果開啟libclang功能會導致崩潰的可能增加. 因此將 let g:clang_use_library=1 這句刪除來關閉libclang的使用可能會好一點, 我暫時沒有關閉, 先用着觀察一段時間吧.
2014-0105
經過較長時間的測試這里得出的最新結論是clang_complete的語法錯誤高亮功能的確非常容易導致vim的突然崩潰, 最近終於絕對將這個功能徹底從vim的常用功能中剔除, 保持他的默認關閉,並且分配一個不適很好用的快捷鍵給它. 現在想想其實代碼的語法錯誤檢查功能並不是一個非常必要的功能, 因為在編碼的過程中語法錯誤幾乎是無法避免的, 編碼時不關注這些臨時的語法錯誤其實不會降低編碼效率. 現在vimrc中和clang_compelte相關的設置如果如下(關閉的libclang支持和自動語法檢測):
"clang_complete
let g:clang_snippets=1
let g:clang_close_preview=1
let g:clang_complete_macros=1
"避免和ctrl+],ctrl+t原有的功能沖突
let g:clang_jumpto_back_key="<a-t>"
let g:clang_jumpto_declaration_key="<a-d>"
ino <a-s> <esc>:call Show_error()<cr>a
nno <a-s> <esc>:call Show_error()<cr>
func! Show_error()
wall
if &filetype == 'c' || &filetype == 'cpp'
call g:ClangUpdateQuickFix()
endif
endfunc