Re: [vim/vim] `expand()` and `expandcmd()` behave differently on `%:~` (Issue #20793)
h_east (Vim Github Repository) <[email protected]>
| Newsgroups | gmane.editors.vim.devel |
|---|---|
| Message-ID | <vim/vim/issues/20793/[email protected]> |
h-east left a comment (vim/vim#20793)
@dkearns is right, `%:~` is not a special case. Here is the code for the two
steps.
`expandcmd()` is a thin wrapper around `expand_filename()` (see `f_expandcmd()`
in `src/evalfunc.c`), and `expand_filename()` in `src/ex_docmd.c` does this:
1. `eval_vars()` evaluates the cmdline-special item, so `%:~` becomes
`~/file`.
2. The replacement text is then run through `expand_env_save()`:
```c
// Wildcards won't be expanded below, the replacement is taken
// literally. But do expand "~/file", "~user/file" and "$HOME/file".
if (vim_strchr(repl, '$') != NULL || vim_strchr(repl, '~') != NULL)
{
char_u *l = repl;
repl = expand_env_save(repl);
vim_free(l);
}
```
So the `~` produced by step 1 is expanded in step 2, just like it is when you
type the command. `expand()` stops after step 1, which is why it keeps the
`~`.
A literal `~/path` in the string is handled by the same mechanism at the end
of `expand_filename()`: `mch_has_wildcard()` returns TRUE for a `~` that is
followed by another character, and the argument is then passed to
`expand_env_esc()`, which expands `~` only at the start of a name.
So the behaviour is correct and I do not intend to change it. What is missing
is that the help never mentions the second step. I would rather document that
order than describe `%:~` as an exception, since it is not one:
```diff
diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt
--- a/runtime/doc/builtin.txt
+++ b/runtime/doc/builtin.txt
@@ -3099,6 +3099,10 @@ expandcmd({string} [, {options}]) *expandcmd()*
like with |expand()|, and environment variables, anywhere in
{string}. "~user" and "~/path" are only expanded at the
start.
+ The expansion is done in two steps: the special keywords are
+ evaluated first, then "~" and environment variables are
+ expanded in the result. Thus `expand('%:~')` keeps the "~",
+ while `expandcmd('%:~')` returns the full path.
The following items are supported in the {options} Dict
argument:
```
The patch only writes down what @dkearns already described.
--
Reply to this email directly or view it on GitHub:
https://github.com/vim/vim/issues/20793#issuecomment-5078933065
You are receiving this because you are subscribed to this thread.
Message ID: <vim/vim/issues/20793/[email protected]>
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups "vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
To view this discussion visit https://groups.google.com/d/msgid/vim_dev/vim/vim/issues/20793/5078933065%40github.com.