2

I'm trying to pass the word under the cursor to gtags and chain the definition search and the reference search together using a single function key.

My understanding is that this should work:

noremap <F4> :Gtags -di <cword><CR>:Gtagsa -ri <cword><CR>

But I get the following message:

Error: Line which matches to <cword> not found.

Just using <cword> should work. And using the following from Learn Vimscript the Hard Way works fine and expands <cword> as I would expect:

nnoremap <leader>g :grep -R <cword> .<cr>

The word under the cursor is passed to grep and searched for.

I've tried map, nmap, noremap, and nnoremap (I understand the difference, I was just trying everything). I've also tried <cword>, '<cword>', and expand('<cword>'). I've yet to find a combination that works.

The best I've been able to find is this:

nnoremap <F4> :Gtags -di <c-r><c-w><CR>:Gtagsa -ri <c-r><c-w><CR>

Which will get the word under the cursor and pass it to the definition search, but jump to the beginning of the line and pass that word to the reference search. For example, given the following with the cursor over my_func:

void my_func(void)

The QuickFix opens with the location of the definition of my_func, but then returns:

Error: Line which matches to void not found.

What is the proper way to map <cword> so that both commands are run? Why does <cword> work when passed to grep but not Gtags? Why does using <c-r><c-w> jump to the beginning of the line?

5

<cword> looks like a key code such as <c-r>, but it is not. As such it is not expanded by nnoremap, but is expanded by :grep and a few other commands which take shell-type arguments. Gtags <cword> does not work becasue Gtags does not know how to expand <cword>- this feature would have to be added deliberately to that command. This is as expected.

The second problem is you need to expand <cword> once between the commands Gtags and Gtagsa, since the cursor moves after the first command (think of nnoremap as typing the sequence as you would type).

An alternative is to use execute to chain the commands together. The pipe is escaped because otherwise it would be a command separator for the nnoremap.

noremap <F4> :execute 'Gtags -di <c-r><c-w>' \| execute 'Gtagsa -ri <c-r><c-w>'<cr>

Again, this is typed (and expanded) as you would type but the command action is delayed until the final <cr>. Note, this is simple but will likely fail if the word contains quotes.

Another method is to use an expression map with expand().

noremap <expr> <F4> ':Gtags -di '.expand('<cword>').'<cr>'
       \ . ':Gtagsa -ri '.expand('<cword>').'<cr>'

This expands both <cword>s at the time <f4> is pressed.

  • It seems that Gtags commands can't be chained with a <bar>. Typing :Gtags -di my_func|Gtagsa -ri my_func into the command line only returns the definition and not the references. While Gtags -di my_func | Gtagsa -ri my_func (spaces around the bar) returns Error: Line which matches to my_func | Gtagsa -ri my_func not found. Is it possible to add the ability to allow chaining using the <bar> to a plugin command as described here? Or do I need to use execute() somehow? – embedded.kyle Apr 30 '18 at 16:06
  • Ah, I was afraid Gtags would not play nicely. The solution is to use execute (command) not execute() (function). Check if the updated one works; I can't actually test it because I don't have the plugin. – Mass Apr 30 '18 at 16:22
  • Both work. Only difference I can find is that the first method echoes both commands, separated by the bar, back to the command line. Whereas the expression map solution echoes the first command and then overwrites it with the second. – embedded.kyle Apr 30 '18 at 17:16
  • this sort of thing always trips me up! Really great answer + explanation :) – JonnyRaa Dec 13 '18 at 12:00

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.