For deleting a range of lines, I know we can use :3,15d and it works. But if we try to run the same command using normal command (:3,15 normal dd), it behaves erratic and deletes some random blocks/lines in 3,15 range. Could anyone explain if this is a bug?
1 Answer
:norm
iterates over lines with specific addresses, not over lines with specific marks.
Suppose you have this file:
line 1
line 2
line 3
line 4
line 5
line 6
And you execute :2,4norm! dd
.
You probably expect getting this file:
line 1
line 5
line 6
But in reality, you'll get this file:
line 1
line 3
line 5
First, :norm
executes the dd
command on the line whose address is 2
; at that point, the file contains:
line 1
line 3
line 4
line 5
line 6
Then, :norm
executes the dd
command on the line whose address is 3
. But since :norm
has removed a line in the previous step, all the addresses of the lines below the deleted line have decreased by 1.
So the line of address 3
is not the one containing the text line 3
anymore, but the one containing the text line 4
; and :norm
deletes the latter; at that point, the file contains:
line 1
line 3
line 5
line 6
Finally, :norm
executes the dd
command on the line whose address is 4
. But again, since :norm
has removed 2 lines in the previous steps, all the addresses of the subsequent lines have decreased by 2; and the line of address 4
is not the one containing the text line 4
anymore, but the one containing the text line 6
; :norm
deletes the latter and the file finally contains:
line 1
line 3
line 5
If for some reason, you really want to use :norm! dd
, combine it with :g
which contrary to :norm
does mark the lines on which it operates before executing its command argument:
:3,15g/^/norm! dd
Or try to reverse the order of the deletions:
:call map(reverse(range(3, 15)), {_,v -> execute(v.'norm! dd')})
Always append a bang to :norm
, unless you really want your custom mappings to be taken into account.
If your file is folded, make sure folding is temporarily disabled; execute :setl nofen
before the deletions, then :setl fen
afterward.