Vim激荡30年发展史
作者 |?Joe Nelson
譯者 | 彎月,編輯?| 屠敏
來(lái)源 | CSDN(ID:CSDNnews)
導(dǎo)語(yǔ):眾所周知,Vim 是從 vi 發(fā)展出來(lái)的一個(gè)文本編輯器。其擁有代碼補(bǔ)全、編譯及錯(cuò)誤跳轉(zhuǎn)等豐富的功能特性,在程序員群體中廣受歡迎。
本文是作者?Joe Nelson?從頭到尾閱讀 Vim 用戶手冊(cè)以及追溯歷史之后的一些心得。希望這些筆記能夠幫助大家發(fā)現(xiàn)這款編輯器的核心功能,從而更加熟練地使用各個(gè)插件。
如果你想進(jìn)一步了解Vim,那么我建議你入手一本紙質(zhì)的用戶手冊(cè)和優(yōu)秀的袖珍參考手冊(cè)。我沒(méi)有找到官方的Vim紙質(zhì)手冊(cè),最后只好打印了這個(gè)PDF(https://begriffs.com/pdf/vim-user-manual.pdf)。為了方便查看Vim的命令列表,我建議你入手上圖中的《vi and Vim Editors Pocket Reference》。
歷史
Vi的誕生
Vi源自QED編輯器,距今已有五十多年的歷史。其發(fā)展歷程如下:
1966年:伯克利分時(shí)系統(tǒng)的QED(“Quick EDitor”)
1969年7月:登月(僅供參考)
1969年8月:QED -> AT&T的ed
1976年2月:ed ->瑪麗王后大學(xué)的em(“Editor for Mortals”)
1976年:em -> 加州大學(xué)伯克利分校的ex (“EXtended”)
1977年10月:ex有了可視化模式,vi
閱讀一下用戶手冊(cè),你就會(huì)發(fā)現(xiàn)QED和ex之間有很多相似之處。這兩個(gè)編輯器在指定和操作行范圍時(shí)都采用了類似的語(yǔ)法。
QED、ed和em這類的編輯器都是為硬拷貝終端設(shè)計(jì)的,這些終端基本上就是帶調(diào)制解調(diào)器的電動(dòng)打字機(jī)。硬拷貝終端可以將系統(tǒng)輸出打印到紙上。顯然一旦打印完成,就無(wú)法更改輸出,因此這種編輯過(guò)程需要包含用于更新和手動(dòng)打印文本范圍的命令。
到1976年的時(shí)候,ADM-3A等視頻可視化終端出現(xiàn)了。Ex編輯器添加了一個(gè)“開放模式”,允許在可視化終端上進(jìn)行行內(nèi)編輯,還有一個(gè)可視化模式,可以在支持光標(biāo)的終端上面利用屏幕進(jìn)行編輯。這種可視模式(可以通過(guò)命令“vi”激活)可以在屏幕上顯示部分文件的最新視圖,同時(shí)還保留了屏幕底部的ex命令行。(趣事:在ADM-3A上,h、j、k、l鍵兼作方向鍵,所以vi選擇這幾個(gè)鍵作為光標(biāo)移動(dòng)只是為了保持一致而已。)
如果你想了解更多關(guān)于從ed到ex / vi的發(fā)展,可以閱讀Bill Joy的這段采訪(https://begriffs.com/pdf/unix-review-bill-joy.pdf),他在文中談到了ex / vi的創(chuàng)建過(guò)程,以及一些令他失望的事情。
傳統(tǒng)的vi實(shí)際上只是ex的另一種形式,它們的可執(zhí)行文件是同一個(gè),根據(jù)調(diào)用時(shí)的可執(zhí)行文件名來(lái)決定啟動(dòng)ex模式還是vi模式。ex / vi對(duì)之前的版本進(jìn)行了改進(jìn),只需很少的系統(tǒng)資源,就可以在有限的帶寬下操作。而且該工具還支持于大多數(shù)系統(tǒng),完全符合POSIX標(biāo)準(zhǔn)。
從vi到vim
作為ed的衍生物,ex / vi編輯器的版權(quán)屬于AT&T。如果想在Unix以外的平臺(tái)上使用vi,就必須重新編寫不使用任何原始代碼的克隆版本。
克隆版本有很多,下面列出了一部分:
nvi:1980年,4BSD版
calvin:1987年,DOS版
vile:1990年,DOS版
stevie:1987年,Atari ST版
elvis:1990年,Minix和386BSD版
vim:1991年,Amiga版
viper:1995年,Emacs版
elwin:1995年,Windows版
lemmy:2002年,Windows版
下面,我們來(lái)重點(diǎn)看一看中間的vim。Bram Moolenaar希望在Amiga上使用vi。于是,他從Atari移植了Stevie,并對(duì)其進(jìn)行了改進(jìn)。他給自己的這一版起名為“Vi IMitation”。有關(guān)完整的第一手資料,請(qǐng)參閱自由軟件雜志對(duì)Bram的采訪(https://begriffs.com/pdf/vim-interview.pdf)。
在版本1.22中,Vim被重新命名為“Vi IMproved”,它完全實(shí)現(xiàn)并且超越了vi的功能。以下是主流版本及其重要功能的發(fā)展歷程:
1991年11月2日,Vim 1.14:首次發(fā)布(Fred Fish disk #591)。
1992年,Vim 1.22:移植到Unix。Vim開始與Vi并駕齊驅(qū)。
1994年8月12日,Vim 3.0:支持多個(gè)緩沖區(qū)和窗口。
1996年5月29日,Vim 4.0:圖形用戶界面(主要由Robert Webb提供)。
1998年2月19日,Vim 5.0:語(yǔ)法著色/高亮顯示。
2001年9月26日,Vim 6.0:折疊,插件,垂直分割。
2006年5月8日,Vim 7.0:拼寫檢查,自動(dòng)補(bǔ)齊,撤消分支,標(biāo)簽。
2016年9月12日,Vim 8.0:作業(yè),異步I / O,本機(jī)包。
有關(guān)各個(gè)版本的詳細(xì)信息,請(qǐng)查看:help vim8。如果想了解未來(lái)的計(jì)劃,以及已知的bug,請(qǐng)查看:help todo.txt。
受到來(lái)自競(jìng)爭(zhēng)對(duì)手NeoVim的壓力,Vim 8.0加入了異步作業(yè)的支持,NeoVim的開發(fā)人員希望在編輯器中直接運(yùn)行Web腳本的調(diào)試器和REPL。
Vim超級(jí)便攜。在漫長(zhǎng)的發(fā)展過(guò)程中,為了支持多種平臺(tái),vim本身不得不保持便攜。它可以在各種平臺(tái)上運(yùn)行,包括OS / 390、Amiga、BeOS和BeBox、Macintosh classic、Atari MiNT、MS-DOS、OS / 2、QNX、RISC-OS、BSD、Linux、OS X、VMS和MS-Windows等。無(wú)論哪種計(jì)算機(jī)都可以使用Vim。
在vi發(fā)展歷程的最后一個(gè)轉(zhuǎn)折點(diǎn)上,最原始的ex / vi源代碼最終于2002年在BSD免費(fèi)軟件許可下發(fā)布了。請(qǐng)點(diǎn)擊這里獲取(http://ex-vi.sourceforge.net/)。
下面干貨來(lái)了。在深入Vim的使用技巧之前,先讓我們了解一下Vim的組織以及讀取配置文件的方式。
配置層次結(jié)構(gòu)
我曾經(jīng)錯(cuò)誤地認(rèn)為,Vim僅從?/ .vimrc文件中讀取其所有設(shè)置和腳本。閱讀各種“dotfiles”的代碼庫(kù)更堅(jiān)定了我的這一看法。通常人們覺(jué)得只通過(guò)一個(gè).vimrc文件來(lái)控制編輯器的各個(gè)方面是一種危險(xiǎn)的做法。這些龐大的配置文件有時(shí)被稱為“vim發(fā)行版”。
實(shí)際上,Vim的結(jié)構(gòu)非常整潔,.vimrc只是多個(gè)配置文件中的其中一個(gè)而已。其實(shí),你可以讓Vim告訴你究竟加載了哪些腳本。試試看:任意編輯計(jì)算機(jī)上的某個(gè)源代碼文件。加載后,運(yùn)行如下命令:
花點(diǎn)時(shí)間讀完整個(gè)清單。猜猜看這些腳本可能會(huì)做些什么,并記下它們所在的目錄。
清單比你預(yù)期的要長(zhǎng)嗎?如果你安裝了大量插件的話,那么編輯器需要做大量工作。你可以通過(guò)以下命令檢查是什么導(dǎo)致編輯器的速度變慢,然后再看看它創(chuàng)建的start.log:
為了比較起見,下面我們看看如果沒(méi)有這些配置,Vim的啟動(dòng)速度有多快:
為了確定啟動(dòng)時(shí)或加載緩沖區(qū)時(shí)會(huì)運(yùn)行哪些腳本,Vim會(huì)遍歷“runtimepath”。該設(shè)置是一組以逗號(hào)分隔的目錄列表,各個(gè)目錄的結(jié)構(gòu)都是一致的。Vim會(huì)檢查每個(gè)目錄的結(jié)構(gòu),找到需要運(yùn)行的腳本,并按照目錄在列表中的順序一一處理。
運(yùn)行以下命令就可以檢查系統(tǒng)上的runtimepath:
在我的系統(tǒng)上,runtimepath默認(rèn)包含以下目錄。并非所有這些都必須出現(xiàn)在文件系統(tǒng)中,但如果存在就會(huì)被使用。
~/.vim
主目錄,保存?zhèn)€人偏好的文件。
/usr/local/share/vim/vimfiles
系統(tǒng)范圍的Vim目錄,保存由系統(tǒng)管理員決定的文件。
/usr/local/share/vim/vim81
即$VIMRUNTIME,保存與Vim一起分發(fā)的文件。
/usr/local/share/vim/vimfiles/after
系統(tǒng)范圍Vim目錄中的“after”目錄。系統(tǒng)管理員可以利用該目錄來(lái)覆蓋默認(rèn)設(shè)置,或添加新的設(shè)置。
~/.vim/after
主目錄中的“after”目錄。可以利用該目錄用個(gè)人偏好覆蓋默認(rèn)設(shè)置或系統(tǒng)設(shè)置,或添加新的設(shè)置。
這些目錄會(huì)按照順序處理,所以要說(shuō)“after”目錄有什么特別的話,那就是它位于列表末尾。實(shí)際上“after”并沒(méi)有什么特別之處。
在處理每個(gè)目錄時(shí),Vim都會(huì)查找具有特定名稱的子文件夾。如果想了解更多這方面的信息,請(qǐng)參閱:help runtimepath。下面我們只挑部分進(jìn)行說(shuō)明。
plugin/
編輯任何類型的文件都會(huì)自動(dòng)加載的Vim腳本文件,稱為“全局插件”。
autoload/
(不要與“插件”相混淆。)自動(dòng)加載中的腳本包含僅在其他腳本請(qǐng)求時(shí)加載的函數(shù)。
ftdetect/
用于檢測(cè)文件類型的腳本。可以根據(jù)文件擴(kuò)展名、位置或內(nèi)部文件內(nèi)容決定文件類型。
ftplugin/
編輯已知類型的文件時(shí)執(zhí)行的腳本。
compiler/
定義如何運(yùn)行各種編譯器或格式化工具,以及如何解析其輸出。可以在多個(gè)ftplugins之間共享。且不會(huì)自動(dòng)執(zhí)行,必須通過(guò) :compiler 調(diào)用。
pack/
Vim 8原生軟件包的目錄,它采用了“Pathogen”格式的包管理。原生的包管理系統(tǒng)不需要任何第三方代碼。
最后,通用的編輯器設(shè)置都會(huì)放到~/.vimrc中。你可以通過(guò)它來(lái)設(shè)置用于覆蓋特定文件類型的默認(rèn)值。有關(guān).vimrc設(shè)置的全面講解,請(qǐng)運(yùn)行 :options。
第三方插件
在Vim中,插件只是腳本,必須放在runtimepath中的正確位置才能執(zhí)行。從概念上講,插件的安裝非常簡(jiǎn)單:只需下載文件。問(wèn)題在于,很難刪除或更新某些插件,因?yàn)樗鼈兊淖幽夸浖尤氲搅藃untimepath中,很難判斷哪個(gè)插件負(fù)責(zé)哪些文件。
為了滿足這種需求,網(wǎng)上出現(xiàn)了很多插件管理器。最早在2003年就出現(xiàn)了Vim.org插件倉(cāng)庫(kù)。然而,直到2008年左右,插件管理器的概念才真正流行起來(lái)。
這些工具在Vim的runtimepath中添加了單獨(dú)的查檢目錄,并會(huì)為插件文檔編譯幫助標(biāo)簽。大多數(shù)插件管理器還可以從網(wǎng)上安裝和更新插件代碼,有的還支持并行更新,或者顯示彩色的進(jìn)度條。
以下是按時(shí)間順序整理的插件管理器。我按照每個(gè)插件最早和最新版本進(jìn)行了排序,如果找不到官方的發(fā)行版本,則根據(jù)最早和最后的提交日期排序。
2006年3月- 2014年7月:Vimball(分發(fā)格式和關(guān)聯(lián)的Vim命令)
2008年10月- 2015年12月:Pathogen(由于原生vim包被棄用)
2009年8月- 2009年12月:Vimana
2009年12月- 2014年12月:VAM
2010年8月 - 2010年12月:Jolt
2010年10月 - 2012年12月:tplugin
2010年10月 - 2014年2月:Vundle(在NeoBundle破解代碼后停止使用)
2012年3月 - 2018年3月:vim-flavor
2012年4月 - 2016年3月:NeoBundle(被棄用,建議使用dein)
2013年1月 - 2017年8月:infect
2013年2月 - 2016年8月:vimogen
2013年10月 - 2015年1月:vim-unbundle
2013年12月 - 2015年7月:Vizardry
2014年2月 - 2018年10月:vim-plug
2015年1月 - 2015年10月:enabler
2015年8月 - 2016年4月:Vizardry 2
2016年1月 - 2018年6月:dein.vim
2016年9月 - 至今:原生Vim 8
2017年2月 - 2018年9月:minpac
2018年3月 - 2018年3月:autopac
2017年2月 - 2018年6月:pack
2017年3月 - 2017年9月:vim-pck
2017年9月 - 2017年9月:vim8-pack
2017年9月 - 2019年5月:volt
2018年9月 - 2019年2月:vim-packager
2019年2月 - 2019年2月:plugpac.vim
首先要注意,這些工具五花八門,其次通常每個(gè)工具在活躍大約四年后就會(huì)過(guò)時(shí)。
最穩(wěn)定的管理插件的方法是使用Vim 8的內(nèi)置功能,該功能不需要第三方代碼。下面讓我們具體來(lái)看看這種方法。
首先在運(yùn)行時(shí)目錄的pack目錄中創(chuàng)建兩個(gè)目錄opt和start。
注意占位符 foobar。這個(gè)名稱完全取決于你。我們用它對(duì)包進(jìn)行分類。大多數(shù)人會(huì)把所有的插件都扔進(jìn)一個(gè)無(wú)意義的類別中,這樣完全沒(méi)問(wèn)題。你可以選擇自己喜歡的名稱,在本文中我選擇使用 foobar。理論上,你也可以創(chuàng)建多個(gè)類別,比如~/.vim/pack/navigation, ~/.vim/pack/linting等。請(qǐng)注意,Vim不會(huì)檢測(cè)類別之間的重復(fù),如果存在重復(fù),則會(huì)加載兩次。
“start”中的包會(huì)自動(dòng)加載。而對(duì)于“opt”中的包,只有通過(guò):packadd命令特別請(qǐng)求,Vim才會(huì)加載。opt中適合保存不常用的軟件包,以及為保持Vim的快速啟動(dòng)不必要運(yùn)行的腳本。請(qǐng)注意,:packadd沒(méi)有相反的命令卸載包。
在下述示例子中,我們將添加“ctrlp”模糊查找插件到opt目錄。下載最新版本的命令如下:
????|?tar?zx?-C?~/.vim/pack/foobar/opt
該命令創(chuàng)建了 ~/.vim/pack/foobar/opt/ctrlp.vim-1.79 文件夾,現(xiàn)在這個(gè)包可以使用了。我們?cè)俅位氐絭im中,為這個(gè)新包創(chuàng)建一個(gè)幫助標(biāo)簽的索引:
該命令會(huì)在包的doc目錄中創(chuàng)建了一個(gè)名叫”tags“的文件,這樣Vim的內(nèi)部幫助系統(tǒng)就可以使用它的內(nèi)容了。(或者你也可以在包加載之后運(yùn)行一次:helptags ALL,該命令會(huì)處理runtimepath下的所有文檔。)
在需要使用包時(shí),只需加載它(Tab自動(dòng)補(bǔ)齊也可以用于插件名,所以不需要輸入全名):
packadd會(huì)把包的根目錄放到runtimepath中,然后運(yùn)行它的plugin和ftdetect腳本。在加載ctrlp之后,就可以按Ctrl-P來(lái)彈出模糊文件查找了。
有些人喜歡將~/.vim目錄放到版本管理中,使用git submodules來(lái)管理每個(gè)包。而我喜歡簡(jiǎn)單地將包從tarball中解壓,然后用自己的代碼庫(kù)來(lái)管理。如果你使用成熟的包,那么更新不會(huì)太頻繁,加上腳本本身也很小,不會(huì)把git歷史弄得太亂。
備份和undo
根據(jù)不同的用戶設(shè)置,Vim可以防止四種類型的丟失:
編輯過(guò)程中(兩次保存之間)崩潰。Vim會(huì)定期將未保存的修改寫入交換文件來(lái)防止這種情況。
使用兩個(gè)Vim進(jìn)程編輯同一個(gè)文件,兩個(gè)進(jìn)程互相覆蓋。交換文件也可以防止這種情況。
保存過(guò)程中崩潰,即在目標(biāo)文件已被截?cái)?#xff0c;新的內(nèi)容尚未完全寫入時(shí)崩潰。Vim可以通過(guò)“writebackup”來(lái)防止這種情況。為了實(shí)現(xiàn)該功能,Vim會(huì)首先將內(nèi)容寫入新的文件,寫入成功后與原始文件交換。但這個(gè)功能取決于“backupcopy”設(shè)置。
已保存新文件,但想要找回原文件。Vim可以通過(guò)在寫入改變后保留原始文件的備份來(lái)防止這種情況。
在介紹具體的設(shè)置之前,先來(lái)放松一下吧!下面是GitHub上人們對(duì)于vimrc的一些評(píng)論:
“不要?jiǎng)?chuàng)建交換文件。用版本控制管理就好。”
“素人才用備份。高手都用版本控制。”
“用版本控制就好!”
“版本控制都滿天飛了,就不要再用交換文件和備份了。”
“不要寫備份文件,版本控制就是很好的備份。”
“我其實(shí)從來(lái)沒(méi)用過(guò)VIM的備份文件……一直都在用版本控制。”
“反正大部分東西都保存在版本控制里。”
“禁用備份文件,因?yàn)榉凑阋驳糜冒姹究刂啤!?/span>
“版本控制已來(lái)到,git拯救全世界。”
“禁用交換文件和備份(永遠(yuǎn)使用版本控制!永遠(yuǎn)!)”
“關(guān)掉備份,我所有東西都用版本控制。”
上面的評(píng)論反映出,大家只了解上述第四種情況(偶爾也會(huì)提及第三種情況),這些人傾向于把交換文件也禁用,這會(huì)讓Vim無(wú)法防止第一種和第二種情況。
為了保證編輯更安全,我建議使用下述配置:
"?(4?seconds)?are?fine
set?swapfile
set?directory^=~/.vim/swap//
"?protect?against?crash-during-write
set?writebackup
"?but?do?not?persist?backup?after?successful?write
set?nobackup
"?use?rename-and-write-new?method?whenever?safe
set?backupcopy=auto
"?patch?required?to?honor?double?slash?at?end
if?has("patch-8.1.0251")
????"?consolidate?the?writebackups?--?not?a?big
????"?deal?either?way,?since?they?usually?get?deleted
????set?backupdir^=~/.vim/backup//
end
"?persist?the?undo?tree?for?each?file
set?undofile
set?undodir^=~/.vim/undo//
這些設(shè)置為寫入過(guò)程啟用了備份,但在成功寫入后不會(huì)保留備份,因?yàn)槲覀冇邪姹究刂啤W⒁饽阈枰猰kdir ~/.vim/{swap,undodir,backup},否則Vim會(huì)使用設(shè)置列表中的下一個(gè)可用的文件夾。你還應(yīng)該chmod這些文件夾來(lái)保證隱私,因?yàn)榻粨Q文件和undo歷史可能包含敏感信息。
關(guān)于配置中的路徑,需要提及的一點(diǎn)是,它們末尾使用了雙斜線。這樣可以無(wú)歧義地表示不同目錄下同名文件的交換文件和備份文件。例如,/foo/bar文件的交換文件會(huì)保存在~/.vim/swap/%foo%bar.swp(斜線z轉(zhuǎn)義成百分號(hào))。Vim有一個(gè)bug,對(duì)于backupdir不會(huì)正確處理雙斜線寫法,該bug直到最近才修復(fù),而上述配置可以防止這個(gè)bug。
我們還要求Vim持久保存每個(gè)文件的undo文件,這樣在退出Vim并重新編輯文件時(shí)依然可以使用undo。雖然有了交換文件,這樣做有點(diǎn)多余,但實(shí)際上undo文件是補(bǔ)充性質(zhì)的,因?yàn)樗鼉H在原文件被寫入時(shí)才寫入。(如果undo文件寫入太頻繁,那么可能在崩潰后無(wú)法匹配磁盤上文件的狀態(tài),所以Vim不這樣做。)
說(shuō)起undo就不得不提起Vim會(huì)維持編輯歷史的整個(gè)樹形結(jié)構(gòu)。這意味著你可以做一個(gè)修改,undo之后,然后做另一個(gè)修改,這時(shí)所有三個(gè)狀態(tài)都可以被恢復(fù)。使用:undolist命令可以看到修改的時(shí)間和大小,但從該命令的結(jié)果很難想象整個(gè)樹形結(jié)構(gòu)。你可以遍歷列表中的特定修改,也可以用:earlier和:later命令加上一個(gè)時(shí)間參數(shù)(如5m)或保存次數(shù)參數(shù)(如3f)在時(shí)間軸上移動(dòng)。但是,遍歷undo樹最好使用插件——如undotree。
啟用這些災(zāi)難恢復(fù)設(shè)置可以讓你安心地使用Vim。我曾經(jīng)在編輯過(guò)程中多次保存,或者每次離開電腦時(shí)也會(huì)保存,但現(xiàn)在我會(huì)幾個(gè)小時(shí)都不保存,因?yàn)槲抑澜粨Q文件在老老實(shí)實(shí)地干活。
最后幾點(diǎn):要時(shí)刻關(guān)注這些災(zāi)難恢復(fù)文件,時(shí)間長(zhǎng)了它們可能會(huì)在.vim文件夾下越積越多,占用大量空間。另外,當(dāng)磁盤剩余空間很少,卻需要保存大文件時(shí),也許有必要設(shè)置nowritebackup,否則Vim必須臨時(shí)保存整個(gè)文件的副本。默認(rèn)設(shè)置下“backupskip”設(shè)置能夠禁用系統(tǒng)臨時(shí)目錄下的任何文件的備份。
Vim的“patchmode”與備份有關(guān)。你可以在沒(méi)有被版本控制管理的目錄下使用該設(shè)置。例如,如果你想下載源代碼tar包,做一些修改然后通過(guò)郵件列表提交補(bǔ)丁,這一過(guò)程中不使用git。只需運(yùn)行:set patchmod=.orig,那么任何Vim寫入的文件“foo”就會(huì)備份成“foo.orig”。然后可以通過(guò)命令行比較.orig文件和新文件來(lái)創(chuàng)建補(bǔ)丁。
包含和路徑
絕大多數(shù)編程需要都允許你在一個(gè)文件中包含另一個(gè)模塊或文件。Vim通過(guò)path、include、suffixesadd和includeexpr配置項(xiàng)來(lái)了解如何跟蹤包含文件中的程序標(biāo)識(shí)符。標(biāo)識(shí)符搜索(參見:help include-search)是另一種使用ctags維持系統(tǒng)頭文件的標(biāo)簽文件的方式。
C程序的默認(rèn)設(shè)置工作得很好。其他語(yǔ)言也同樣支持,但需要一些設(shè)置。這些設(shè)置超出了本文的范圍,可以參考:help include。
如果一切配置正確,那么你可以在標(biāo)識(shí)符上按 [i 來(lái)顯示標(biāo)識(shí)符定義,或者在宏常量上按 [d 顯示宏定義。還有,在文件名上按 gf 可以搜索路徑并跳轉(zhuǎn)到相應(yīng)的文件。由于路徑也會(huì)影響 :find 命令,一些人傾向于在路徑中添加“**/*”或常用的目錄,把 :find 命令當(dāng)作簡(jiǎn)裝版的模糊查找使用。但這樣做會(huì)減慢標(biāo)識(shí)符搜索的速度,因?yàn)樗枰阉髋c標(biāo)識(shí)符搜索無(wú)關(guān)的目錄。
不污染路徑而實(shí)現(xiàn)相同查找功能的方式之一就是建立一個(gè)映射。這樣只需按<Leader><space>(通常這兩個(gè)鍵就是反斜杠然后空格)然后輸入文件名,再使用Tab或Ctrl-D自動(dòng)完成來(lái)查找文件。
nmap?<Leader><space>?:e?./**/
重申一下:路徑參數(shù)是為頭文件準(zhǔn)備的。如果你想看更多證據(jù),還可以用:checkpath命令顯示哪些路徑有效。加載一個(gè)C文件然后運(yùn)行:checkpath,它就會(huì)顯示那些當(dāng)前文件包含,卻找不到的文件名。帶感嘆號(hào)的 :checkpath! 可以顯示當(dāng)前文件包含的整個(gè)頭文件層次結(jié)構(gòu)。
默認(rèn)情況下,路徑的值為“.,/usr/include,,”,意思是當(dāng)前目錄、/usr/include,然后是當(dāng)前活動(dòng)緩沖區(qū)的所有兄弟文件。目錄指定符和glob非常強(qiáng)大,詳情可以查看:help file-searching。
我還在C ftplugin中(后文會(huì)多次提到它),讓路徑搜索包含了當(dāng)前項(xiàng)目的包含文件,如./src/include或./include。
setlocal?path+=/usr/include
帶數(shù)字的 ** (如**3)指定子目錄搜索的深度。最好在這里指定深度,以免標(biāo)識(shí)符搜索鎖死。
如果 :checkpath 指示出項(xiàng)目中找不到的文件,那么也可以考慮將下面這些模式添加到路徑中。當(dāng)然,這完全取決于你的系統(tǒng)。
更多的系統(tǒng)包含文件:/usr/include/**4,/usr/local/include/**3
Homebrew庫(kù)的頭文件:/usr/local/Cellar/**2/include/**2
Macports庫(kù)的頭文件:/opt/local/include/**
OpenBSD庫(kù)的頭文件:/usr/local/lib/\*/include,/usr/X11R6/include/\*\*3
另請(qǐng)參考::he [,:he gf,:he :find。
編輯-編譯循環(huán)
:make 命令會(huì)執(zhí)行用戶選擇的程序來(lái)構(gòu)建項(xiàng)目,然后將輸出收集到quickfix緩沖區(qū)中。quickfix記錄中的每一項(xiàng)都記錄了文件名、行號(hào)、列號(hào)、類型(警告或錯(cuò)誤)和消息。一種常見的使用方括號(hào)命令的映射方式如下,可以在quickfix項(xiàng)目中快速移動(dòng):
nmap?]Q?:clast<cr>
nmap?[q?:cprev<cr>
nmap?[Q?:cfirst<cr>
如果在更新程序并重新編譯后,你想知道上次的消息,可以使用 :colder 命令(使用 :cnewer 返回)。如果需要查看有關(guān)當(dāng)前錯(cuò)誤的更多信息,可以使用 :cc ,然后用 :copen 命令查看完整的quickfix緩沖區(qū)。還可以使用 :cile、:caddfile 或 :cexpr 命令,無(wú)需運(yùn)行:make而自行填充quickfix緩沖區(qū)。
Vim能夠利用指定的errorformat字符串解析編譯的輸出。errorformat是個(gè)類似scanf的轉(zhuǎn)義序列。例如,Vim的gcc設(shè)置($VIMRUNTIME/compiler/gcc.vim)中自帶了errorformat設(shè)置,但卻沒(méi)有包含clang編譯器的設(shè)置。于是我創(chuàng)建了下面的定義:
"
"?It?should?be?possible?to?make?this?work?for?the?combination?of
"?-fno-show-column?and?-fcaret-diagnostics?as?well?with?multiline
"?and?%p,?but?I?was?too?lazy?to?figure?it?out.
"
"?The?%D?and?%X?patterns?are?not?clang?per?se.?They?capture?the
"?directory?change?messages?from?(GNU)?'make?-w'.?I?needed?this
"?for?building?a?project?which?used?recursive?Makefiles.
CompilerSet?errorformat=
????\%f:%l%c:{%*[^}]}{%*[^}]}:\?%trror:\?%m,
????\%f:%l%c:{%*[^}]}{%*[^}]}:\?%tarning:\?%m,
????\%f:%l:%c:\?%trror:\?%m,
????\%f:%l:%c:\?%tarning:\?%m,
????\%f(%l,%c)\?:\?%trror:\?%m,
????\%f(%l,%c)\?:\?%tarning:\?%m,
????\%f\?+%l%c:\?%trror:\?%m,
????\%f\?+%l%c:\?%tarning:\?%m,
????\%f:%l:\?%trror:\?%m,
????\%f:%l:\?%tarning:\?%m,
????\%D%*\\a[%*\\d]:\?Entering\?directory\?%*[`']%f',
????\%D%*\\a:\?Entering\?directory\?%*[`']%f',
????\%X%*\\a[%*\\d]:\?Leaving\?directory\?%*[`']%f',
????\%X%*\\a:\?Leaving\?directory\?%*[`']%f',
????\%DMaking\?%*\\a\?in\?%f
CompilerSet?makeprg=make
要激活該編譯器設(shè)置,只需運(yùn)行 :compiler clang。通常該命令在ftplugin文件中執(zhí)行。
另一個(gè)例子是在文本文件上運(yùn)行GNU Diction來(lái)識(shí)別句子中用錯(cuò)的詞匯和短語(yǔ)。可以創(chuàng)建一個(gè)“編譯器”,名為diction.vim:
運(yùn)行 :compiler diction 之后,可以使用 :make 命令來(lái)運(yùn)行,并填充quickfix。最后,我在.vimrc中添加了一個(gè)映射來(lái)運(yùn)行make:
"?GNUism,?for?building?recursively
map?<silent>?<s-F5>?:make?-w<cr><cr><cr>
差異文件和補(bǔ)丁
Vim自帶的比較工具非常強(qiáng)大,但可能有點(diǎn)難用,特別是三方合并視圖。但實(shí)際上花點(diǎn)時(shí)間學(xué)習(xí)你就會(huì)發(fā)現(xiàn)其實(shí)挺好用的。要點(diǎn)就是,每個(gè)窗口都可以處于或不處于“diff mode”。所有處于diffmode的窗口(用:difft[his]設(shè)置)會(huì)與所有其他已經(jīng)處于diffmode的窗口進(jìn)行比較。
我們從一個(gè)簡(jiǎn)單的例子開始。首先創(chuàng)建兩個(gè)文件:
echo?"goodbye,?world"?>?h2
vim?h1?h2
在vim中運(yùn)行 :all 命令,將上述參數(shù)指定的文件分別放入各自的窗口中。在上方的h1的窗口中運(yùn)行 :difft。你會(huì)看到出現(xiàn)了一個(gè)分割線,但沒(méi)有檢測(cè)到任何差異。用Ctrl-W Ctrl-W移動(dòng)到下方窗口,然后運(yùn)行 :difft。這時(shí)就會(huì)檢測(cè)出hello和goodbye之間的差異。在下方窗口中執(zhí)行 :diffg[et] 可以從上方窗口中拉取“hello”,或者使用 :diffp[ut] 將“goodbye”發(fā)送到上方窗口。如果有多個(gè)差異塊,那么按 ]c 或 [c 可以在不同的差異塊中移動(dòng)。
快捷方式之一就是運(yùn)行 vim -d h1 h2 (或者運(yùn)行其別名 vimdiff h1 h2),該命令會(huì)對(duì)所有窗口執(zhí)行 :difft。此外,還可以先用vim h1僅加載h1,然后執(zhí)行 :diffsplit h2。記住,所有這些命令實(shí)際上都是將文件加載到窗口中并設(shè)置diffmode而已。
了解這些基本知識(shí)后,我們來(lái)學(xué)習(xí)怎樣把Vim作為git的三方合并工具使用。首先配置git:
git?config?merge.conflictstyle?diff3
git?config?mergetool.prompt?false
現(xiàn)在,當(dāng)遇到合并沖突時(shí),只需運(yùn)行g(shù)it mergetool。該命令會(huì)啟動(dòng)Vim并打開四個(gè)窗口。這部分看上去很嚇人,我經(jīng)常會(huì)舉棋不定。
|???????????|????????????|????????????|
|???LOCAL???|????BASE????|???REMOTE???|
+-----------+------------+------------+
|?????????????????????????????????????|
|?????????????????????????????????????|
|?????????????(edit?me)???????????????|
+-------------------------------------+
關(guān)鍵在于所有編輯都應(yīng)該在下方窗口中進(jìn)行。上方的三個(gè)窗口僅用于提供文件差異(local和remote)的上下文,以及每一方在修改之前的樣子(base)。
使用 ]c 命令在下方窗口中移動(dòng),針對(duì)每個(gè)差異塊,可以選擇local、base或remote之一來(lái)替換,或者可以自己修改,合并多方的內(nèi)容。
為了能夠更容易地從上方窗口拉取修改,我在vimrc里設(shè)置了一些映射:
map?<Leader>2?:diffget?BASE<CR>
map?<Leader>3?:diffget?REMOTE<CR>
我們已經(jīng)介紹過(guò)了 :diffget,上述綁定會(huì)為其傳遞一個(gè)參數(shù),即用來(lái)識(shí)別拉取源的緩沖區(qū)名。
合并結(jié)束后,執(zhí)行 :wqa 保存所有窗口并退出。如果你想放棄合并,可以運(yùn)行 :cq 放棄所有修改,給shell返回一個(gè)錯(cuò)誤代碼。該錯(cuò)誤代碼會(huì)告訴git應(yīng)當(dāng)忽略這些修改。
diffget還可以接受范圍。如果想從某個(gè)上方窗口拉取所有差異塊,而不想逐個(gè)拉取,可以執(zhí)行 :1,$+1diffget {LOCAL,BASE,REMOTE} 。“+1”是必要的,因?yàn)榫彌_區(qū)的最后一行的“下方”可能存在被刪除的行。
畢竟,三方合并其實(shí)很簡(jiǎn)單。至少,不需要用Fugitive之類的插件在合并沖突時(shí)顯示差異。
最后,8.1.0360版本中包含了xdiff庫(kù),可以直接創(chuàng)建diff文件。這比使用外部程序更有效率,而且可以采用多種diff算法。“patience”算法通常可以生成比默認(rèn)設(shè)置更容易閱讀的輸出。在.vimrc中這樣設(shè)置:
endif
緩沖區(qū)I/O?
看看這是不是很熟悉?你編輯了一個(gè)緩沖區(qū),想把它保存成新文件,所以執(zhí)行了:w newname。再次進(jìn)行一些編輯后,執(zhí)行 :w ,但卻保存到了原始文件上。在這種情況下,你真正需要的是 :saveas newname,即寫入新文件,并將緩沖區(qū)的文件名改為新文件,方便以后的寫入。此外,:file newname命令可以改變緩沖區(qū)文件名,而不會(huì)執(zhí)行實(shí)際的寫入。
學(xué)習(xí)更多有關(guān)讀寫命令的知識(shí)也很有用。因?yàn)閞和w都是ex的命令,所以它們都可以接受范圍。下面是一些你不太熟知的使用方法:
:w >> foo
將整個(gè)緩沖區(qū)追加到文件中
:.w >> foo
將當(dāng)前行追加到文件中
:$r foo
讀取foo并插入到緩沖區(qū)末尾
:0r foo
讀取foo并插入到開頭,已有行向下移動(dòng)
:.,$w foo
將當(dāng)前行以及之后的所有行寫入文件
:r !ls
讀取ls輸出到當(dāng)前光標(biāo)位置
:w !wc
將緩沖區(qū)發(fā)送到wc命令然后顯示結(jié)果
:.!tr 'A-Za-z' 'N-ZA-Mn-za-m'
為當(dāng)前行執(zhí)行ROT-13
:w | so %
連鎖命令:寫入并執(zhí)行緩沖區(qū)
:e!
放棄為保存到修改,重新加載緩沖區(qū)
:hide edit foo
編輯foo,如果當(dāng)前緩沖區(qū)被修改過(guò),則隱藏
冷知識(shí):上面的例子中使用一整行來(lái)調(diào)用 tr 以實(shí)現(xiàn)ROT-13加密,但實(shí)際上Vim內(nèi)置了該功能,即 g? 命令。可以將其應(yīng)用到移動(dòng)操作,如 g?$。
filetypes
filetypes設(shè)置可以根據(jù)緩沖區(qū)中檢測(cè)到到文件類型來(lái)改變?cè)O(shè)置。不過(guò)它們并不一定非要自動(dòng)檢測(cè),我們可以手動(dòng)啟用它們,實(shí)現(xiàn)一些有趣的效果。一個(gè)例子就是十六進(jìn)制編輯。任何文件都可以作為十六進(jìn)制值查看。GitHub用戶the9ball寫了一個(gè)非常聰明的ftplugin腳本,可以將緩沖區(qū)傳遞給xxd或傳回,實(shí)現(xiàn)十六進(jìn)制編輯。
為了方便使用,Vim 5版本捆綁了xxd工具。Vim的todo.txt提到,他們想讓二進(jìn)制文件編輯功能更加順暢,但xxd已經(jīng)實(shí)現(xiàn)了不少功能。?
將下面的代碼放到 ~/.vim/ftplugin/xxd.vim 中。保存到ftplugin中的意思是,每當(dāng)filetype(即“ft”)變成xxd時(shí),Vim就會(huì)執(zhí)行該腳本。我在腳本中添加了一些簡(jiǎn)單的注釋:
????finish
endif
"?don't?insert?a?newline?in?the?final?line?if?it
"?doesn't?already?exist,?and?don't?insert?linebreaks
setlocal?binary?noendofline
silent?%!xxd?-g?1
%s/\r$//e
"?put?the?autocmds?into?a?group?for?easy?removal?later
augroup?ftplugin-xxd
????"?erase?any?existing?autocmds?on?buffer
????autocmd!?*?<buffer>
????"?before?writing,?translate?back?to?binary
????autocmd?BufWritePre?<buffer>?let?b:xxd_cursor?=?getpos('.')
????autocmd?BufWritePre?<buffer>?silent?%!xxd?-r
????"?after?writing,?restore?hex?view?and?mark?unmodified
????autocmd?BufWritePost?<buffer>?silent?%!xxd?-g?1
????autocmd?BufWritePost?<buffer>?%s/\r$//e
????autocmd?BufWritePost?<buffer>?setlocal?nomodified
????autocmd?BufWritePost?<buffer>?call?setpos('.',?b:xxd_cursor)?|?unlet?b:xxd_cursor
????"?update?text?column?after?changing?hex?values
????autocmd?TextChanged,InsertLeave?<buffer>?let?b:xxd_cursor?=?getpos('.')
????autocmd?TextChanged,InsertLeave?<buffer>?silent?%!xxd?-r
????autocmd?TextChanged,InsertLeave?<buffer>?silent?%!xxd?-g?1
????autocmd?TextChanged,InsertLeave?<buffer>?call?setpos('.',?b:xxd_cursor)?|?unlet?b:xxd_cursor
augroup?END
"?when?filetype?is?set?to?no?longer?be?"xxd,"?put?the?binary
"?and?endofline?settings?back?to?what?they?were?before,?remove
"?the?autocmds,?and?replace?buffer?with?its?binary?value
let?b:undo_ftplugin?=?'setl?bin<?eol<?|?execute?"au!?ftplugin-xxd?*?<buffer>"?|?execute?"silent?%!xxd?-r"'
打開一個(gè)文件,然后執(zhí)行 :set ft。記下文件類型。然后執(zhí)行 :set ft=xxd。Vim就會(huì)變成一個(gè)十六進(jìn)制編輯器。要恢復(fù)原來(lái)的視圖,只需 :set fo=foo,其中foo是原始的文件類型。注意十六進(jìn)制視圖甚至還有語(yǔ)法高亮,因?yàn)閂im默認(rèn)自帶了 $VIMRUNTIME/syntax/xxd.vim 。
注意這里的“b:undo_ftplugin”非常巧妙,它可以在用戶或ftdetect機(jī)制將文件類型切換成其他filetype時(shí),讓filetypes執(zhí)行一些清理工作。(上面的例子還可以改進(jìn)一下,因?yàn)槿绻?:set ft=xxd 然后直接改回去,那么緩沖區(qū)會(huì)被標(biāo)記為已修改,即使你沒(méi)有進(jìn)行任何修改。)
ftplugins還可以進(jìn)一步定義已知的filetype。例如,Vim已經(jīng)在 $VIMRUNTIME/ftplugin/c.vim 中為C語(yǔ)言包含了非常好的默認(rèn)設(shè)置。我在 ~/.vim/after/ftplugin/c.vim 中添加了額外的選項(xiàng):
setlocal?cino="Ls,:0,l1,t0,(s,U1,W4"
"?for?quickfix?errorformat
compiler?clang
"?shows?long?build?messages?better
setlocal?ch=2
"?auto-create?folds?per?grammar
setlocal?foldmethod=syntax
setlocal?foldlevel=10
"?local?project?headers
setlocal?path=.,,*/include/**3,./*/include/**3
"?basic?system?headers
setlocal?path+=/usr/include
setlocal?tags=./tags,tags;~
"??????????????????????^?in?working?dir,?or?parents
"????????????????^?sibling?of?open?file
"?the?default?is?menu,preview?but?the?preview?window?is?annoying
setlocal?completeopt=menu
iabbrev?#i?#include
iabbrev?#d?#define
iabbrev?main()?int?main(int?argc,?char?**argv)
"?add?#include?guard
iabbrev?#g?_<c-r>=expand("%:t:r")<cr><esc>VgUV:s/[^A-Z]/_/g<cr>A_H<esc>yypki#ifndef?<esc>j0i#define?<esc>o<cr><cr>#endif<esc>2ki
注意上述腳本使用了“setlocal”而不是“set”。它僅對(duì)當(dāng)前緩沖區(qū)生效,而不是對(duì)整個(gè)Vim進(jìn)程生效。
該腳本還添加了一些縮寫。例如,我可以輸入 #g 并按回撤,就能自動(dòng)使用當(dāng)前文件名添加包含檢測(cè):
#define?_FILENAME_H
/*?<--?cursor?here?*/
#endif
你還可以使用點(diǎn)(“.”)來(lái)混合多種filetypes。下面是應(yīng)用的例子。不同的項(xiàng)目有不同的編碼規(guī)范,所以你可以將默認(rèn)的C設(shè)置與特定項(xiàng)目的設(shè)置結(jié)合起來(lái)。OpenBSD的源代碼遵循style(9)格式(https://man.openbsd.org/style.9),所以我們來(lái)做一個(gè)特殊的openbsd filetype。可以在相關(guān)文件上使用 :set ft=c.openbsd 將兩個(gè)filetype合并。
要檢測(cè)openbsd filetype,可以查看緩沖區(qū)的內(nèi)容,而不僅僅是通過(guò)文件擴(kuò)展名或文件在磁盤上的位置。C文件中包含OpenBSD源代碼的標(biāo)志就是第一行出現(xiàn) /* $OpenBSD: 。
創(chuàng)建 ~/.vim/after/ftdetect/openbsd.vim 進(jìn)行檢測(cè):
????????????????\??if?getline(1)?=~?'OpenBSD;'
????????????????\|???setl?ft=c.openbsd
????????????????\|?endif
augroup?END
OpenBSD的Vim移植已經(jīng)包含了該filetype的特殊語(yǔ)法:/usr/local/share/vim/vimfiles/syntax/openbsd.vim。回憶一下,/usr/local/share/vim/vimfiles目錄位于runtimepath中,用于保存系統(tǒng)管理員提供的文件。該openbsd.vim腳本包含下面的函數(shù):
????setlocal?cindent
????setlocal?cinoptions=(4200,u4200,+0.5s,*500,:0,t0,U4200
????setlocal?indentexpr=IgnoreParenIndent()
????setlocal?indentkeys=0{,0},0),:,0#,!^F,o,O,e
????setlocal?noexpandtab
????setlocal?shiftwidth=8
????setlocal?tabstop=8
????setlocal?textwidth=80
endfun
我們只需在適當(dāng)時(shí)候調(diào)用該函數(shù)。創(chuàng)建 ~/.vim/after/ftplugin/openbsd.vim:
現(xiàn)在打開任何頂部具有標(biāo)志性注釋的C文件或頭文件,就會(huì)被識(shí)別為c.openbsd類型,從而采用style(9)手冊(cè)頁(yè)中規(guī)定的縮進(jìn)選項(xiàng)。
別忘了鼠標(biāo)
在此友好地提醒你,盡管我們都喜歡命令行,但實(shí)際上Vim也支持鼠標(biāo),而且有些任務(wù)比鍵盤更方便。由于xterm能夠?qū)⑹髽?biāo)事件轉(zhuǎn)換為stdin轉(zhuǎn)義代碼,所以我們甚至可以通過(guò)SSH都能支持鼠標(biāo)事件。
如果想啟用鼠標(biāo)支持,則需要設(shè)置 mouse=n。許多人喜歡設(shè)置 mouse=a,因?yàn)檫@樣就可以在所有模式下工作,但我更喜歡只在普通模式下啟用鼠標(biāo)支持。這樣,在我用鍵盤加點(diǎn)擊的方式在瀏覽器中打開鏈接時(shí),就不會(huì)錯(cuò)誤地創(chuàng)建可視選擇區(qū)域。
以下是鼠標(biāo)可以執(zhí)行的操作:
打開或關(guān)閉折疊(當(dāng)foldcolumn> 0時(shí))。
選擇標(biāo)簽(比 gt gt gt gt ...要好用得多)
單擊完成動(dòng)作,例如 d<點(diǎn)擊>。類似于easymotion插件,但不需要任何插件。
雙擊即可跳轉(zhuǎn)到幫助主題。
拖動(dòng)底部的狀態(tài)行以更改cmdheight。
拖動(dòng)窗口邊緣以調(diào)整大小。
鼠標(biāo)滾輪。
其他編輯功能
這部分涉及的內(nèi)容很雜,但我僅在此介紹一些我學(xué)到的技巧。第一個(gè)讓我感到震驚的是::set virtualedit=all。它允許你將光標(biāo)移動(dòng)到窗口中的任何位置。如果你輸入字符或插入可視塊,Vim會(huì)在插入的字符的左側(cè)添加所需的空格以保證它們的位置。虛擬編輯模式可以簡(jiǎn)化表格數(shù)據(jù)的編輯。你可以通過(guò) :set virtualedit= 來(lái)關(guān)閉這個(gè)選項(xiàng)。
接下來(lái)是一些移動(dòng)命令。在跳轉(zhuǎn)到下一段時(shí),我習(xí)慣于使用 } ,每次跳轉(zhuǎn)一個(gè)段落。然而, ] 字符可以完成更精準(zhǔn)的跳轉(zhuǎn):跳轉(zhuǎn)到下一個(gè)函數(shù) ]]、作用域 ]}、圓括號(hào) ‘])’、注釋 ]/、差異塊 ]c。前面提到的 quickfix 映射 ]q 也是這種操作方式之一。
對(duì)于大段的跳轉(zhuǎn),我曾經(jīng)嘗試過(guò) 1000j 等操作,但實(shí)際上只需在普通模式下鍵入百分比,Vim就會(huì)跳轉(zhuǎn)到相應(yīng)的位置,比如50%。說(shuō)到滾動(dòng)百分比,你隨時(shí)可以使用CTRL-G查看它。所以現(xiàn)在我采用了 :set noruler 的設(shè)置,只在需要了解百分比的時(shí)候查看,這樣畫面就不會(huì)過(guò)于雜亂了。這似乎與色彩斑斕的powerlines的流行趨勢(shì)有點(diǎn)背道而馳。
如果想在標(biāo)簽、文件或文件中跳轉(zhuǎn),那么有些命令可以幫助你。比如::ls、:tags、:jumps 和 :marks。在標(biāo)簽之間跳轉(zhuǎn)實(shí)際上會(huì)創(chuàng)建一個(gè)棧,你可以按CTRL-T跳到前一個(gè)。以前我經(jīng)常按CTRL-O退出跳轉(zhuǎn),但是它不如彈出標(biāo)簽棧那般直接。
在使用ctags編制索引的項(xiàng)目目錄中,你可以使用 -t 選項(xiàng)在打開編輯器時(shí)直接跳到標(biāo)簽,比如:vim -t main。如果想更靈活地查找標(biāo)簽文件,那么可以設(shè)置 tags 配置變量。請(qǐng)注意如下示例中的分號(hào),有了它Vim就可以從當(dāng)前目錄向上搜索到主目錄。如此一來(lái),你就可以在項(xiàng)目文件夾外部使用更通用的系統(tǒng)標(biāo)記文件。
"??????????????????????????^?in?working?dir,?or?parents
"???????????????????^?in?any?subfolder?of?working?dir
"???????????^?sibling?of?open?file
此外,還有一些緩沖區(qū)技巧。切換緩沖區(qū)的命令 :bu 可以接受緩沖區(qū)名稱的片段作為參數(shù),而不僅僅是數(shù)字。有時(shí)很難記住這些數(shù)字,相比之下源文件的名稱更加方便記憶。你也可以使用標(biāo)記來(lái)瀏覽緩沖區(qū)。如果使用大寫字母作為標(biāo)記的名稱,則可以跨緩沖區(qū)跳轉(zhuǎn)到該標(biāo)記。你還可以在標(biāo)題中設(shè)置標(biāo)記H,在源文件中設(shè)置C,在Makefile中設(shè)置M,這樣就可以在緩沖區(qū)之間來(lái)回跳轉(zhuǎn)了。
你有沒(méi)有遇到過(guò)這種情況:復(fù)制一個(gè)單詞,然后在其他地方刪掉一個(gè)單詞,當(dāng)嘗試粘貼第一個(gè)單詞時(shí),卻發(fā)現(xiàn)原來(lái)復(fù)制的單詞已被覆蓋。是不是很氣惱?Vim寄存器不善于處理這種情況。你可以用 :reg 檢查其內(nèi)容。當(dāng)你復(fù)制文本時(shí),先前的復(fù)制就會(huì)被輪換到寄存器"0 - "9。因此,"0p 會(huì)粘貼倒數(shù)第二個(gè)復(fù)制/刪除。特殊寄存器 "+ 和 "* 可以從系統(tǒng)剪貼板中復(fù)制/粘貼,也可以復(fù)制/粘貼到系統(tǒng)剪貼板。通常,這兩者的含義相同,除了在一些X11設(shè)置中會(huì)區(qū)分首選和備選。
另一個(gè)非常方便的隱藏功能是命令行窗口。它是一個(gè)緩沖區(qū),其中包含了你以前運(yùn)行的命令和搜索。你可以通過(guò) q: 或 q/ 顯示該窗口。在進(jìn)入該緩沖區(qū)后,你可以隨意移動(dòng)到任何一行,然后按Enter鍵運(yùn)行該行的命令。然而,你也可以在按Enter鍵之前對(duì)行進(jìn)行編輯。你的更改不會(huì)影響該行(僅會(huì)將新的命令將添加到列表的底部)。
vim的使用技巧繁多,文本無(wú)法詳盡闡述。如果你想了解更多信息,請(qǐng)參閱幫助文檔:views-sessions、viminfo、TOhtml、ins-completion、cmdline-completion、multi-repeat、scroll-cursor、text-objects、grep、netrw-contents。
原文:https://begriffs.com/posts/2019-07-19-history-use-vim.html
本文為 CSDN 翻譯,轉(zhuǎn)載請(qǐng)注明來(lái)源出處。
(*本文為 AI科技大本營(yíng)轉(zhuǎn)載文章,轉(zhuǎn)載請(qǐng)聯(lián)系原作者)
社群福利
掃碼添加小助手,回復(fù):大會(huì),加入2019 AI開發(fā)者大會(huì)福利群,每周一、三、五更新技術(shù)福利,還有不定期的抽獎(jiǎng)活動(dòng)~
◆
精彩推薦
◆
60+技術(shù)大咖與你相約 2019 AI ProCon!大會(huì)早鳥票已售罄,優(yōu)惠票速搶進(jìn)行中......2019 AI開發(fā)者大會(huì)將于9月6日-7日在北京舉行,這一屆AI開發(fā)者大會(huì)有哪些亮點(diǎn)?一線公司的大牛們都在關(guān)注什么?AI行業(yè)的風(fēng)向是什么?2019 AI開發(fā)者大會(huì),傾聽大牛分享,聚焦技術(shù)實(shí)踐,和萬(wàn)千開發(fā)者共成長(zhǎng)。
推薦閱讀
自動(dòng)駕駛激蕩風(fēng)云錄:來(lái)自圈內(nèi)人的冷眼解讀
不止最佳長(zhǎng)論文,騰訊AI在ACL上還有這些NLP成果
認(rèn)知智能的突圍:NLP、知識(shí)圖譜是AI下一個(gè)“掘金地”?
5G+AI重新定義生老病死
干貨 | 20個(gè)Python教程,掌握時(shí)間序列的特征分析(附代碼)
2019 年度程序員吸金榜:你排第幾?
字節(jié)跳動(dòng)入局全網(wǎng)搜索;思科回應(yīng)中國(guó)區(qū)裁員;IntelliJ IDEA 新版發(fā)布!?| 極客頭條
知名飲料制造商股價(jià)暴漲500%驚動(dòng)FBI,只因在名字中加入了"區(qū)塊鏈" ?
總結(jié)
以上是生活随笔為你收集整理的Vim激荡30年发展史的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: CTC模型简介
- 下一篇: anki制作灵活简洁的英语单词模板