Let's start with investigating some motions in vi(m). I use the sample line
AA BBB
as subject of these investigations, and for each experiment we are starting off in normal mode, cursor at beginning of line. The experiments will end up also in normal mode, and I'm adding an enclosing rX
action to indicate the final cursor position.
So see these four movements: tB
, fB
, w
, 3l
. The first one moves the cursor to the space preceding BBB
, the others to the first B
. That is,
tBrX # AAXBBB
fBrX # AA XBB
wrX # AA XBB
3lrX # AA XBB
Now let's see what the doc says about performing these moves in deletion context:
Vim:
d{motion} Delete text that {motion} moves over
FreeBSD vi(1) man page:
d motion Delete the region of text described by ... motion
So these express a simple and clear concept, the composition of deletion and movement. At this point almost everything seems to be clear, except maybe whether the deletion range is inclusive or exclusive, ie. whether the position we end up by the movement is deleted or kept.
If it were exclusive, prefixing the above actions with d
should just delete everything up to the X
:
dtBrX # XBBB
dfBrX # XBB
dwrX # XBB
d3lrX # XBB
If it were inclusive, the position that is indicated with the X
above gets also deleted, so the final position is the followup one, ie. one more character would be devoured, thus we were to get:
dtBrX # XBB
dfBrX # XB
dwrX # XB
d3lrX # XB
Now let's see how it is in real life:
dtBrX # XBB
dfBrX # XB
dwrX # XBB
d3lrX # XBB
That is, the composition is inclusive for the first two movements, but exclusive for the latter two! I wonder is there any principle that can explain this?
Also, there is c
, which is described in Vim doc as Delete {motion} text and start insert
. I expect it, from the spec, that if we go back to normal mode after c
: c{motion}<ESC>l
, that has the same effect as d{motion}
(as discussed in Why does `ESC` move the cursor back in vim?, <ESC>
has the effect of moving the cursor left, so we need an l
to compensate if we want to keep position through normal / insert mode roundtrips). Well, almost:
ctB<ESC>lrX # XBB
cfB<ESC>lrX # XB
cw<ESC>lrX # XBBB
c3l<ESC>lrX # XBB
... just c
combined with w
has a different effect: this operation keeps even the space preceding BBB
, that is, the character preceding the destination of the movement! What's the logic behind this behavior?