Question

I am trying to create a simple mapping in vim to execute a shell command. The command I want to execute is this:

ruby -e "Dir.glob('./spec/*_spec.rb').each {|f| require f}"

which works fine when I run it at the command line.

However, if I run the following in vim:

nmap ,t :!ruby -e "Dir.glob('./spec/*_spec.rb').each {|f| require f}"<cr>

I get the error:

E492: Not an editor command: require f}"<cr>

Note: I'm on windows, if that's relevant.

  1. What am I doing wrong?

  2. Bonus: How can alter the above command so that it does not depend on the current file being in the directory containing "spec"? Ideally, if the current file's directory did not contain "spec", it would check the parent directory, and so on, recursively, until it found a directory containing "spec". At that point it would run the command with "." replaced by the directory it found in my code above.

Final Solution

Based on Ingo's answer, my final solution was this:

nnoremap ,tt :call RunAllMinitestSpecs()<cr>

function! RunAllMinitestSpecs()
  let l:dir = finddir('spec', '.;')
  let l:dir = substitute(l:dir, '\', '/', 'g') " so it works on windows
  let l:ruby_cmd = "\"Dir.glob('" . l:dir . "/*_spec.rb').each {|f| require f}\""
  exe('!ruby -e ' . l:ruby_cmd)
endfunction
Was it helpful?

Solution

The | separates Vim commands; for Vim, the mapping ends at the first |, and Vim tries to interpret the remainder as a command (which obviously fails). You need to either escape via \ or (better) use the special <Bar> notation in mappings:

:nnoremap ,t :!ruby -e "Dir.glob('./spec/*_spec.rb').each {<Bar>f<Bar> require f}"<cr>

Tips

You should use :noremap; it makes the mapping immune to remapping and recursion.

Bonus answer

You can get an upward directory search (:help file-searching) via finddir(), then pass the result to glob(). See

:echo finddir('spec', '.;')

(I would then move the implementation into a :function, and invoke that from the mapping. This would have also avoided the | escaping problem.)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top