3

Following my question about some search pattern in vim, I would like to get the the text corresponding to the first match (if any) of my search pattern wich includes cursor position and is multiline.

Here is a text example (markdown python cell):

```python
x = 10
```

```python
[p]rint(x)
```

the [] indicates cursor positon.

My search pattern:

\(```python\n\)\@<=\%(\%(```\)\@!\_.\)*\%#\_.\{-}\(```\)\@= 

Wich corresponds to the text print(x).

So basically I would like to extract this text and save it into a variable in vimscript.

Thank you.

3
  • :help search() – D. Ben Knoble Aug 21 '20 at 13:24
  • I read it already and it seems that there is no way to make search return the text of the first match. So what is a good way of doing it? – Nick Skywalker Aug 21 '20 at 20:36
  • it gives you a line no., you can use getline and some other functions to grab the text, or yank it (and either clobber a register or save/restore one) – D. Ben Knoble Aug 21 '20 at 20:42
4

So I found that gn was the one I need; from :help gn:

Search forward for the last used search pattern, like with n, and start Visual mode to select the match. If the cursor is on the match, visually selects it. If an operator is pending, operates on the match.

That means I can combine it with yank and get the text from the register into a variable.

So I made a function to get the text matching a pattern:

function! GetMatch(pattern)
    get matched = search(a:pattern)
    if l:matched
        " save register content
        let savereg = @9
        normal "9ygn
        let match = @9
        " restore register content
        let @9 = l:savereg
    else
        let match = ""
    endif
    return l:match
endfunction

Update: Another version without the test:

function! GetMatch(pattern)
    let found = search(a:pattern)
    " save register content
    let savereg = @9
    normal "9ygn
    let match = @9
    " restore register content
    let @9 = l:savereg
    return l:match
endfunction
2
  • Nick, if you let @9 = "" after savereg but before the normal command, you don't need to do the search() at all, as if gn doesn't find a match, it won't overwrite the register, and you'll return "" the same as before – jeremysprofile Aug 25 '20 at 18:06
  • I could remove the search, but I actually wanted to include it in the function. However I can shorten the code by removing the condition. – Nick Skywalker Aug 28 '20 at 21:24
1

A bit overkill but I refer you to How to run a python command based on a matched group of a pattern?

Based on the pattern(first match group), you can then run a python command. Here I set a vim variable.

:%GL/PATTERN/py vim.command("let var='" + match + '"')

some escaping problems might occur.

3
  • 2
    Thanks. Effectively it looks a bit overkill, I found a better solution. I can't post it unfortunately since I'm new on the vim stackexchange. It's using yank with gn: function! GetMatch(regex) | let matched = search(a:regex) | if l:matched | let savereg = @9 | normal "9ygn | let match = @9 | let @9 = l:savereg else | let match = "" | endif | return l:match | endfunction – Nick Skywalker Aug 21 '20 at 23:51
  • @NickSkywalker You should be able to post an answer... Can you please try again? If it still doesn't work, let me know. Thanks! – filbranden Aug 22 '20 at 3:24
  • 1
    You're right, it worked. – Nick Skywalker Aug 22 '20 at 7:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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