Question regarding :normal

123 views
Skip to first unread message

Quinn Strahl

unread,
Aug 26, 2015, 12:17:44 AM8/26/15
to vim_dev
A difference in behaviour between :g and :<range>normal recently frustrated me, and I wonder if it's up for debate:

:g does a pass on matching lines and marks them before performing the operation; this allows it to be generally undeterred by operations that include addition/deletion of lines.

:<range>normal does not do this, and as a result, it can get "thrown off" by such operations. For (a trivial) example, on the hypothetical file:

foo
bar
baz

Performing :1,3normal yyp would produce the following result:

foo
foo
foo
foo
bar
baz

Whereas the more intuitive result would be:

foo
foo
bar
bar
baz
baz

There does exist a workaround, in the form of :<range>g/^/normal yyp -- simply using :g in a way guaranteed to match every line in the desired range -- but this is a bit of a compositional kludge.

Would it be feasible to add the marking behaviour of :g to :normal, or is that not worth implementing / a feature?

Justin M. Keyes

unread,
Aug 26, 2015, 1:31:34 AM8/26/15
to vim...@googlegroups.com
Why do you want them to behave the same? They serve different
purposes. Or rather, :g serves a purpose, and :normal is behaving in
the typical way for a range command that performs edits/changes.


Justin M. Keyes

Quinn Strahl

unread,
Aug 26, 2015, 9:40:10 AM8/26/15
to vim_dev

I have on many occasions run into situations where it would be very handy if :normal worked the way :g does with respect to how it handles changes in number of lines during operation, and I have not run into any case (nor can I imagine one) where the current behaviour is favourable. It seems less intuitive and less useful for it to behave this way.

Charles Campbell

unread,
Aug 26, 2015, 12:15:44 PM8/26/15
to vim...@googlegroups.com
Why not use

:[range]g/pattern/norm whatever

Regards,
Chip Campbell

Quinn Strahl

unread,
Aug 26, 2015, 1:32:27 PM8/26/15
to vim_dev, Charles.E...@nasa.gov

That's the workaround I'm using right now, but there are many cases where I want to operate on every line in the range, forcing me to use something like my previous example:

:<range>g/^/norm whatever

It feels hacky; I'm essentially trying to avoid what is arguably the primary function of :g (matching a subset of lines) just to get that line-marking behaviour for the :normal operation. It makes me wonder, is there any reason for :normal to lack that behaviour? It seems like an objective improvement.

Quinn Strahl

unread,
Aug 27, 2015, 12:02:42 PM8/27/15
to vim_dev, Charles.E...@nasa.gov
I was just reminded of another little grievance I have with :g/^/norm -- it sets the last search pattern to /^/, a very unintended side-effect.

Christian Brabandt

unread,
Aug 27, 2015, 3:19:32 PM8/27/15
to vim_dev
Hi Quinn!

On Do, 27 Aug 2015, Quinn Strahl wrote:

> I was just reminded of another little grievance I have with :g/^/norm -- it sets the last search pattern to /^/, a very unintended side-effect.

But that is what :g is for.


Best,
Christian
--
Neue Meldungen von Windows 2000:
Netscape.exe. Falscher Dateiname. Systemintegrität verletzt.
Internet-Explorer wird installiert.

Gary Johnson

unread,
Aug 27, 2015, 3:45:27 PM8/27/15
to vim_dev
On 2015-08-27, Christian Brabandt wrote:
> Hi Quinn!
>
> On Do, 27 Aug 2015, Quinn Strahl wrote:
>
> > I was just reminded of another little grievance I have with
> > :g/^/norm -- it sets the last search pattern to /^/, a very
> > unintended side-effect.
>
> But that is what :g is for.

Yes, but Quinn's point is that it wouldn't be necessary to use :g
and a dummy pattern if :normal worked the way that :g does, that is,
if ":{range}normal {commands}" first marked the lines in {range},
then went back and executed {commands} on those marked lines.

Regards,
Gary

Christian Brabandt

unread,
Aug 28, 2015, 7:47:24 AM8/28/15
to vim_dev
Okay, I can understand that. So here is a patch.

It is a little bit tricky, since if you simply mark the lines while a :g
command is running, this would cancel your :g command (because we need
to clear the marks once the :normal is done). So here is an approach,
that only marks the lines, if no :g command is running, else we fall
back to the old behaviour.

E.g. for this file
1
2

This is a bit a silly example, but it explains my point:
:g/^/1,2norm! yyp
will still behave like the old behaviour (since we can't mark the lines,
as then after the :norm! finishes all marks for the :g would be gone)
e.g. result in:
1
1
1
1
1
2

But :g/^/norm yyp and :%norm! yyp will result in

1
1
2
2

Included in the patch is a test and updated documentation.


Best
Christian
--
Stilblüten aus Schreiben von Versicherungsnehmern:
Der Unfall ist dadurch entstanden, daß der Volkswagen weiterfuhr. Er
mußte verfolgt werden, ehe er schließlich anhielt. Als wir ihm eine
Tracht Prügel verabreichten, geschah es.
normal_marked.diff

Justin M. Keyes

unread,
Aug 28, 2015, 6:46:00 PM8/28/15
to vim...@googlegroups.com

Use

:keeppatterns g/^/...

to avoid setting @/.

Quinn Strahl

unread,
Aug 31, 2015, 10:12:53 AM8/31/15
to vim_dev

*Of course* there is a command for that. :)

Thank you, Justin, and thank you, Christian. Between a patch and a workaround I don't think I could ask for a better response.

Cheers!

Reply all
Reply to author
Forward
0 new messages