Vimscript 自動命令

2018-02-24 16:02 更新

現(xiàn)在我們談?wù)撘粋€跟映射一樣重要的東西:自動命令。

自動命令可以讓Vim自動執(zhí)行某些指定的命令,這些指定的命令會在某些事件發(fā)生的時候執(zhí)行。我們先看一個例子。

使用:edit foo打開一個新文件,然后立即使用:quit關(guān)閉。查看你的硬盤,你會發(fā)現(xiàn)這個文件并不存在。這是因為在你第一次保存這個文件之前,Vim_實際上_并沒有真正創(chuàng)建它。

讓我們對Vim做一些改變,使得Vim可以在你開始編輯文件的時候就創(chuàng)建它們。執(zhí)行下面的命令:

:autocmd BufNewFile * :write

這里面有很多需要進一步說明的,不過在此之前我建議你先感受下它是怎么工作的。執(zhí)行:edit foo,使用:quit關(guān)閉,然后查看硬盤。這個時候文件會存在(當然文件內(nèi)容為空)。

你只有關(guān)閉Vim才能刪除這個自動命令。我們會在后面的章節(jié)說明如何避免這種情況。

自動命令結(jié)構(gòu)

讓我們來深入分析下我們剛才創(chuàng)建的自動命令:

:autocmd BufNewFile * :write
         ^          ^ ^
         |          | |
         |          | 要執(zhí)行的命令
         |          |
         |          用于事件過濾的“模式(pattern)”
         |
         要監(jiān)聽的“事件”

這個命令的第一部分是我們想監(jiān)聽的事件的類型。Vim提供了_很多_可以監(jiān)聽的事件。這些事件包括:

  • 開始編輯一個當前并不存在的文件。
  • 讀取一個文件,不管這個文件是否存在。
  • 改變一個緩沖區(qū)的filetype設(shè)置。
  • 在某段時間內(nèi)不按下鍵盤上面的某個按鍵。
  • 進入插入模式。
  • 退出插入模式。

上面只舉出了可用事件里面的很小一部分。還有很多其他的事件,你可以利用這些事件來做一些有趣的事情。

這個自動命令的下一部分是一個“模式”,這個模式可以進一步限定你要執(zhí)行的命令的執(zhí)行范圍。新開一個Vim實例,執(zhí)行下面的命令:

:autocmd BufNewFile *.txt :write

這個跟之前的那個自動命令基本一樣,不過這個自動命令只對后綴為.txt的文件有效,也就是說當你新建的文件為txt文件的時候,Vim會在文件創(chuàng)建的時候自動執(zhí)行write命令將文件保存到硬盤上。

試試執(zhí)行:edit bar,然后執(zhí)行:quit,再執(zhí)行:edit bar.txt,然后再執(zhí)行:quit。你會發(fā)現(xiàn)Vim會自動創(chuàng)建bar.txt,但不會創(chuàng)建bar,因為它的后綴名不是txt,不跟模式匹配。

這個自動命令的最后一部分是事件發(fā)生時我們想執(zhí)行的命令。這個部分很容易理解,跟我們執(zhí)行其他命令一樣,除了不能在這個命令中使用特殊的字符,例如<cr>。我們會在本書后面的章節(jié)中談?wù)撊绾瓮黄七@個限制,現(xiàn)在你只需要遵守它就可以。

再來一個示例

我們再定義一個自動命令,這次使用一個不同的事件。執(zhí)行下面的命令:

:autocmd BufWritePre *.html :normal gg=G

這里用到了normal命令,我會在本書的后面的章節(jié)里面講到它,這可能有點超前,不過我覺得這是一個很好的使用自動命令的示例,所以請大家先忍受一下。

創(chuàng)建一個名為foo.html的新文件。用Vim編輯它,并輸入下面的文本,請保證輸入的文本完全一致,包括空白符:

<html>
<body>
 <p>Hello!</p>
                 </body>
                  </html>

執(zhí)行:w保存這個文件。看看會發(fā)生了什么?Vim似乎在文件保存之前重新進行了文本縮進處理。

ok,請先相信我文本縮進處理是:normal gg=G干的,先別糾結(jié)于為什么:normal gg=G可以干這個。

我們_應(yīng)該_把注意力放在自動命令上。這個自動命令里面用到的事件是BufWritePre,這個事件會在你保存_任何_字符到文件之前觸發(fā)。

我們使用了*.html這個模式,這個模式會保證命令只會在編輯html文件的時候被執(zhí)行。這就是自動命令強大的地方,因為它可以專門針對特定類型的文件來執(zhí)行我們想要執(zhí)行的命令。ok,讓我們繼續(xù)探索它吧。

多個事件

你可以創(chuàng)建一個綁定_多個_事件的自動命令,這些事件使用逗號分隔開。執(zhí)行下面的命令:

:autocmd BufWritePre,BufRead *.html :normal gg=G

這個跟上面的自動命令基本一樣,不同的是它會讓Vim不僅在寫html文件的時候進行縮進處理,讀html文件的時候也會進行縮進處理。如果你有些同事不喜歡把HTML文件格式搞得漂亮點,那么這個命令會很有用。

在Vim腳本編程中有一個不成文的規(guī)定,你應(yīng)該同時使用BufReadBufNewFile(譯注:這里不是BufWritePre)這兩個事件來運行命令,這樣當你打開某個類型的文件,不論這個文件是否存在命令都會執(zhí)行。執(zhí)行下面的命令:

:autocmd BufNewFile,BufRead *.html setlocal nowrap

上面的命令會使得無論你在什么時候編輯HTML文件自動換行都會被關(guān)閉。

FileType事件

最有用的事件是FileType事件。這個事件會在Vim設(shè)置一個緩沖區(qū)的filetype的時候觸發(fā)。

讓我們針對不同文件類型設(shè)置一些有用的映射。運行命令:

:autocmd FileType javascript nnoremap <buffer> <localleader>c I//<esc>
:autocmd FileType python     nnoremap <buffer> <localleader>c I#<esc>

打開一個Javascript文件(后綴為.js的文件),將光標移動到某一行,敲擊<localleader>c,光標所在的那一行會被注釋掉。

現(xiàn)在打開一個Python文件(后綴為.py的文件),將光標移動到某一行,敲擊<localleader>c,同樣的那一行會被注釋掉,不同的是此時所用的是Python的注釋字符!

在自動命令中包含我們上一章中學(xué)到的本地緩沖區(qū)映射,我們可以創(chuàng)建一些映射,這些映射會根據(jù)我們正在編輯的文件的類型來進行不同的處理。

這可以為我們在編碼的時候減輕很多思考的負擔。如果要添加一個注釋,我們可能想到的是必須將光標移動到行首,然后添加一個注釋字符,而使用上面的映射,我們只需要簡單的將其理解為“注釋掉這一行”。

練習

瀏覽:help autocmd-events查看自動命令可以綁定的所有事件。你不需要現(xiàn)在就記住每一個事件。僅僅只需要了解下你可以使用這些事件做哪些事情。

創(chuàng)建一些FileType自動命令使用setlocal對你喜歡的文件類型做一些設(shè)置。你可以針對不同的文件類型設(shè)置wraplist、?spellnumber這些選項。

對一些你會經(jīng)常處理的文件類型創(chuàng)建一些類似“注釋掉這一行”的命令。

把所有這些自動命令寫到你的~/.vimrc文件里面。記住使用前面章節(jié)中提到過的快速編輯和加載~/.vimrc文件的映射來做這個事情,這是必須的!

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號