flyingL123
flyingL123

Reputation: 8076

Vim syntax for getting name of current file

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?

Upvotes: 11

Views: 5575

Answers (2)

Ingo Karkat
Ingo Karkat

Reputation: 172570

: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.

Upvotes: 10

Etan Reisner
Etan Reisner

Reputation: 80931

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_%

Upvotes: 5

Related Questions