[vim/vim] `expand()` and `expandcmd()` behave differently on `%:~` (Issue #20793)

6 views
Skip to first unread message

Edwin Chan

unread,
Jul 19, 2026, 12:31:08 PM (2 days ago) Jul 19
to vim/vim, Subscribed
EdwinChan created an issue (vim/vim#20793)

Steps to reproduce

  1. Run vim -u NONE -c 'echo expand("%:~") expandcmd("%:~")' "$HOME/file".
  2. Note that vim shows ~/file /home/user/file with the name of the current user.

Expected behaviour

:help does not suggest that expand() and expandcmd() should behave differently regarding command line special variables. These are the relevant parts from :help:

expand(…) … When {string} starts with '%', '#' or '<', the expansion is done like for the cmdline-special variables with their associated modifiers.

expandcmd(…) … This expands special keywords, like with expand(), and environment variables, anywhere in {string}. "~user" and "~/path" are only expanded at the start.

Version of Vim

9.2 (patches 1-807)

Environment

Operating system: Ubuntu 24.04.4 LTS on WSL 2.7.10.0 (Windows 11 Home 25H2)
Terminal: Windows Terminal 1.24.11911.0
Value of $TERM: xterm-256color
Shell: GNU bash, version 5.2.21(1)-release (x86_64-pc-linux-gnu)

Logs and stack traces


Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!
You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/20793@github.com>

Christian Brabandt

unread,
Jul 20, 2026, 5:37:41 AM (yesterday) Jul 20
to vim/vim, Subscribed
chrisbra left a comment (vim/vim#20793)

You already quoted the relevant sections, the behavioural difference is documented:

"user" and "/path" are only expanded at the start.

Which is not mentioned at :h expand().


Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!

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

Edwin Chan

unread,
Jul 20, 2026, 11:10:37 AM (yesterday) Jul 20
to vim/vim, Subscribed
EdwinChan left a comment (vim/vim#20793)

The way that sentence is phrased suggests e.g., ~, ~/dir, are expanded, but not, say, e.g., ./~temp~. The rationale, of course, is that ~ stands for $HOME in a shell command only at the start.

I would argue %:~ is a different class of expansion that belongs with e.g., %:p, %:h, i.e., command line special variables. These commands (as far as I can tell) work the same way for expand() and expandcmd().

There is also no reason to exclude %:~ from being expanded. A user may want to write, e.g., %:~:s?\~?/root? (same file but under root; this works with, e.g., :edit, :terminal, expand()) or :!docker exec container python %:~:s?\~?? (run this Python script in a Docker container, assuming that $HOME/app is mounted as /app).


Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!

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

Christian Brabandt

unread,
Jul 20, 2026, 11:33:57 AM (yesterday) Jul 20
to vim/vim, Subscribed
chrisbra left a comment (vim/vim#20793)

But expanding %:~ to the actual home path would be backwards incompatible change. I'd think, you could use %:p for that, if you really need that (and then you could use :s?pat?sub afterwards. Even if slightly inconsistent, I think the current behaviour should not be changed, since it has been like that for a very long time.


Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!

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

Edwin Chan

unread,
Jul 20, 2026, 12:40:23 PM (yesterday) Jul 20
to vim/vim, Subscribed
EdwinChan left a comment (vim/vim#20793)

I cannot speak to how long this behavior has been or indeed how much code depends on this particular quirk, so I would leave the judgment call to the code maintainers. But as you pointed out, it is inconsistent behavior, and surprising the user is not a good thing to do. I think at least this exception to the regular processing of command line special variables should be documented explicitly under expandcmd().

I have considered your suggestion before regarding the two-step replacement, but if % is used in, e.g., 'makeprg', then $HOME would have to be hard-coded, which is not very desirable—one would need to keep multiple versions of .vimrc on different servers.


Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!

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

Edwin Chan

unread,
Jul 20, 2026, 11:40:39 PM (23 hours ago) Jul 20
to vim/vim, Subscribed
EdwinChan left a comment (vim/vim#20793)

Let me add that, in my opinion, the primary usage of expandcmd() is to expand 'makeprg' and friends out in full so they can be consumed by others, e.g., system() and term_start(). That is why expandcmd() has cmd in its name, why it expands % everywhere, and why it expands only leading ~ in paths. expandcmd() should make scripting easier by exposing the internal expansion mechanism used by Vim. It should produce the same result as, e.g., :edit and 'makeprg'.


Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!

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

Reply all
Reply to author
Forward
0 new messages