Problem
I am trying to create a more dynamic mapping for vimgrep
. Many project directories I work in don't have consistent names for directories in which source/test code lives (ie. test
vs. tst
). I would like to run a command when I first begin a vim
session at the root of the project to change the mapping for vimgrep
to limit my searching to only user-provided directories.
The problem is that I am having difficulty creating a mapped expression to provide this functionality.
Desired workflow:
$ (.../proj_root) vim .
[in vim session]
:<user-command> src test
:<user-command> src test
would execute the following and create the mapping:
:nn <c-\> :vimgrep /<c-r><c-w>/j src/** test/** <bar>:cw<cr>
Attempted solution:
{.vimrc}
command! -nargs=* ExeVpaths call ExeVpaths(<f-args>)
function! ExeVpaths(...)
if len(a:000) == 0
nn <expr> <c-\> printf(":vimgrep /<c-r><c-w>/j %s <bar>:cw<cr>", "*/**")
else
let l:vpaths = join(a:000, "/** ") . "/** "
nn <expr> <c-\> printf(":vimgrep /<c-r><c-w>/j %s <bar>:cw<cr>", l:vpaths)
endif
endfunction
Solution error
The above function executes with no errors for the following two examples:
(1) :ExeVpaths
(2) :ExeVpaths src test
However, using <c-\>
after having run (2)
fails with the two error messages:
E121: Undefined variable: l:vpaths
E116: Invalid arguments for function printf(":vimgrep /^R^W/j %s |:cw^M", l:vpaths)
This seems to be a scoping issue, seeing l:vpaths
appears to be undefined. But that does not make sense to me because the variable is defined right above it.
Comments and critiques are appreciated.
l:vpaths
is being evaluated when the mapping is executed and that won't work. You only have access tol:vpaths
and its contained value when the function is running. Include the value itself in the mapping...not the string 'l:vpaths'.