3

I am trying to define a string in vimscript containing a literal # which then gets passed to a shell command using execute.

function! g:Call_imagemagick_with_hex(hex_color)
    let a:display_command = "! display -size 300x300 xc: '\#" . a:hex_color . "'"
    execute a:display_command
    "echo(a:display_command)
endfunction

and I would call this function like

:call Call_imagemagick_with_hex('34495e')

what I want the shell to see via execute' is:

display -size 300x300 xc: '#34495e'

The problem is that if # appears unescaped in the string passed to execute, vim tries to expand it - it seems # is like % but represents the previous buffer. e.g. If I use

let a:display_command = "! display -size 300x300 xc: '#" . a:hex_color . "'"

vim tries to expand # and throws an error. If I use

let a:display_command = "! display -size 300x300 xc: '\#" . a:hex_color . "'"

the shell sees:

display -size 300x300 xc: '\#34495e'

and the shell command doesn't work. From learning vimscript the hardway

Using single quotes tells Vim that you want the string exactly as-is, with no escape sequences. The one exception is that two single quotes in a row will produce one single quote.

It seems if ' does protects against meta-character expansion, it's possibly only in certain contexts.
Otherwise, how can I pass a # character to an underlying shell command?

7
  • @user9433424 thanks, the shellescape() looks interesting. I tried your command and it seems to work from the point of dealing with the # thanks May 17, 2016 at 11:10
  • Did you try \\#? See :help string.
    – romainl
    May 17, 2016 at 11:40
  • @romainl I did think to try that but dimissed the idea because I thought it would only add characters. Im interested to to see what it does though . I will try now... May 17, 2016 at 11:42
  • @romainl it seems the first "\" is getting consumed by vim. i.e. when I xtrace what the shell is seeing I get + display -size 300x300 'xc:\#59a7da'. I'm still confused by this issue. it seems like vim's user interface, vimscript seems modal too, i.e. the rules about when metacharacters are escaped depends on the command using the string... May 17, 2016 at 11:55
  • :execute "!echo \\\\#" or :execute '!echo \\#.
    – romainl
    May 17, 2016 at 12:10

1 Answer 1

4

You should use system instead of execute ! :

call system("display -size 300x300 xc: '#" . a:hex_color . "'")

You can use the return value in a variable if you want, e.g.:

let l:files = system('ls')

In this case you can prefer using the systemlist() that returns a list:

let l:files = systemlist('ls')

If you need to use special vim char in this context you can always use expand.

Reference: :h system()

6
  • thanks, I needed to use call system(...) else vim threw an error. the # doesn't seem to be making it to the display command. also the shell command display doesnt have a text output. it launches an x gui program. Still testing now.. May 17, 2016 at 10:47
  • even if I run call system('display -size 300x300 xc: "#34495e"') the display command isn't working as expected. May 17, 2016 at 10:55
  • what is your issue ? can you try with a simpler command (i.e. ls/cat/..) to check if the issue is your command ?
    – nobe4
    May 17, 2016 at 10:56
  • 1
    xtrace is showing that vim seems to invoking the command perfectly + display -size 300x300 xc: '#34495e' it seems your system idea is working, the problem now must be somewhere else. I think this solves the # issue anyway. thanks May 17, 2016 at 11:04
  • 1
    turns out it was a space between xc: # causing the problem! so this version of your statement: call system('display -size 300x300 xc:"#' . a:hex_color . '"') works fine. May 17, 2016 at 11:23

Your Answer

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

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