與自定義快捷鍵相關的四個系列命令
map系列命令
這個命令的聲明如下: :map {lhs} {rhs}。這個命令就是將{lhs}代表的按鍵映射成{rhs}所代表的按鍵。例如map L $就是將$鍵映射成L。此外需要注意的是map命令定義的快捷鍵是可以嵌套的,例如下面這樣的命令:
map L $
map Y yL
就是將Y按鍵映射成了y$按鍵。
noremap系列命令
這個命令的聲明如下: :no[remap] {lhs} {rhs},顧名思義,就是不可以重新映射的命令。這個命令和map命令類似,不過它所定義的命令不可以被重新映射,例如下面的例子:
map L $
map Y yL
此時我們映射的Y按鍵的效果就不會和y$按鍵的效果相同了。此命令的主要作用是為了防止按鍵重新定義時出現沖突,所以一般推薦使用此命令來映射快捷鍵。
unmap系列命令
unmap,顧名思義,就是用來取消所在模式下快捷鍵的定義(關於模式我們下一小結會將)。
mapclear系命令
mapclear,清除所在模式下定義的所有快捷鍵。
自定義快捷鍵相關的六種模式
在Vim中,共有六種模式,不同的定義快捷鍵的命令生效的模式不同,這六種模式如下:
N ormal Mode: 即Vim的普通模式,我們打開Vim后進入的第一個模式即此模式。
V isual Mode: 即Vim的Visual模式,我們在選中了一定的文本之后(通過v或者V命令)即進入此模式。
S elect Mode: 這種模式和Visual模式相似,不過輸入的文本都會替換選中的文本。在普通模式下,通過鼠標選中或者使用gH命令都可以進入此模式。
O perator-pending Mode: 當我們輸入一個操作符后(例如,d,y,c等等),就會進入此模式。
I nsert Mode: 即Vim的插入模式,普通模式下我們輸入i(或者s,a等等)就會進入此模式。
C ommand-line Mode: 命令行模式,我們在普通模式下輸入:或者/等就會進入此模式。
命令模式對應表
下表表示了每個自定義快捷鍵的命令和其對應的生效模式,需要注意的是Lang-Arg並不是一種新的模式,而是表示了這樣一種情況。當我們鍵入一個字符的時候,它是緩沖區中文本的一部分,而不是一個Vim命令。上面這句話我翻譯自Vim文檔,我感覺自己也沒有很是搞懂,所以還是把原文貼出了吧(參見:help language-mapping):

