martanne / vis

A vi-like editor based on Plan 9's structural regular expressions
Other
4.21k stars 258 forks source link

modifying multiple selections with :c/&.../ duplicates the last modified selection instead #934

Open hyphenrf opened 3 years ago

hyphenrf commented 3 years ago
pattern0
pattern1
pattern2

select some pattern with :x/pattern[0-3]/ modify it in a generic way with :c/modified-&/ the result is:

modified-pattern0
modified-pattern0
modified-pattern0

instead of the original 1,2,3 sequence

Is this a bug or the expected behaviour and I'm using the wrong sre command?

7v0lk0v commented 3 years ago

I've noticed this as well in other use cases, the common denominator is running the commands separately ie. if you do it all in one line it works fine.

x/pattern-[0-3]/c/modified-& works

so I guess it's a bug from the user perspective but I suspect the implementation just doesn't want to store potentially 1000s of matches in case they may be referenced in a later command; whereas when it's a single command it does the substitution as it comes across each match (which makes sense so is not strictly a bug and has a simple work around though it does catch me every now and then).

aksr commented 3 years ago

For me, it's a bug. & doesn't work as expected.

hyphenrf commented 3 years ago

I suspect the implementation just doesn't want to store potentially 1000s of matches in case they may be referenced in a later command

I see.. My understanding was, since the selections are highlighted, at least cursor positions and lengths are stored somewhere in program memory.. and since you can further refine selections by issuing extra x/.../ commands, that c/.../ should be able to iterate over those already-stored selections in a similar fashion.

7v0lk0v commented 3 years ago

hmm yea you're right. In that case there might be an easy fix specifically for the & case (as opposed to \1).

martanne commented 3 years ago

As has been pointed out, the reason for this behavior is that we do not associate the capture groups with the selections, but only update the corresponding register values for each match of the x loop. Fixing this even just for & won't work without increasing memory usage. The resulting selection might not be the same as the initial match (e.g. for x/pattern/ +- which selects all lines matching pattern).

Contrary to the initial report, the result is

modified-pattern2
modified-pattern2
modified-pattern2

i.e. the capture group of the last x match is saved and used.

Like #925 this is another case where commands have a different effect when broken up into individual parts vs issued at once.

hyphenrf commented 3 years ago

ah - it really is the last match not the first one. That wasn't apparent to me at the time of reporting because the selection that made me first encounter this was terminal, no variances, sorry. I should correct the title just in case someone later searched for this issue