The 29th Saltshaker
The 29th Saltshaker

Reputation: 691

Trying to understand the logic of deletions in Vim

I Googled this but was unable to find any clear explanation.

A lot of people praise Vim for sort of being its own internally consistent language but I am failing to see the consistency.

Since hjkl are left down up right:

dh is like "delete left" and it deletes the character to the left of the cursor, makes sense so far.

dl is like "delete right" but it deletes... the current character?

dj is like "delete down" and I'd assume this just deletes the line below, but it actually deletes the current line as well!

'dk' is like "delete up" and similarly I'd expect it just clears the line above, but instead it clears the current line AND the one above it.

Can anyone explain what the logic is here? I am okay with the idea of delete + left and right handling characters on the same line, and delete + up and down handling lines, but why is the behavior so inconsistent? What's the logic I am missing here?

Or is it really more of a "there is no consistent logic here really, just memorize it" thing?

Upvotes: 5

Views: 1268

Answers (2)

B.G.
B.G.

Reputation: 6016

This is consistent. Think about it as a textcursor, not as a block cursor so for example:

abc
 ^

You are here with the cursor. For the delete command it is actually like this:

a|bc

Vim always works with ranges. If you do not specify a range, only a target, the first point of the range is always the cursor position: So dh is delete from here to h, with h being the following position:

|abc

So you tell vim to delete from a|bc to |abc hence everything between the cursor positions is deleted.

dl goes to the other direction from a|bc to ab|c -> a|b|c so only the b will be deleted.

In j and k movements, it is line-based, but basically the same.

So if you press dk on the following situation:

abc

abc
 ^

You tell vim to delete every line until you reach the following position:

abc
 ^
abc

This is consistent with all other commands in vim, and is a part of what makes vim so powerful. Think about the search / command for example:

 abc
 a|bc
 abc
 dfe
 dfe 
 dfe

If you press d/dfe<CR> it will not just delete dfe, it will delete until dfe. So you will have following two cursor positions:

 abc
 a|bc
 abc
 |dfe    
 dfe 
 dfe

Everything in between will be deleted, you will end up with:

 abc
 a
 dfe    
 dfe 
 dfe

This is the case for every other movement.

Upvotes: 7

romainl
romainl

Reputation: 196456

You shouldn't "assume" or "expect" anything. The behavior of all those commands is explained precisely in Vim's online documentation.

hjkl are motions and d is an operator that works on the text covered by a motion.

  • dj works on the text covered by the j motion. Since j is a linewise motion that moves the cursor to the line below, dj is "cut this line and the one below".

  • dk works on the text covered by the k motion. Since k is a linewise motion that moves the cursor to the line above, dk is "cut this line and the one above".

For horizontal motions, you must understand that the terminal's cursor is actually between two characters:

sample text:                lorem

the "current character":    lorem
                              ^

the "cursor":               lo|rem

the text covered by "h":    l|orem
                              ←

the text covered by "l":    lor|em
                              →
  • dh works on the text covered by the h motion so it cuts the character before the "cursor" which happens to also be the character before the "current character".

  • dl works on the text covered by the l motion so it cuts the character after the "cursor" which happens to be the "current character".

Upvotes: 1

Related Questions