May 24, 2021 Vim
This chapter explores another magical part of the Vim mapping system: the Operator-Pending mapping. Before we begin, let's explain the meaning of a few words in this.
An Operator is a command in which you can enter a Move command after the command, and Vim begins to execute the previous action command on the text, starting at your current location and ending where the move command will take you.
Operators that are commonly
d
y
and
c
For example:
按键 操作 移动
---- -------- -------------
dw 删除 到下一个单词
ci( 修改 在括号内
yt, 复制 到逗号
Vim allows you to create any new movements that work with all the commands. Execute the following command:
:onoremap p i(
Enter the following text in the buffer:
return person.get_pets(type="cat", fluffy_only=True)
Place the cursor on the word "cat" and tap
dp
W
hat happens as a result? V
im deletes all text in parentheses.
You can use this new movements as an "argument".
onoremap
command tells Vim that when it is waiting for a movement to be attached to the back of the operator, if the
p
it will treat it
i(
.
So when
dp
it's like saying "delete parameters" to Vim, which Vim will understand as "delete in parentheses."
We can now immediately use this new mapping for all operators. Enter the above text again in the buffer (or restore the previous modifications directly).
return person.get_pets(type="cat", fluffy_only=True)
Place the cursor on the word "cat" and tap
cp
W
hat's going to happen this time?
Vim deletes all text in parentheses, but after this deletion Vim is in insert mode because you're using "change" instead of "delete."
Let's look at another example. Execute the following command:
:onoremap b /return<cr>
Now enter the following text into the buffer:
def count(i):
i += 1
print i
return foo
Place the cursor on the second
i
and press
db
. I
s it going to happen?
Vim removes the entire function body
return
above
return
result of the mapping above using Vim's generic lookup.
As you figure out how to define a new operator-pending movement, here are a few steps to think about:
All you have to do is fill in the right buttons in the third step.
You may have realized a problem from what you have learned above. If we define a movements that start where the cursor is located, then this limits us to doing what we want to do with movement.
But Vim doesn't limit you from doing what you want to do, so there's definitely a solution to the problem. Execute the following command:
:onoremap in( :<c-u>normal! f(vi(<cr>
The command may seem complicated, but let's try what it does first. Enter the following text into the buffer:
print foo(bar)
Place the cursor over the word
print
and tap
cin(
.
Vim removes the contents of the parenthesis and goes into insertion mode, and the cursor stays in the middle of the parenthesis.
You can understand this mapping as "inside the next parentheses". It executes the objector on the text in the next parenthesis where the current line cursor is located.
Let's also create a "inside last parentheses" movement for comparison. (It may be more accurate to use "previous" here, but it overrides the "paragraph" movement)
:onoremap il( :<c-u>normal! F)vi(<cr>
Try making sure this command works first.
So how do these maps work? F
irst of
<c-u>
special to be able to do it first (you just have to trust me to make this mapping work under any circumstances).
If we delete it, this mapping will look like this:
:normal! F)vi(<cr>
:normal!
A
s you'll see later in the chapter, now you just need to know that it simulates pressing a button in a common mode. F
or example,
:normal! dddd
two lines, just like pressing
dddd
T
he mapping is followed by the
<cr>
is used to
:normal!
Commanded.
So now we can think that the key to this mapping is to run the commands made up of these keys:
F)vi(
This is fairly simple: This command is easy to understand:
F)
Moves back to the
)
character.
vi(
: Enter visual mode to select everything in parentheses.
This movement ends with the text we want to manipulate in visual mode, and then Vim takes action on the selected text, as is often the case.
The following two rules allow you to create an operator-pending map in a number of ways that are intuitive:
Create an operator-pending map for "around next parentheses" and "around last parentheses"
Create a similar in/around next/last mappings for parentheses.
Read
:help omap-info
to see if you can figure out what you're
<c-u>
doing.