2

In a substitute command, is it possible to retrieve the 'index' of the search (i.e. for the n-th match, the index is n)?

I am looking to use this in this context: :s/pattern/\=[SEARCH INDEX HERE].

I looked around in help :search, etc. but could not find what I'm looking for.

3

Here's a way to do it (maybe not the simplest way), using a recent Vim8 feature: closures (*):

  • In your vimrc, add the following (reusable) function - a function that returns a reference to another function, one that increments a counter:

    function! MakeSearchIndex()
        let counter = 0
        function! SearchIndex() closure
            let counter += 1
            return counter
        endfunction
        return funcref('SearchIndex')
    endfunction
    
  • Before every new search in which you need a search index, call MakeSearchIndex() and use its result as your \=[SEARCH INDEX] replacement part:

    let SI=MakeSearchIndex()
    %s/pattern/\=SI()/gc
    

or (one liner):

    let SI=MakeSearchIndex()|%s/pattern/\=SI()/gc

Basically, using a closure, you "capture" a new variable counter (created and set to 0 by each call to MakeSearchIndex), by making it visible and modifiable only in the returned funcref. So, while being local to MakeSearchIndex, counter's life is actually bound to that of the returned object.


(*) I guess this makes the answer ... emacs flavoured (LISP style) :)


The variation below works in exactly the same way, but also lets you create search index functions that receive an optional increment argument:

function! MakeSearchIndex()
    let counter = 0
    function! SearchIndex(...) closure
        if (a:0 > 0)
            let counter += a:1
        else
            let counter += 1
        endif
        return counter
    endfunction
    return funcref('SearchIndex')
endfunction

.. so that you could use for example SI(3) to increment the current counter with 3 at every call, or SI() (as before) to increment with 1.

(Well, I presume I just re-created the "counters" example from functional programming 101, or something like that :P)

1
  • 1
    Thanks, this is a clever application (with the small downside that SI() have to called in every replacement text, e.g., can't be called in an if branch that is sometimes not taken). I'll wait a bit more for other possible answers to flow in before accepting (I already upvoted but I won't show up until I have 15 rep.)
    – Kevin
    Oct 29 '16 at 20:38

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.