W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
這一章我們將來(lái)探索Vim映射系統(tǒng)中另外一個(gè)神奇的部分:“Operator-Pending映射”。開(kāi)始之前,我們先解釋下這里面的幾個(gè)詞含義。
一個(gè)Operator(操作)就是一個(gè)命令,你可以在這個(gè)命令的后面輸入一個(gè)Movement(移動(dòng))命令,然后Vim開(kāi)始對(duì)文本執(zhí)行前面的操作命令,這個(gè)操作命令會(huì)從你當(dāng)前所在的位置開(kāi)始執(zhí)行,一直到這個(gè)移動(dòng)命令會(huì)把你帶到的位置結(jié)束。
常用到的Operator有d
,y
和c
。例如:
按鍵 操作 移動(dòng)
---- -------- -------------
dw 刪除 到下一個(gè)單詞
ci( 修改 在括號(hào)內(nèi)
yt, 復(fù)制 到逗號(hào)
Vim允許你創(chuàng)建任何新的movements,這些movements可以跟所有命令一起工作。執(zhí)行下面的命令:
:onoremap p i(
在緩沖區(qū)中輸入下面的文字:
return person.get_pets(type="cat", fluffy_only=True)
把光標(biāo)放到單詞“cat”上,然后敲擊dp
。結(jié)果會(huì)發(fā)生什么?Vim會(huì)刪除括號(hào)內(nèi)的所有文字。你可以把這個(gè)新建的movements當(dāng)作“參數(shù)”。
onoremap
命令會(huì)告訴Vim當(dāng)它在等待一個(gè)要附加在operator后面的movement的時(shí)候,如果這個(gè)movement是p
的話,它會(huì)把它當(dāng)作i(
。所以當(dāng)我們?cè)谶\(yùn)行dp
的時(shí)候,就象是在對(duì)Vim說(shuō)“delete parameters”,而Vim會(huì)把它理解為“在括號(hào)內(nèi)刪除”。
我們現(xiàn)在可以立馬對(duì)所有的operators使用這個(gè)新建的映射。再次在緩沖區(qū)中輸入上面的文字(或者直接把之前修改恢復(fù)一下)。
return person.get_pets(type="cat", fluffy_only=True)
把光標(biāo)放到單詞“cat”上,然后敲擊cp
。這次又會(huì)發(fā)生什么?Vim會(huì)刪除括號(hào)中的所有文字,不過(guò)這一次刪除之后Vim會(huì)處于插入模式,這是因?yàn)槟闶褂玫氖恰癱hange”,而不是“delete”。
再看一個(gè)示例。執(zhí)行下面的命令:
:onoremap b /return<cr>
現(xiàn)在把下面的文字輸入到緩沖區(qū):
def count(i):
i += 1
print i
return foo
把光標(biāo)放到第二行的i
上,然后按下db
。會(huì)發(fā)生生么?Vim把整個(gè)函數(shù)體中直到return
上面的內(nèi)容都刪除了,return
就是上面的映射使用Vim的通用查找得到的結(jié)果。
當(dāng)你想搞清楚怎么定義一個(gè)新的operator-pending movement的時(shí)候,你可以從下面幾個(gè)步驟來(lái)思考:
你所要做的工作就是在第三步中填上合適的按鍵。
你可能已經(jīng)從上面所學(xué)的東西中意識(shí)到一個(gè)了問(wèn)題。如果我們定義的movements都是從光標(biāo)所在的位置開(kāi)始的話,那么這就會(huì)限制我們做一些我們想使用movement來(lái)做的事情。
但是Vim并不會(huì)限制你去做你想做的事情,所以對(duì)于這個(gè)問(wèn)題肯定有解決辦法。執(zhí)行下面的命令:
:onoremap in( :<c-u>normal! f(vi(<cr>
這個(gè)命令看起來(lái)有些復(fù)雜,不過(guò)我們還是先試試它能干什么。將下面的文字輸入緩沖區(qū):
print foo(bar)
把光標(biāo)放到單詞print
上面,然后敲擊cin(
。Vim會(huì)刪除括號(hào)內(nèi)的內(nèi)容然后進(jìn)入插入模式,并且光標(biāo)會(huì)停留在括號(hào)的中間。
你可以將這個(gè)映射理解為“在下一個(gè)括號(hào)內(nèi)(inside next parentheses)”。它會(huì)對(duì)當(dāng)前行光標(biāo)所在位置的下一個(gè)括號(hào)內(nèi)的文本執(zhí)行operator。
我們?cè)賱?chuàng)建一個(gè)“在上一個(gè)括號(hào)內(nèi)(inside last parentheses)”的movement進(jìn)行對(duì)照。(在這里使用“前一個(gè)(previous)“可能更準(zhǔn)確,但這會(huì)覆蓋“段落(paragraph)”movement)
:onoremap il( :<c-u>normal! F)vi(<cr>
先試試確保這個(gè)命令可以工作。
那么這些映射是怎么工作的呢?首先,<c-u>
比較特殊,可以先不用管(你只需要相信我這個(gè)東西可以讓這個(gè)映射在任何情況下都能正常工作)。如果我們刪除它的話,這個(gè)映射會(huì)變成這個(gè)樣子:
:normal! F)vi(<cr>
:normal!
會(huì)在后面的章節(jié)談到,現(xiàn)在你只需要知道它可以在常用模式下模擬按下按鍵。例如,運(yùn)行:normal! dddd
會(huì)刪除兩行,就像按下dddd
。映射后面的<cr>
是用來(lái)執(zhí)行:normal!
命令的。
那么現(xiàn)在我們可以認(rèn)為這個(gè)映射的關(guān)鍵是運(yùn)行下面這些按鍵組成的命令:
F)vi(
This is fairly simple: 這個(gè)命令很容易理解:
F)
: 向后移動(dòng)到最近的)
字符。vi(
: 進(jìn)入可視模式選擇括號(hào)內(nèi)的所有內(nèi)容。這個(gè)movement結(jié)束在在可視模式下選擇中我們想操作的文本,然后Vim會(huì)對(duì)選中的文本執(zhí)行操作,就像通常情況一樣。
下面兩條規(guī)則可以讓你可以很直觀的以多種方式創(chuàng)建operator-pending映射:
為"around next parentheses"和"around last parentheses"創(chuàng)建operator-pending映射
為打括號(hào)創(chuàng)建類似的in/around next/last的mappings。
閱讀:help omap-info
,看看你可不可以搞清楚<c-u>
是干啥的。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: