这个章节我们继续来探索vim映射的神奇功能:“操作符-区间 映射”,让我们先来弄懂这个名词的意义,然后在使用他。
一个操作符是一个等待你来输入一个移动命令的命令,然后对你当前位置到移动后的位置之间的文本做操作。
常见的操作符有d,y,c。例如:
Operator
vvvvvv
dw " Delete to next word
ci( " Change inside parents
yt, " Yank until comman
^^^^^^^^
Movement
在vim里,你创建的移动命令可以和所有现存的命令配合使用。运行下面的命令:
:onoremap p i(
现在把下面的文本输入到vim里:
return person.get_pets(type="cat",fluffy_only=True)
把光标放在“cat”上,然后输入dp,会发生什么呢?vim会删除括号里的文本。你可以认为这里面的动作是“选中参数”。
上面的 onoremap 命令让vim是告诉vim当他在等待一个动作时,如果输入了p,那么就把它映射成i(。当我们输入dp的时候,就像是在说“删除参数”一样,对vim而言就是“删除括号里的内容”。
我们可以对所有的命令使用这种新映射方式,把之前的文本再次输入vim:
return person.get_pets(type="cat", fluffy_only=True)
把光标放在“cat”上,然后输入cp,这次又发生了什么呢?Vim还是会删除括号里的文本,不同的是这次vim会停留在inset模式,因为你用了“替换”命令,而不是“删除”命令。
下面我们看看另外一个例子,运行下面的命令:
:onoremap b /return<cr>
现在在vim里输入以下文本:
def count(i):
i += 1
print i
return foo
把光标移动到第二行的i上面,然后按下db。会出现什么呢?Vim会删除函数体里的内容,一直到“return”语句,这是因为我们的映射使用了vim的normal模式下的搜索。
当你在考虑怎么来定义一个新的操作符-区间的动作时,你可以按照下面的思路来考虑:
你要做的是把第三步替换成你想要的功能。
对于我们之前学习的功能,你可能发现了一个问题,如果我们的操作只能从当前位置开始的话,这样会限制我们想要做的。
不过Vim并不会限制我们能过什么,所以这个问题还是有办法来解决的。运行下面的命令:
:onoremap in( :<c-u>normal! f(vi(<cr
这个命令看起来很难,不过我们可以先试试这个命令。把下面的文本输入到vim里:
print foo(bar)
把你的光标移动到单词“print”的任何位置上,然后输入cin(。Vim会删除括号里的内容,然后把你的光标放在中间,并且是处于insert模式下。
你可以把这个映射当做“在下一个括号里”,它会对当当前行的下一个括号里的内容执行操作符所对应的操作。
接下来我们来做一个和上面相对的命令“在上一个括号里面”。运行下面的命令:
:onoremap il( :<c-u>normal! F)vi(<cr>
你自己可以输入一些文本来测试上面的映射,确保它确实有效。
那么这个映射到底是怎么工作的呢?首先,:normal! F)vi(<cr>
:normal!使我们后面将会讨论的一个命令,现在只需要知道它的功能是模拟在normal模式下按下键盘。例如:normal! dddd会删除两行文本,就像按下dddd一样。末尾的
所以排除上面的那些命令,就只剩下
F)vi(
现在就变得很简单了:
最后我们在visual模式下选中了我们要操作的文本,vim接着就会执行我们指定的操作。
操作符-区间 映射的创建方式多种多样,记住下面两条准则可以帮助你方便的来创建操作符-区间映射: