On 2009-02-03 18:52 (+1100), John Beckett wrote:
> However, supposing I understood this, I still don't see why you would
> escape % and #.
Put this code to a file and source it:
command! -complete=file -nargs=* Test call s:TestFunc(<q-args>)
function! s:TestFunc(args)
echo a:args
execute '!ls -l ' . a:args
endfunction
Now select a buffer which has a file that exists in the filesystem. Run
these commands:
:Test %
:Test \%
Besides echoing the a:args both will print the "ls -l" for that
filename, like this:
-rw-r--r-- 1 dtw dtw 132 3.2. 10:03 test.vim
In the ":Test %" case the % is expanded when Vim parses the command
line. In the ":Test \%" case Vim command line parser removes the
backslash and passes "%" to the function in which it is expanded by the
"!ls -l" command.
So we really just want these meta characters expanded only on the
command line. That's why we escape them in the function. Think about a
situation where the filename itself contains a "%" character. Then the
result of ":Test %" is like the following. We use filename "test-%.vim"
here.
First ":Test %" echoes a:args, that is, the % expanded to the filename:
test-%.vim
Then we see an error from "ls" command:
:!ls -l test-test-%.vim.vim
ls: cannot access test-test-%.vim.vim: No such file or directory
A user of commands like :Test or :Shell deals directly with the command
line so expanding Vim meta characters only in that context is the right
thing to do. Vim does that automatically.
Have I convinced everybody that we don't want to expand "%" and "#"
twice?
> [...] wouldn't there be a bunch of other characters that needed
> escaping??
Yes. In shell, parentheses, for example, would need escaping too.
Suppose we have a filename which has parentheses, like "test-().vim".
Let's try ":Test %" command again:
test-().vim
:!ls -l test-().vim
/bin/bash: -c: line 0: syntax error near unexpected token `('
/bin/bash: -c: line 0: `ls -l test-().vim'
The first line is the output of "echo a:args". Parentheses are shell
meta characters and the would need escaping in shell's context.
On the other hand "%" and "#" need escaping as Vim's context. But we
can't use "escape(a:cmdline, '%#()')" (that is, escape the parentheses
too) because then we couldn't pass parentheses as themselves anymore
from the Vim command line. The problem comes from the fact that there
are three levels where expansion happens:
1. when user executes the :Test or :Shell command (Vim expansion)
2. when the script runs "!" command (Vim expansion)
3. when the shell runs the command line (shell expansion).
Vim's expanding/escaping business is such a mess and it just can't work
in all situations. It has bitten me many times even though I think I
understand it quite well.
So after trying different things I think the best compromize is the one
already in the Vim tip page.
>> I'll conclude that we can have a sort of fix to this but we
>> lose filename completion and we lose % and # expansion. They
>> are too useful to me so I'm not going to change the version
>> of the script on my computer but for the Vim tip page the fix
>> would be to remove the -complete=file option:
>>
>> command! -nargs=+ Shell call s:RunShellCommand(<q-args>)
>>
>> And we need to remove the examples with % expansion.
>
> I agree that filename completion is too useful to discard. Again, I'm
> confused by how the above seems to imply that % and # do something
> useful for you, yet % failed for Cory.
I'm confused too. If the currently active buffer has a filename, then
with :Shell command "%" and "#" are expanded correctly. They work well
here. If the buffer don't have a filename then Vim (quite rightly) gives
E499 error without even executing the custom :Shell command.
> [...] at the moment all I want to do is have someone clean up the
> proposed new tip so that it makes sense and works as advertised.
Here it does work as advertised. It's the Vim command-line parser that
gives the E499 error. It happens before my s:RunShellCommand function is
even called.
--~--~---------~--~----~------------~-------~--~----~
You received this message from the "vim_use" maillist.
For more information, visit http://www.vim.org/maillist.php
-~----------~----~----~----~------~----~------~--~---