Get a Vim script's <SNR>

vim

Solution

You can retrieve a script's `<SNR>` by parsing the output of `:scriptnames`. The following function will do just that for either the script's full filename, or a fragment of it (as long as it uniquely identifies the one you want).

func! GetScriptNumber(script_name)
    " Return the <SNR> of a script.
    "
    " Args:
    "   script_name : (str) The name of a sourced script.
    "
    " Return:
    "   (int) The <SNR> of the script; if the script isn't found, -1.

    redir => scriptnames
    silent! scriptnames
    redir END

    for script in split(l:scriptnames, "\n")
        if l:script =~ a:script_name
            return str2nr(split(l:script, ":")[0])
        endif
    endfor

    return -1
endfunc

If you need to, for instance, call a function `foo` defined with `s:` in a script named `bar.vim`, you can use:

call eval(printf("<SNR>%d_foo()", GetScriptNumber("bar.vim")))

Problem

I'd like to call a function declared with script-scope (`s:`) in a sourced Vim script, without hard-coding the `%d` in `call <SNR>%d_function()` or exposing the function to the global namespace by modifying the plugin file itself. How can I retrieve its parent script's`<SNR>`, or script number, programmatically?

Original source