oeasy教您玩轉vim - 88 - # 自動命令autocmd
自動命令 autocommand
回憶
上次我們研究的是外部命令grep
可以在vim中使用grep
搜索的結果進入了列表
可以打開、遍歷、跳轉、關閉這個列表
也可以給列表中的匹配行或者每個文件執(zhí)行命令
到此為止學了很多的命令
有內部的也有外部的
有的在命令行模式里面執(zhí)行
還有的映射到一組鍵盤在正常模式下執(zhí)行
但是都需要按下些什么按鍵才能支持
能否什么都不按自動就執(zhí)行呢???
自動命令autocmd
在~/.vim/ftplugin(當前用戶的插件目錄)編輯插件文件
ftplugin中
ft代表filetype
plugin代表插件
mkdir -p ~/.vim/ftplugin sudo vi ~/.vim/ftplugin/log.vim
定義函數
function DateInsert() ? ?$delete ? ?read !dateendfunction
$delete
把原來的最后一行的日期刪除掉
read !date
讀取當前日期
并且寫到最后一行
嘗試調用
新建并打開log文件
vi a.log
調用函數
:call DateInsert()
但是他好像不認識log文件一樣
:function
中沒有DateInsert():function DateInsert

設置filetype文件類型
Q進入Ex模式
:filetype
查看文件類型檢測情況
:set filetype=log
強制設置文件類型為log
:function DateInsert
觀察DateInsert函數
可以找到了定義的函數了
是否可以調用呢?

:call DateInsert()
調用DateInsert()
:visual
回到編輯模式
但是每次都要手動設置filetype么?
這顆太麻煩了
能否自動檢測呢?
自動檢測文件類型filetype
查詢幫助
:h filetype

mkdir ~/.vim/ftdetect
sudo vi ~/.vim/ftdetect/log.vim
ft代表filetype
detect 代表文件自動檢測
在文件里面寫上
au BufRead,BufNewFile *.log set filetype=log
vi a.log

檢測成功
:call DateInsert()
函數調用成功
我想把這個函數做成一個命令可以么?
制作命令
:nnoremap Di :call DateInsert()<CR>
n
normal 正常模式noremap
不再遞歸映射nnoremap
Di 指定的命令Command
:call DateInsert() 調用函數
<CR>
carriage 回車在normal模式下依次按下
Di
可以用
再次
Di
可以刷新時間我想保存的時候自動調用可以么?
自動命令
:autocmd BufWritePre *.log call DateInsert()
對應具體執(zhí)行的命令
目前文件模式為
*.log
Buf
指的是當前緩存bufferWrite
指的是寫當前緩存Pre
指的是在寫當前緩存之前作用是添加自動命令
autocmd
是命令的名字BufWritePre
是{events} 是觸發(fā)條件*.log
是 {file_pattern} 是文件模式call DateInsert()
是{cmd}:wq
cat a.log
最新的時間已經寫在最后一行了
不過這個自動命令最好寫在filetype的插件里面
這樣自動命令就被定義到自動插件里面了
刪除自動命令
:autocmd
可以查看所有的自動命令autocmd
:autocmd! FileWritePre *.log
注意那個嘆號是否定的意思
把他定義為啥都沒有
也就刪除了
配置插件
vi ~/.vim/ftplugin/log.vim
:autocmd BufWritePre *.log call DateInsert()
為什么強調
*.log
呢因為如果{file_pattern}是
*.*
的話一旦打開了
log
文件保存任何其他文件時都會執(zhí)行
DateInsert()
了
echo "i am a log!"set filetype=log ? ?source ~/.vim/ftplugin/log.vimautocmd BufWritePre *.log call DateInsert()
查看幫助
:h autocmd

