5

Considering the following regex pattern:

/\s*<<.\{-}>>/

I want to match those patterns only when the cursor is somewhere on this pattern.

So, if have the line (the character enclosed in [] is the cusor position):

This is <<on[e]>> and this is <<another one>>.

I want to only match <<one>>, not <<another one>>.

I know that \%# specifies the cursor position, but I don't know how to apply it to state that the cursor may be anywhere on that pattern.

Is this possible somehow?

2
  • Am I correct in thinking that you still want to match if the cursor is in the whitespace before the <<?
    – Rich
    Sep 4, 2019 at 10:37
  • @Rich Yes. That is not the most important aspect, I could live with it if that would be missing. But it should match on any other position.
    – radlan
    Sep 4, 2019 at 10:39

2 Answers 2

4

One solution is to use a lookahead before the regex and a lookbehind after the regex. That ensures the cursor is after the start of the match, and before the end of the match.

One issue with the regex you're using is .\{-} which is a non-greedy operator. If you add anchors for the cursor position, this will end up matching from the beginning of <<one to the end of another one>>. To solve that, I'm replacing it with \([^>]\|>[^>]\)*, which will match any character other than >, or a single > followed by a different character. (Perhaps a negative match would have worked here instead.)

Putting it all together:

/\(.*\%#\)\@=\s*<<\([^>]\|>[^>]\)*>>\(\%#.*\)\@<=

UPDATE: Using \@> for the middle bit is able to preserve the -\{-}, resulting in:

 /\(.*\%#\)\@=\(\s*<<.\{-}>>\)\@>\(\%#.*\)\@<=
2
  • 1
    Wow, this gets way more complicated than I had expected. But thank you. I think I will try your approach in the answer, although the one in your comment works as well. Many thanks!
    – radlan
    Sep 5, 2019 at 6:40
  • Yeah it gets complicated! I just updated the answer to incorporate the comment. Glad this helped you!
    – filbranden
    Sep 5, 2019 at 11:22
6

You can use the atom /\&. This is like forcing two different regular atoms to match at the same position.

Now it becomes a bit complicated, since the cursor position can be anywhere inside the <<..>> and then you also want to allow whitespace inside those <<..>>. This makes it a bit complex to match the correct item if there are several matches in a line.

So instead of using .\{-\} to allow an arbitrarily long number of matches (even other <<), you need to restrict your match to only match until the >>.

To make the pattern simpler, let's for now assume all characters are allowed except for >. That would make the pattern like this:

/<[^>]\+>>\&[^>]*\%#[^>]*>>

which means < followed by any character except > ([^>]) and at the same time (\&) allow any character except >, followed by the cursor position (\%#), followed by any character except > followed by >>.

Now you can make this more complicated by enforcing the >> delimiter. Possible search patterns are \(>>\)\@! (not followed by >>) or the already mentioned \([^>]\|>[^>]\). However this will make your search pattern a lot more complex, so this is left as an exercise to the reader ;)

You might also want to have a look at the distributed plugin LogiPat, which allows to construct patterns using logical operators (and, or, not, etc).

1
  • 1
    Thank you. Although I have accepted filbrandens answer, your approach works, too. Unfortunately, both can get quite complicated. :-) But ok, I have to live with that.
    – radlan
    Sep 5, 2019 at 6:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.