11

In Vim, I can echo the current filename using this command:

:echo @%

I found that information here: http://vim.wikia.com/wiki/Get_the_name_of_the_current_file

Can someone explain why the @ symbol is necessary? If I enter the command without the @ symbol, I get an error:

E15: Invalid expression: %
E15: Invalid expression: %

However, if I try to send the filename to a bang command as an argument, including the @ sign appears as a regular character in the argument. Removing the @ sign works. In other words, in my .bash_profile I have the following function:

test_func() {
        echo $1
}

In Vim, I run:

:! test_func @%    #outputs @path/to/my/file
:! test_func %     #outputs path/to/my/file

What is the @ symbol doing and why does it behave differently when sending the output to a bash function?

1
  • I presume you know Ctrl+G but want something else. Commented Feb 19, 2015 at 16:21

2 Answers 2

10

:echo takes a Vimscript expression, whereas :! takes and external command, which is a special case for a filename, which is accepted by :edit et al.

For external commands and filenames, there are special characters such as % and #, described under :help cmdline-special. This also includes this crucial sentence:

In Ex commands, at places where a file name can be used, the following characters have a special meaning.

In contrast, :echo does not take a filename, but an expression. There are several ways to resolve the current filename; the most direct is via expand():

:echo expand('%')

Alternatively, as the current filename is also stored in a special register %, and registers are addressed via the @ sigil:

:echo @%

The other way around

This also explains the frequent question of why :edit g:variable doesn't work as expected. Vim's evaluation rules are different than most programming languages. You need to use :execute in order to evaluate a variable (or expression); otherwise, it's taken literally; i.e. Vim uses the variable name itself as the argument.

Sign up to request clarification or add additional context in comments.

Comments

5

I believe that is :h expr-register:

register expr-register @r


@r contents of register 'r'

The result is the contents of the named register, as a single string. Newlines are inserted where required. To get the contents of the unnamed register use @" or @@. See |registers| for an explanation of the available registers.

When using the '=' register you get the expression itself, not what it evaluates to. Use |eval()| to evaluate it.

As to why you don't need that for :! that is probably because of :h cmdline-special.

  1. Ex special characters cmdline-special

Note: These are special characters in the executed command line. If you want to insert special things while typing you can use the CTRL-R command. For example, "%" stands for the current file name, while CTRL-R % inserts the current file name right away. See |c_CTRL-R|.

Note: If you want to avoid the special characters in a Vim script you may want to use |fnameescape()|.

In Ex commands, at places where a file name can be used, the following characters have a special meaning. These can also be used in the expression function expand() |expand()|. % Is replaced with the current file name. :_% c_%

8 Comments

Thank you. Can you explain this in a simpler way? I don't know what :h expr-register and :h cmdline-special mean.
Those are vim help commands. Run them in vim to see the help items.
I'm still not sure what the @ symbol is doing. Is it shorthand for something?
You might as well ask "What is :? Is it short for something?" I think. It just is. @ is the indicator/sigil, in eval contexts, for a register. The way $ is the sigil for variables in the shell. It is the difference between :echo % (where % is an invalid expression) and :echo "%" (where "%" is a string) and :echo @% (where @% is an eval expression for the % register).
The difference between :! test_func @% and :! test_func % is interesting, % is not the same in both cases. In the former case % is a register and @% is evaluated as an expression, in the latter % is a cmdline-special. The result just happens to be the same.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.