这一章我们将来探索Vim映射系统中另外一个神奇的部分:“Operator-Pending映射”。开始之前,我们先解释下这里面的几个词含义。
一个Operator(操作)就是一个命令,你可以在这个命令的后面输入一个Movement(移动)命令,然后Vim开始对文本执行前面的操作命令,这个操作命令会从你当前所在的位置开始执行,一直到这个移动命令会把你带到的位置结束。
常用到的Operator有d
,y
和c
。例如:
按键 操作 移动
---- -------- -------------
dw 删除 到下一个单词
ci( 修改 在括号内
yt, 复制 到逗号
Vim允许你创建任何新的movements,这些movements可以跟所有命令一起工作。执行下面的命令:
:onoremap p i(
在缓冲区中输入下面的文字:
return person.get_pets(type="cat", fluffy_only=True)
把光标放到单词“cat”上,然后敲击dp
。结果会发生什么?Vim会删除括号内的所有文字。你可以把这个新建的movements当作“参数”。
onoremap
命令会告诉Vim当它在等待一个要附加在operator后面的movement的时候,如果这个movement是p
的话,它会把它当作i(
。所以当我们在运行dp
的时候,就象是在对Vim说“delete parameters”,而Vim会把它理解为“在括号内删除”。
我们现在可以立马对所有的operators使用这个新建的映射。再次在缓冲区中输入上面的文字(或者直接把之前修改恢复一下)。
return person.get_pets(type="cat", fluffy_only=True)
把光标放到单词“cat”上,然后敲击cp
。这次又会发生什么?Vim会删除括号中的所有文字,不过这一次删除之后Vim会处于插入模式,这是因为你使用的是“change”,而不是“delete”。
再看一个示例。执行下面的命令:
:onoremap b /return<cr>
现在把下面的文字输入到缓冲区:
def count(i):
i += 1
print i
return foo
把光标放到第二行的i
上,然后按下db
。会发生生么?Vim把整个函数体中直到return
上面的内容都删除了,return
就是上面的映射使用Vim的通用查找得到的结果。
当你想搞清楚怎么定义一个新的operator-pending movement的时候,你可以从下面几个步骤来思考:
你所要做的工作就是在第三步中填上合适的按键。
你可能已经从上面所学的东西中意识到一个了问题。如果我们定义的movements都是从光标所在的位置开始的话,那么这就会限制我们做一些我们想使用movement来做的事情。
但是Vim并不会限制你去做你想做的事情,所以对于这个问题肯定有解决办法。执行下面的命令:
:onoremap in( :<c-u>normal! f(vi(<cr>
这个命令看起来有些复杂,不过我们还是先试试它能干什么。将下面的文字输入缓冲区:
print foo(bar)
把光标放到单词print
上面,然后敲击cin(
。Vim会删除括号内的内容然后进入插入模式,并且光标会停留在括号的中间。
你可以将这个映射理解为“在下一个括号内(inside next parentheses)”。它会对当前行光标所在位置的下一个括号内的文本执行operator。
我们再创建一个“在上一个括号内(inside last parentheses)”的movement进行对照。(在这里使用“前一个(previous)“可能更准确,但这会覆盖“段落(paragraph)”movement)
:onoremap il( :<c-u>normal! F)vi(<cr>
先试试确保这个命令可以工作。
那么这些映射是怎么工作的呢?首先,<c-u>
比较特殊,可以先不用管(你只需要相信我这个东西可以让这个映射在任何情况下都能正常工作)。如果我们删除它的话,这个映射会变成这个样子:
:normal! F)vi(<cr>
:normal!
会在后面的章节谈到,现在你只需要知道它可以在常用模式下模拟按下按键。例如,运行:normal! dddd
会删除两行,就像按下dddd
。映射后面的<cr>
是用来执行:normal!
命令的。
那么现在我们可以认为这个映射的关键是运行下面这些按键组成的命令:
F)vi(
This is fairly simple: 这个命令很容易理解:
F)
: 向后移动到最近的)
字符。vi(
: 进入可视模式选择括号内的所有内容。这个movement结束在在可视模式下选择中我们想操作的文本,然后Vim会对选中的文本执行操作,就像通常情况一样。
下面两条规则可以让你可以很直观的以多种方式创建operator-pending映射:
为"around next parentheses"和"around last parentheses"创建operator-pending映射
为打括号创建类似的in/around next/last的mappings。
阅读:help omap-info
,看看你可不可以搞清楚<c-u>
是干啥的。
SVG line line 元素用于绘制直线;它取两个点的位置作为属性,指定这条线的起点和终点位置。SVG 直线 - line line 元素是用来创...
XSL-FO region-body 对象XSL-FO 参考手册使用 XSL-FO 的时候,一个页面的主体区域是通过 region-body对象定义的。 定义和用法 fo...
XSL-FO single-page-master-reference 对象XSL-FO 参考手册定义和用法 fo:single-page-master-reference 对象为用在页面序列的给...
XSL-FO keep-with-next 属性 XSL-FO 参考手册定义和用法 keep-with-next属性在XSL-FO对象中创建keep-with-next 条件。详情继承性...
XML Schema any 元素 完整 XML Schema 参考手册定义和用法 any 元素使创作者可以通过未被 schema 规定的元素来扩展 XML 文档。 ...