{events} 具體的觸發(fā)事件
{pattern} 文件模式
{group} 成組 自動命令成組并命名 可省
group 應該如何理解?
成組自動命令
成組是可選的
可以成組也可以不成組
這是繞口令么?
我們來看看
augroup cprograms ? ?autocmd BufReadPost *.c *.h :set sw=4 sts=4 ? ?autocmd BufReadPost *.cpp :set sw=3 sts=3 augroup END
上面說的是在讀取.c、.h 之后
自動設置縮進寬度為4
在讀取.cpp之后
自動設置縮進寬度為3
總而言之這兩自動命令成為了一個組叫做cprograms
也可以寫成
? ?autocmd cprograms BufReadPost *.c *.h :set sw=4 sts=4 ? ?autocmd cprograms BufReadPost *.cpp :set sw=3 sts=3
下面這樣可以刪除組中所有的自動命令
:autocmd! cprograms
觸發(fā)事件events
:autocmd BufReadPost *.gsm set filetype=asm
把gsm文件的文件格式filetype設置為asm
gsm是gnu的assemble language
BufReadPost
是讀取之后set filetype=asm
:autocmd Filetype text source ~/.vim/abbrevs.vim
加載一些縮寫
是檢測到文件類型為文本的時候
vi a.txt
可以觸發(fā)Filetype text
Filetype text
source ~/.vim/abbrevs.vim
:autocmd BufNewFile *.[ch] 0read ~/sktletons/skel.c
加載c一個骨架文件作為框架
然后添皮加肉
BufNewFile
新建緩存文件的時候*.[ch]
文件類型對應
*.c或者*.h
BufNewFile *.[ch]
0read ~/sktletons/skel.c
文件模式patterns
通配符wild character
在對應路徑中使用,比如:
~/.vim/ftplugin/*
/home/oeasy/*.txt
a{b,c}
對應ab或ac
*.[ch]
對應一個點dot
D???.c
*.c
*.h
*任意多個字符或數字
?一個字母
.
[]或者關系
{}或者關系
/
自動命令的嵌套
一般來說自動命令的執(zhí)行結果不會觸發(fā)另一個自動命令
但是,如果你偏要觸發(fā)
可以加上 nested
:autocmd FileChangedShell * nested edit
比如你打開了文件時觸發(fā)了自動命令
自動命令做出了一些修改
這些修改就也會觸發(fā)這個事件
使用文件名和擴展名
touch oeasy.txt oeasy.txt.new
新建兩個文件
vi
:echo expand("%:t")
輸出文件名
因為現在啥都沒有所以啥都沒輸出
:e oeasy.txt
打開oeasy.txt進入緩存buffer
:echo expand("%:t")
輸出當前文件名
:echo "hello i am " . expand("%:t")
輸出一句話

autocmd BufReadPost * echo "hello i am " . expand("%:t")
定義自動命令
讀取任何文件格式的文件之后
輸出hello 和 當前文件名
:h expand
顯示
hello i am eval.txt
成功
強制觸發(fā)
:doautocmd BufReadPost oeasy.txt
雖然后沒有打開
oeasy.txt
但是他強制執(zhí)行了
BufReadPost oeasy.txt
對應的自動命令autocmd
這樣的話我可以在讀取oeasy.txt.new的時候
然后顯示出oeasy.txt么?
:autocmd BufReadPost *.new echo "hhh " . expand("<afile>:r")

先退出vim
執(zhí)行其他的自動命令
重新打開vim
輸入
:autocmd BufReadPost *.txt echo "hello i am txt:" . expand("%:t")
定義對于txt文件讀取之后的自動命令
然后打開txt文件和非txt文件
打開或切換時會有相應的顯示
而非txt文件不會有顯示

此時打開oeasy.txt.new沒有任何提示
:autocmd BufReadPost *.new execute "doautocmd BufReadPost " . expand("<afile>:r")
執(zhí)行 "doautocmd BufReadPost " . expand("<afile>:r")
定義
*.new
打開之后對應的自動命令autocmd BufReadPost *.new
excute "doautocmd BufReadPost " . expand("<afile>:r")

如果我們重新打開
oeasy.txt.new
或者切換buffer的時候強制執(zhí)行
oeasy.txt
打開后的自動命令也就是
execute "doautocmd BufReadPost oeasy.txt"

執(zhí)行正常模式命令
剛才執(zhí)行的都是命令行模式的命令
如果我想執(zhí)行正常模式的命令應該如何呢?
:autocmd BufReadPost *.log normal G
讀取
*.log
的時候normal G 在正常模式下執(zhí)行G
跳到最后一行,查看最新的日志
那么可以自動命令可以進入插入模式么?
normal
進入正常模式,在正常模式下i進入插入模式esc退出
:進入命令模式esc退出
/進入搜索模式esc退出
:autocmd BufReadPost *.txt execute "normal ggONew entry:\<Esc>" | 1read !date
執(zhí)行
normal ggONew entry:\<Esc>
在第一行寫字|
然后執(zhí)行1read !date
在第二行寫日期制作讀取txt文件后對應自動命令
autocmd BufReadPost *.txt
excute "normal ggONew entry:\<Esc>" | 1read !date

我們最后來看看已經寫好的一些autocmd
vim的系統(tǒng)文件夾
我們之前都是在用戶的vim文件夾進行配置
用戶的vim文件夾只能配置當前用戶的vim
現在我們去系統(tǒng)的vim文件夾看看具體的配置
這樣我們就可以給所有用戶配置vim了
系統(tǒng)的vim的文件夾在
/usr/share/vim/vim81
基本上配置都在這里完成

其中有一些縮寫
au autocmd
exe execute

總結
這個自動命令還是很方便的
打開時、保存時就會有自動執(zhí)行的操作
自動命令有這么幾大元素
{event}
觸發(fā)事件{pattern}
文件模式{cmd}
具體執(zhí)行命令{augroup}
命令組自動命令可以新建、刪除、列表、查詢
還可以強制執(zhí)行
有這個我們可以
針對每種不同的文件的類型
定義相應的觸發(fā)事件
然后執(zhí)行各種各樣的命令
方便操作
不過關于文件類型的高亮顯示還是沒有講的特別清楚
為什么
public
在java
文件里面就可以改變顏色呢????下次再說!