[vim/vim] :autocmd `<sfile>` behavior documented at `:h autocmd-expand` at doesn't always work (Issue #17569)

6 views
Skip to first unread message

zeertzjq

unread,
Jun 17, 2025, 9:05:05 PM6/17/25
to vim/vim, Subscribed
zeertzjq created an issue (vim/vim#17569)

In :h autocmd-expand:

							*autocmd-expand*
Note that special characters (e.g., "%", "<cword>") in the ":autocmd"
arguments are not expanded when the autocommand is defined.  These will be
expanded when the Event is recognized, and the {cmd} is executed.  The only
exception is that "<sfile>" is expanded when the autocmd is defined.  Example:
>
	:au BufNewFile,BufRead *.html so <sfile>:h/html.vim

Here Vim expands <sfile> to the name of the file containing this line.

However, in :h <sfile>:

							*:<sfile>* *<sfile>*
	<sfile>    When executing a `:source` command, is replaced with the
		   file name of the sourced file.  *E498*
		   When executing a legacy function, is replaced with the call
		   stack, as with <stack> (this is for backwards
		   compatibility, using <stack> or <script> is preferred).
		   In Vim9 script using <sfile> in a function gives error
		   *E1245* .

And indeed, when sourcing the following file saved as /tmp/tmp.vim using vim --clean -S /tmp/tmp.vim:

func Foo()
  au BufNewFile,BufRead *.html so <sfile>:h/html.vim
endfunc
call Foo()

the defined autocommand becomes the call stack:

so command line..script /tmp/html.vim

while normally (with :source /tmp/tmp.vim) the autocommand is:

so /tmp/html.vim

What's more, using <sfile> in :autocmd isn't allowed in a :def function:

def Foo()
  au BufNewFile,BufRead *.html so <sfile>:h/html.vim
enddef
call Foo()

Changing <sfile> to <script> won't work either, as <script> is expanded when executing the autocommand, not when defining it.

I think there a 3 solutions to this problem:

  1. Change the behavior of <sfile> in :autocmd to be the same as <script>.
  2. Also expand <script> in :autocmd when defining the autocommand.
  3. Don't change any behavior, but update the documentation to encourage using :execute with expand('<script>') (which is a bit verbose) instead of <sfile> in :autocmd.


Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/17569@github.com>

Christian Brabandt

unread,
Jun 18, 2025, 11:53:52 AM6/18/25
to vim/vim, Subscribed
chrisbra left a comment (vim/vim#17569)

Hm, not sure. Nobody has complained until yet.

  1. Change the behavior of in :autocmd to be the same as <script>.

That would not help with vim9 script.

  1. Also expand <script> in :autocmd when defining an autocommand rather than when executing it.

This would be a backwards incompatible change.

  1. Don't change any behavior, but update the documentation to encourage using :execute with expand('<script>') (which is a bit verbose) instead of in :autocmd.

That makes sense and would need to be done anyhow for Vim9 script, no? Perhaps we can follow what you have done with Neovim and emphasis that <sfile> is deprecated and should not be used for new code (but don't wipe it yet from the documentation).


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/17569/2984799026@github.com>

Christian Brabandt

unread,
Jun 19, 2025, 1:42:10 PM6/19/25
to vim/vim, Subscribed

Closed #17569 as completed via 476b65e.


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issue/17569/issue_event/18234356483@github.com>

Reply all
Reply to author
Forward
0 new messages