Why does Vim's U command work differently when lines are changed vs deleted?

Viewed 111

I'm trying to understand the U command in Vim. My understanding is that it undoes all changes that affect only the most recently changed line. However, if I start with the following file:

abc
def
ghi

jxx navigates down and deletes two characters:

abc
f
ghi

kgU2j sets the entire document to uppercase:

ABC
F
GHI

Now, U gives this result:

ABC
def
GHI

If I had used kd2j to delete the entire document instead of changing its case, U would have no effect. I'm wondering why d is treated as a command that affects multiple lines, but gU is seemingly ignored.

Is there an intuitive way to understand this behavior, or is this just an odd edge case of Vim?

1 Answers

To understand this behaviour I decided to dig into the source code and the things I found:

In your case, you removed one letter from second line. Current line (and the state before the change) was updated. When you deleted next character, you did it in the already stored line, so current line nor state were updated. Next change touched 3 lines - no updates. U restored current line to saved state. Notice that gUG on the last line would touch only it, so that change updates current line and state under the hood.

This can move current line up (deleting) or down (adding). It's much easier to clear it instead of handling logic of moving it and that's my guess why it's done such way.

Notice that deleting part of line (e.g. with d$) will update current line and state as expected. Opening line with o and type some text (current line is that line, state is empty line) works too. However when you press enter during typing (so affect more than one line), current line is cleared.

Related