通過觀察上面這些命令的前綴,我們可以發現,命令前綴和生效的模式有關。例如,v表示Visual和Select模式,s表示Select模式,c表示Command-line模式,等等。
分享兩個我自己定義的快捷鍵
Ok,扯了那么多和自定義快捷鍵相關的東西,接下來我和大家分享幾個我自定義的快捷鍵吧,感覺用起來很爽,希望對大家有幫助。
Tab鍵映射成搜索
搜索無疑是一個使用頻率非常高的快捷鍵,但在原始的Vim中使用的卻是/或者?,當要使用搜索功能的時候,我的右手要離開HomeRow(就是 愛上對方過后就哭了 那一行),然后使用中指或者食指去按/,感覺雖然也可以用右手小拇指去按/,但實在是太費勁。
所以我就把/映射成了<Tab>,<Tab>鍵在普通模式下基本用不到,同時左手小拇指又非常容易按到,感覺一下子方便了許多。映射命令如下:
" 映射/為<Tab>
noremap <Tab> /
1
2
大家可以看到,我這里使用的是noremap映射的(防止以后再來映射和<Tab>鍵相關的組合鍵時出現錯誤),同時,這個命令生效的模式是Normal,Visual,Select,Operator-pending。這樣我不僅可以在普通模式下搜索,也可以在選擇文本(Visual),刪除文本(通過d命令)時進行搜索。
后來我才發現,<Tab>和<C-i>的keycode是一樣的,無法分別映射,所以將<Tab>映射為搜索按鍵會影響到<C-i>的功能,所以還是先刪除掉吧。
快速定位當前文件
這條映射是我在《VIM 實用技巧》中看到的,感覺很好用,特意來分享給大家。此映射命令如下:
" 將%:h映射為%%,%:h的功能是顯示當前緩沖區文件的相對路徑
cnoremap <expr> %% getcmdtype() == ':' ? expand('%:h').'/' : '%%'
這條命令比較復雜,首先cnoremap表示在命令行模式下進行映射,<expr>表示將映射命令的右邊的參數當做一個表達式來對待(詳見: :help :map-<expr>)。
%%就是我們定義的快捷鍵,getcmdtype() == ':' ? expand('%:h').'/' : '%%'就是我們要執行的表達式,此命令的含義就是每當我們在命令行模式下輸入%%,就會得到表達式getcmdtype() == ':' ? expand('%:h').'/' : '%%'運算的結果。
接着我們再來分析一下這個表達式,getcmdtype() == ':' ? expand('%:h').'/' : '%%'。
首先來看調用的兩個函數,getcmdtype表示獲取當前命令行模式的類型,:表示是Ex-Mode,就是在普通模式下輸入:進入的模式,此外其他的返回結果參見:help getcmdtype()。
expand()函數表示對通配符進行擴展,其中傳入的參數為%和:h,%表示當前緩沖區文件,:h相當於一個函數,傳入一個文件參數,返回文件所在的文件夾(相當於Python中的os.path.dirname()),我們可以看到expand('%:h')函數的功能就是返回當前緩沖區文件所在的路徑。
整體來看這個表達式的話,就是一個三元運算符,如果當前模式是Ex-Mode的話,返回當前緩沖區文件所在的文件夾,否則的話返回%%。
有待考證和完善之處
寫文章之前,我覺得我應該已經了解了Vim的map相關的命令,但是寫完以后,發現還是有很多疑問,寫到最后發現還有新東西自己沒有涉及,這里先記錄下來,以待以后完善:
map的遞歸定義的用法。我看到:help :map文檔中說,This allows for nested and recursive use of mappings.也就是說map可以進行遞歸定義的,只是不知道怎么用,遞歸出口在哪?
map命令還有一個map-<expr>的用法,這次還沒有講,以后加上。
關於文檔中Lang-arg還不是很懂。
前綴鍵
前綴鍵。各類 vim 插件幫助文檔中經常出現 <leader>,即,前綴鍵。vim 自帶有很多快捷鍵,再加上各類插件的快捷鍵,大量快捷鍵出現在單層空間中難免引起沖突,為緩解該問題,引入了前綴鍵 <leader>,這樣,鍵 r 可以配置成 r、<leader>r、<leader><leader>r 等等多個快捷鍵。前綴鍵是 vim 使用率較高的一個鍵(最高的當屬 Esc),選一個最方便輸入的鍵作為前綴鍵,將有助於提高編輯效率。找個無須眼睛查找、無須移動手指的鍵 —— 分號鍵,挺方便的,就在你右手小指處:
" 定義快捷鍵的前綴,即<Leader> let mapleader=";"
舉例
- 使用set命令:
set pastetoggle=<F9> - 使用imap命令:
用Esc退出插入模式很麻煩,可以將另外的鍵映射到這個鍵上,比如將Ctrl-i映射為Esc:imap <C-I> <Esc> - "配置F4為Ack快捷鍵:
:map <F4> :Ack -i - 在插入模式,設置ctrl+\為退出文件 :
:map! <C-\> <ESC>:q<CR>
<Esc>代表Escape鍵:<CR>代表Enter鍵;<D>代表Command鍵。
Alt鍵可以使用<M-key>或<A-key>來表示。<C>代表Ctrl.
對於組合鍵,可以用<C-Esc>代表Ctrl-Esc;使用<S-F1>表示Shift-F1.
