8

I'm looking for a way to execute some code within a function conditionally depending on the presence of some text within the edited file. I found a way to do it which works but doesn't feel very "clean".

Here's what I have:

function! foo()
    (...)
    let v:errmsg = 'ok'
    execute "silent! normal! :/" . l:pattern . "\r"
    if v:errmsg == 'ok'
        (... do stuff ...)
    else
        (... do other stuff ...)
    endif
 endfunction

The question is: can the same result be achieved somewhow without the clunky use of v:errmsg ?

What I have in mind is something of the form

function! foo()
   (...)
   if GrepInCurrentBuffer(l:pattern)
      (... do stuff ...)
   (...etc...)
3
  • 6
    Use search() - See:h search()
    – VanLaser
    Commented Nov 7, 2015 at 21:36
  • 1
    @VanLaser : this worked flawlessly and is exactly what I was looking for. Thanks a lot!
    – Dalker
    Commented Nov 7, 2015 at 21:43
  • 2
    You're welcome! In general, start from this to discover what's available: :h function-list
    – VanLaser
    Commented Nov 7, 2015 at 22:09

2 Answers 2

8

The function you are looking for is search(). This function will search starting at the cursor position, and when a match is found its line number will be returned. If no match is found, 0 is returned. The 'ignorecase', 'smartcase', and 'magic' options are used on the search pattern. Note that if you want to choose where the search starts at, you can use the cursor() or the setpos() function to set the cursor position, and the getcurpos() function to save the cursor location.

Here is an example of it in action:

function! SearchInRange(pattern, start_line, end_line)
    " Save cursor position.
    let save_cursor = getcurpos()

    " Set cursor position to beginning of file.
    call cursor(a:start_line, 0)

    " Search for the string 'hello' with a flag c.  The c flag means that a
    " match at the cursor position will be accepted.
    let search_result = search(pattern, "c", a:end_line)

    " Set the cursor back at the saved position.  The setpos function was
    " used here because the return value of getcurpos can be used directly
    " with it, unlike the cursor function.
    call setpos('.', save_cursor)

    " If the search function didn't find the pattern, it will have
    " returned 0, thus it wasn't found.  Any other number means that an instance
    " has been found.
    return search_result ? 1 : 0
endfunction

For more on the things mentioned in this answer, see the following help topics:

  • :help search()
  • :help 'ignorecase'
  • :help 'smartcase'
  • :help 'magic'
  • :help cursor()
  • :help setpos()
  • :help getcurpos()
6
  • 1
    How about just :echo search('pattern', 'nw') ? 1 : 0 instead ? :)
    – VanLaser
    Commented Nov 8, 2015 at 20:57
  • Because if an occurrence of hello is before the cursor, then it won't be detected. Commented Nov 8, 2015 at 20:59
  • The 'w' flag will wrap the search around the end of the file though. So any occurrence will be detected.
    – VanLaser
    Commented Nov 8, 2015 at 21:00
  • 1
    That is a very nice solution! I was trying to demonstrate the setting of the cursor position for searching within ranges, but I guess I didn't choose the best example. I have updated the example. Commented Nov 8, 2015 at 21:21
  • 1
    does it support regex search ? Commented Feb 3, 2017 at 10:33
4

For reference to anyone looking at this question in the future, here's a working solution following the same pattern as the pseudo-code in the question. It is completely based on VanLaser's comments to both the original question and EvergreenTree's answer.

function! foo()
    (... do stuff that defines l:pattern ...)
    if search(l:pattern,'nw')
        (... do stuff ...)
    else
        (... do other stuff ...)
    endif
endfunction

In the particular case of the actual function that originated this question, the solution did not really require the 'nw' flags. These flags should however make the solution safer in general, based on their description in vim's help:

'n'     do Not move the cursor
'w'     wrap around the end of the file

(from :help search in Vim 7.4)

1
  • For simply checking if something exists in the buffer, this is the best way of doing it. Commented Nov 8, 2015 at 22:03

Your Answer

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

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