如果說 vim有什么最吸引人,我想vim允許你自由的定義各種快捷鍵算是一個原因吧。你可以通過綁定各種快捷鍵來使經常使用的功能更加便利。通俗的講,快捷鍵映射就是我按下某個鍵,我想讓vim將它當成另一個鍵,例如我按下 k
,我想讓vim把它當做 c
來使用(當然這么映射會把人逼瘋)
快捷鍵映射
我們使用 :map
命令來進行快捷鍵的映射,例如我們輸入如下內容
:map - dd
通過這個命令,我們將 -
映射為 dd
,也就是說現在我們按下 -
就可以刪除光標所在行了。
針對功能鍵,例如 Ctrl
、空格
、Tab鍵
等,在 vim
中使用 <keyname>
的形式,其中 keyname
是按鍵名稱,下面列舉出一些常用的控制鍵的表示方式:
-
Ctrl
鍵對應<c>
-
空格
鍵對應<space>
-
alt
鍵對應<a>
-
esc
鍵對應<esc>
- 退格鍵對應
<bs>
- 回車鍵對應
<cr>
-
shift
鍵對應<shift>
-
f1
到f12
對應<f1>
到<f12>
這些功能鍵與普通字母做配合時,將字母鍵放入到 <>
中,并以 -
和 功能鍵做分割,比如 :map <c-d> dd
來將 <Ctrl +d>
映射為 dd
當然有時候為了可讀性,我們可以將這些功能鍵以大寫字母來表示,例如 <C-d>
就表示 <Ctrl +d>
快捷鍵映射就是這么簡單,接下來要做的就是思考如何進行映射能提升我們的效率,即提取常用的操作將他們映射為快捷鍵。我們來通過幾個小例子來給小伙伴們提供一些思路。
定義 -為將當前行往下移動移動
我們知道,在普通模式下要將當前行往下移動,可以首先執行 dd
刪除一行,然后執行 p
來拷貝到下一行,因此我們可以這樣定義快捷鍵
:map - ddp
定義 _
為將當前行往上移動移動
在這個例子中,第一步仍然是執行刪除,但是與上一個例子不同的是,我們要將刪除部分往上一行粘貼。如果往上一行粘貼呢,在之前介紹的時候我們并沒有提到如何執行這么一個操作。如果你的第一反應是要去翻用戶手冊或者去查其他的資料,那么我建議你仔細去閱讀一下我之前寫的內容。體會一下vim的一些思想和技巧。
仔細回想一下 o
(小寫)和 O
(大寫) 的區別,而且我們曾經提到過,普通模式下,大寫字母和小寫字母功能類似。說到這我想你應該知道答案了。我們使用 P來粘貼到上一行。因此這里的映射可以寫成
:map _ ddP
如果你覺得這兩個映射對你有用,你可以將它放入你的 vimrc
中,或者先記下來,等我們介紹完使用 lua
配置之后,再寫到 init.lua
中。
其他模式下的映射
map
可以定義映射,但是各位小伙伴可以做一下試驗,map
命令定義的快捷鍵在 visual
模式下仍然有效。這樣就會帶來一個問題,如果我想在多個模式下都對 -
這個鍵進行了定義,而且定義成了不同的快捷鍵,這該怎么處理呢?
其實 vim
針對不同的模式有不同的快捷鍵定義命令,例如 :nmap
負責在普通模式下定義快捷鍵, :vmap
負責在 visual
模式下定義快捷鍵。這個時候你肯定已經猜到了,:imap
可以在插入模式下定義快捷鍵,或者使用 :cmap
定義命令行模式下的快捷鍵。
這些命令的格式與 :map
一樣。下面還是以例子為主吧
例1: 重新在普通模式下定義 -
例如我們使用 :nmap
重新定義 -
為 ddp
,這個時候我們發現它只在普通模式下有用,而在選擇模式下無效。
例2: 定義 <C-c><C-v>為復制粘貼
不知道有沒有小伙伴在初學vim的時候希望也能像在Windows中那樣,使用 <Ctrl+c>
和 <Ctrl+v>
來進行復制粘貼。學到現在我們終于有能力自己動手實現這個需求了。
雖然不推薦這么干,但是還是滿足各位折騰的欲望吧。
仔細回想一下,<Ctrl+c>
實際上是拷貝選中的文本,而<Ctrl+v>
是在輸入的時候直接粘貼的。因此我們知道映射 <Ctrl+c>
應該是在 可視模式下。而<Ctrl+v>
應該是在插入模式下。
另外在插入模式下是不支持使用 p
來進行粘貼的。還記得我們在插入模式下介紹的那些技巧嗎?其中有一個快速從寄存器中粘貼的技巧。正好可以在這里用到。而復制操作會將復制的文本拷貝到寄存器中(也就是 0
寄存器)。結合這兩個知識點,我們可以很方便的映射出這兩個快捷鍵
:vmap <C-c> y
:imap <C-v> <C-r>0
雖然它仍有一些不完美,但是已經夠用了。最后還是不推薦這么干,畢竟使用 y
等操作就能搞定的事情沒必要弄的這么麻煩。而且在linux平臺,特別是在終端上,這些鍵都另有用途。例如 <C-c>
在vim中可以退回到普通模式。
例3: 定義 <c-d>
為在插入模式下刪除一行
我們再舉一個例子,我想在插入模式下使用 <C-d>
來刪除光標所在行。vim
在插入模式下并沒有提供快捷鍵來刪除一行,需要使用退格鍵一個個的刪除,想要快速刪除可以回到普通模式使用dd
。那么我們可以使用 :imap <c-d> <esc>dd
。
我們會發現按下 <c-d>
之后它成功刪除了一行,但是它自己退回到普通模式去了,我們想要的是它能在刪除一行后仍然處于插入模式,這樣我們就可以直接輸入了,因此我們可以在后面新加一個再次進入插入模式的步驟,即 :imap <c-d> <esc>ddi
。
再次嘗試,我們發現它已經滿足我們的需求了。
例4: 在插入模式下定義快捷鍵快速轉換單詞為全大寫
我們定義一個在插入模式下能快速將光標所在單詞改為全大寫字母。例如 C/C++
語言的編程規范中都會講到宏或者常量最好以大寫字母命名。例如 #define MAX_CONNECTIONS_QUEUE 100
這樣長的宏定義,我們在輸入的時候要一直按著 shift
鍵是很痛苦的事情。我們需要有這么一個快捷鍵我們可以先輸入小寫字母然后使用快捷鍵將它改為全大寫。
首先我們思考一下,不使用快捷鍵該是如何操作呢?首先我們將光標移動到單詞所在位置并退回到普通模式,接著使用 viw選中,然后使用 U來改為大寫。
根據這一串操作命令,我們可以就知道了該如何定義快捷鍵了,:imap <c-u> <esc>viwU
。根據上面的一個例子我們知道,這樣它最終會停留在普通模式下面,我們還是希望能夠回到插入模式,考慮到我的使用場景是,我在寫完整個單詞之后會立馬將它轉化為大寫,然后再編輯后面的其他部分,因此我將光標移動到被大寫的單詞的尾部,并且進入插入模式。現在命令就變成了 :imap <c-u> <esc>viwUwa
。
這里你可以根據需要靈活的進行調整,例如可以改為 :imap <c-u> <esc>viwUA
,在行尾進入插入模式。
最后做一個總結。本篇提到的比較重要的定義快捷鍵的命令有:
- map: 定義所有模式下的通用快捷鍵
- imap: 定義插入模式下的快捷鍵 (insert)
- nmpa: 定義普通模式下的快捷鍵 (normal)
- vmap: 定義選擇模式下的快捷鍵 (visual)