14

for example suppose I did

:let foo=pattern

and now I want to perform Ggrep patter but use variable foo instead of the literal patter string.

:echo foo

outputs pattern, but

:Ggrep foo

just looks for foo

UPDATE:

building a string of command and then running :execute on it is not a solution, its a hack. And it breaks with any non-trivial variable values.

3
  • what is Ggrep (capital G?)? – akira Aug 8 '11 at 11:30
  • git grep from 'fugutive' vim plugin – Vitaly Kushner Aug 9 '11 at 10:08
  • example command is wrong. it should be let foo='pattern'. Say that :execute is a hack is totally wrong. That's the solution: You want vim to evaluate the command before execute it – albfan Mar 9 '18 at 19:51
3

It's not about variable but maybe vim abbreviate command can helps. Try from command line:

:abbreviate foo pattern

Then

:Ggrep foo<space>

It will complete 'foo' to your 'pattern'.

1
  • Now try to run echo foo. Opps echo pattern which is not a variable. this is a hack and misguiding. – albfan Mar 9 '18 at 19:55
8

what about:

:execute ':grep ' . foo
12
  • how do I properly escape foo's content? it might contain special characters like ", ', /, \, etc – Vitaly Kushner Aug 8 '11 at 11:34
  • 1
    @Vitaly Kushner: See ":help escape()" and ":help fnameescape()". – garyjohn Aug 8 '11 at 16:45
  • I know escape(), but not sure about what characters to escape – Vitaly Kushner Aug 10 '11 at 13:00
  • fnameescape() is not good, its not a filename argument, its an arg to plugin function. suppose I :let foo = "aaa\"bbbb'cccc" – Vitaly Kushner Aug 10 '11 at 13:02
  • 1
    I am pulling my hair out over this too. You can't issue a command like let xyz = tabpagenr() then tabnext xyz. Vim's scripting language is as flawed as its modal environment is flawless. – puk Mar 1 '12 at 7:01
2

If you don't like the :exe solution, you can "read" the contents of a variable into to the command line by using the = expression register. For example, type :Ggrep then press Ctrl-r and then type =foo and press Enter. Assuming the variable foo contained "pattern", your command line should now look like:

:Ggrep pattern

This has the advantage that you can see the actual command that will be run, and even modify it before pressing Enter a second time.

See:

:help "=
1

As far as I'm aware, there is no option other than :execute

echo "hello"

" same as

let greeting = "hello"
execute "echo '" . greeting . "'"

However, as you've noticed, if the variable contains certain bad characters, that causes an issue:

let greeting = "hel'lo"
execute "echo '" . greeting . "'"

" hel
" E121: Undefined variable: lo

To avoid this, the string variable needs to be escaped properly. This is actually easier than it sounds, using single-quoted strings. Double-quoted strings would be a nightmare, but if you look at :help literal-string it says:

Note that single quotes are used. This string is taken as it is. No backslashes are removed or have a special meaning. The only exception is that two quotes stand for one quote.

So the only special character is ', which can be escaped by replacing it with ''. That can be done with substitute.

let greeting = "hel'lo"
execute "echo '" . substitute(greeting, "'", "''", 'g') . "'"
" echoes: hel'lo

That's a bit gross looking, so you could move that into a function:

function! EscapeVimStr(str)
  return "'" . substitute(a:str, "'", "''", 'g') . "'"
endfunction

let greeting = "hel'lo"
execute 'echo' EscapeVimStr(greeting)
" echoes: hel'lo

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.