Coding With Fun
Home Docker Django Node.js Articles Python pip guide FAQ Policy

Vimscript Operator-Pending mapping


May 24, 2021 Vim


Table of contents


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,    复制       到逗号

Movement map

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:

  1. Start where the cursor is located.
  2. Go into visual mode (charwise).
  3. ... Put the mapped keys here ...
  4. All text you want to include in movement will be selected.

All you have to do is fill in the right buttons in the third step.

Change the start position

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.

General rules

The following two rules allow you to create an operator-pending map in a number of ways that are intuitive:

  • Vim manipulates the text if your operator-pending map ends Chinese selected in visual mode.
  • Otherwise, Vim manipulates the text from the original position of the cursor to a new location.

Practice

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.