4

How do I get the path to the currently executing VimL script from inside a function? I know from outside a function, you can use expand('<sfile>'), but if you call that inside a function, you just get the function name. I know I asked this somewhere else before and got an answer, but now I forget how and can't find it anywhere.

1 Answer 1

7

Edit If need to get the filename of your script I haven't found a good way to do that in the doc, so here is the solution I would suggested:

At the beginning of your script define a script-variable (see :h script-variable) like this:

let s:filename="MyFileName.vim"

The variable will be locale to the script so it is accessible and modifiable only from within the script. You can then access it with echo s:filename for example, and concatenate it with the expand('<sfile>') if you need the complete path.

EDit 2 As @still_dreaming mentioned it in the comments it is possible to make this solution more robust:

expand('<sfile>') returns function only when it is called from inside a function, but when it is called from a script but outside a function it expands to the complete filename. Thus as long as the variable s:filename is set at the beginning of the script outside of any function it is possible to set it like this:

let s:filename=expand('<sfile>:p')

This way it is not necessary to update the line if the file is renamed (but it will be necessary to source it again if its name is changed while it is in use).

A script would then be of this form:

let s:filename=expand('<sfile>:p')

function! Foo()
    " Do magical Vim stuff

    echo "Path of this script: " . s:filename
endfunction

You have to use the :p filename modifier like this:

echom expand('<sfile>:p')

See: :h filename-modifiers for more modifiers like :~ for example which reduce the path to a relative path to the home directory.

7
  • 1
    This still does not provide the script path from inside a function. I don't think any of the modifiers will help, I think I need a completely different solution other than calling expand(). It is not a problem of the path being full or partial, or relative. The problem is <sfile> expands to the function name when called inside a function. Apr 17, 2016 at 20:28
  • 2
    @still_dreaming_1 I edited the answer with a workaround to keep the filename, I hope it fits your needs.
    – statox
    Apr 18, 2016 at 7:32
  • Yeah that works. You need to call expand('<sfile>') to get what needs to be removed from the end of expand('<sfile>:p) and then take that string with the correct part removed and add the s:filename to the end of it. I believe there is a better way of doing this, but this does work. Thanks! May 2, 2016 at 17:47
  • I'm glad it worked for you. I'm really not sure a better solution exists but if you find one please post an answer it would certainly benefits to other users.
    – statox
    May 2, 2016 at 18:16
  • Actually if s:filename will be set from outside any function, it can be set to expand('<sfile>'). Then that variable can be referenced inside functions inside that script or anywhere else in that script. That way the name of the file does not need to be hard coded into the variable and the variable will still get set correctly if the filename changes. May 3, 2016 at 15:26

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.