Wish: enable :subst-expr with 'n' flag

0 views
Skip to first unread message

Andy Wokula

unread,
Jan 9, 2008, 7:52:35 AM1/9/08
to vim...@googlegroups.com
I tried to write a function that collects all the matches for a given
pattern in the text.

For that purpose, it would be very nice if the following worked:
:%s/{pattern}/\=MyAddMatch(submatch(0))/gn

but it doesn't, because the "n" flag disables evaluation of the
expression after '\='.

IMHO the "n" flag should only ignore the result of the expression.

--
Andy

ap

unread,
Jan 9, 2008, 11:28:47 AM1/9/08
to vim_dev


On Jan 9, 1:52 pm, Andy Wokula <anw...@yahoo.de> wrote:
> I tried to write a function that collects all the matches for a given
> pattern in the text.
>
> For that purpose, it would be very nice if the following worked:
> :%s/{pattern}/\=MyAddMatch(submatch(0))/gn

Remove the 'n' and let MyAddMatch() return submatch(0).
Not very eficient, but easy.
I am sorry if that is beside your point.


>
> but it doesn't, because the "n" flag disables evaluation of the
> expression after '\='.
>
> IMHO the "n" flag should only ignore the result of the expression.
>
> --
> Andy

-ap

Andy Wokula

unread,
Jan 9, 2008, 12:06:40 PM1/9/08
to vim...@googlegroups.com
ap schrieb:

>
> On Jan 9, 1:52 pm, Andy Wokula <anw...@yahoo.de> wrote:
>> I tried to write a function that collects all the matches for a given
>> pattern in the text.
>>
>> For that purpose, it would be very nice if the following worked:
>> :%s/{pattern}/\=MyAddMatch(submatch(0))/gn
>
> Remove the 'n' and let MyAddMatch() return submatch(0).
> Not very eficient, but easy.
> I am sorry if that is beside your point.

Yeah, this could be accepted as a workaround.

but: it doesn't work safely in all situations (e.g. ambigious NUL
characters in the returned string).

Also it would unnecessarily change the buffer (ugly in readonly
buffers) and add useless undo information.



>> but it doesn't, because the "n" flag disables evaluation of the
>> expression after '\='.
>>
>> IMHO the "n" flag should only ignore the result of the expression.
>>
>> --
>> Andy
>
> -ap

--
Andy

ap

unread,
Jan 10, 2008, 10:46:09 AM1/10/08
to vim_dev


On Jan 9, 6:06 pm, Andy Wokula <anw...@yahoo.de> wrote:
> I tried to write a function that collects all the matches for a given
> pattern in the text.
>
> For that purpose, it would be very nice if the following worked:
> :%s/{pattern}/\=MyAddMatch(submatch(0))/gn


I agree, this could be easier.

Doing it with search() seems a bit tricky.

-it needs 2 calls to search()
-the startposition needs special care
( there could be a match in the first column of
the first line one wants to search )

----------%<------------------
"Could be improved by handling the startpos differently
"and avoid the 3rd search.
func! CollectWords( pat, first_line, last_line )
let result = []
call cursor(a:first_line,1)
while search(a:pat,'cW',a:last_line)
normal! ms
call search(a:pat,'ceW')
normal! me
normal! `sv`ey
call add(result,@")
call search('.','W')
endwhile
return result
endfun
----------%<------------------


Maybe someone has a better idea, apart from source modification.

-ap


Andy Wokula

unread,
Jan 10, 2008, 1:43:09 PM1/10/08
to vim...@googlegroups.com
ap schrieb:

Thanks for your try. Right, two search()es are much effort just for
getting the contents of a single match.

I first tried to use
//^M
y//e^M
in a loop, but this fails for matches of length 1.
Your function does it right.


Since in most cases I have a pattern that matches on a single line and
I only want matches for the last search pattern, I'll go with this:

func! CollectMatches()
let matches = []
let patq = substitute(@/, "'", "''", "g")
exec 'sil g//call substitute(getline("."),'''.patq
\.''', "\\=add(matches, submatch(0))", "g")'
return matches
endfunc

--
Andy

Reply all
Reply to author
Forward
0 new messages