Friday, June 26, 2015

Re: How get a list of substrings matching a pattern?

2015-06-26 18:33 GMT+03:00 BPJ <bpj@melroch.se>:
> I have succeded in writing a function which splits the contents of a visual
> selection on a pattern, reverses the resulting list, joins it together on a
> separator and puts the result back into the visual selection (Yes that's
> kind of basic, right?):
>
> fun! RevList(...)
> let reg_save=@@
> let pattern=!exists('a:1') ? '\s*,\s*' : a:1
> let sep=!exists('a:2') ? ', ' : a:2
> normal gvy
> let @@=join(reverse(split(@@,pattern)),sep)
> normal gvp
> let @@=reg_save
> endfun
>
> What I want to do is to make this smart enough to not split on commas (or
> whatever) which are inside quotes, so how do I extract all substrings which
> match a pattern rather than split on a pattern, the equivalent of `my @list
> = $string =~ m/($pattern)/g` in Perl? (Hopefully a pattern like
> '\v%(%(\s*\,\s*)@!.)+' will match the non-quoted parts...)

You can use a hack with substitute(, , '\='):

let matches = []
call substitute(str, pattern, '\=add(matches, submatch(0))[-1]', 'g')

---

Some notes about your code:

1. !exists('a:n') may be written as a:0 < n. The whole expression can
be written using get(a:000, n, default).
2. You should not ever use :normal in scripts. You can't know whether
`normal gvy` will restore the selection and yank because user may have
remapped something. You need to use :normal!.
3. Using :let and @reg does not allow you neither to correctly save
nor restore the register. You need to use

let reg_save = [getreg('"', 1, 1), getregtype('"')]

call setreg('"', reg_save[0], reg_save[1])

. In the current state your code spoils

1. Any NUL which happens to appear in the register. (This is why I
have second argument to getreg().)
2. Register restored with :let @ will *never* be blockwise.

4. Yank operation does alter registers besides the unnamed register:
at least, the zero register, possibly also system clipboard. If you
care about restoring registers it is better to avoid yank operation,
though code will be much more complex (I would be using code based on
`getpos()` (using positions of < and > marks) and `visualmode()`).
Warning: you cannot possibly restore system clipboard from Vim because
Vim can only put text there.

>
> --
> --
> You received this message from the "vim_use" maillist.
> Do not top-post! Type your reply below the text you are replying to.
> For more information, visit http://www.vim.org/maillist.php
>
> --- You received this message because you are subscribed to the Google
> Groups "vim_use" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to vim_use+unsubscribe@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

--
--
You received this message from the "vim_use" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

---
You received this message because you are subscribed to the Google Groups "vim_use" group.
To unsubscribe from this group and stop receiving emails from it, send an email to vim_use+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

No comments: