24

After generating a tags file with exuberant-ctags I can jump from a function call to its declaration with <C-]> which is pretty convenient.

My question is how to do it in the other way? When my cursor is on the definition of a function, how can I go to the lines where the function is called?

When I look to the file generated by ctags I only see informations related to the location of the definition and not of the calls, does it means that I can't do that, that Vim as a clever workaround or that I need to use something else than exuberant-ctags?

1

5 Answers 5

15

You can't jump to function calls with ctags. For C/C++ and Java there is cscope, and it integrates nicely with Vim (see :help cscope). For other languages you might be able to find a tool that generates / exports cscope-compatible databases (f.i. hscope for Haskell, and starscope for Ruby, Go, and JavaScript). You can also use cscope with GNU global databases, by pointing cscopeprg to gtags-cscope.

On a side note: if you aren't put off by occasionally puzzling use of Engrish, ;) you probably also want to use universal-ctags instead of exuberant-ctags. The latter hasn't been updated in years. The former is an actively maintained fork.

2
  • Does cscope support other languages than C/C++ and Java ?
    – edi9999
    Oct 2, 2015 at 10:42
  • @edi9999 cscope itself supports C/C++, Lex, and Yacc. The support for Java is marginally useful. You can get support for (old-style) PHP and JavaScript from GNU global, via the gtags-cscope utility. And, as I said above, there are other indexers that can export cscope-compatible databases. Oct 2, 2015 at 16:36
9

You can't do that with ctags.

Try a beefier alternative like cscope (which even has its own help section: :help cscope) or global.

7
  • Does cscope support other languages than C/C++ and Java ?
    – edi9999
    Oct 2, 2015 at 10:42
  • Yes, at least PHP and JavaScript.
    – romainl
    Oct 2, 2015 at 11:20
  • 1
    @romainl Nope, cscope itself supports neither PHP, nor JavaScript. You can however index PHP and JavaScript files with GNU global, then run gtags-cscope to use the resulting gtags file with cscope. Oct 2, 2015 at 16:40
  • @SatoKatsura, yes, cscope supports JavaScript (and CSS, appparently).
    – romainl
    Oct 2, 2015 at 18:43
  • 2
    @romainl You should consider looking at cscope's sources instead of speculating based on quick experiments. cscope has a rather relaxed C parser. That's all it has, and all it does. With that parser it "supports" a lot of languages, for suitable values of "support". Constructs are recognized as long as they look more or less like C. Which is why f.i. Java classes and newer PHP constructs are not recognized. Compare f.i. with starscope, which actually allows adding new languages. Oct 3, 2015 at 20:36
9

You could use Vim's grep command to search all the files in your project:

:grep! "\<<cword>\>" . -r
:copen

Let's put that in a keybind:

nnoremap <F4> :grep! "\<<cword>\>" . -r<CR>:copen<CR>

I find this one-key project-wide search invaluable when I am exploring a large unfamiliar codebase.

\< and \> are regexp sequences which indicate the start and end of a word, so you won't get partial matches. (The -w option to grep might be another way to achieve this.)

However, this is an unintelligent search, so it can produce false-positives if the same word appears in unrelated contexts.


Truthfully, I use my own modified version of the grep.vim plugin instead. This is slightly friendlier to use:

  • It lets you edit the search pattern, and also the grep commandline (so you can target specific folders like src/ lib/ instead of .) and remembers the changes.
  • I added support for Google's csearch. This can be much faster than grep (on HDDs) because it builds an index of words rather than scanning each file every time. Notably, csearch uses a slightly different regexp standard, so \b must be used instead of \< and \>.

I configure it and exclude some standard files like this.

For fast access, I create two keybinds. F3 lets me edit the commandline, F4 uses the previously configured commandline without any extra keystrokes. The mechanism is pretty ugly, and could use some cleanup, but it has served me well.

0

One option is to add your own search patterns on the command line or in the config:

--regex-c++='/(\.|->)([[:alnum:]_]+)[[:space:]]*\(/\2(/i,function instance or call/'

This creates a new tag "kind" with the code 'i' (for Instance or Invocation) to distinguish it from other tags. It also creates the tags with a trailing '(', because when you are looking for the definition, having 100 invocation results can muddy the waters. So searching for 'my_func(' limits the results in either case. If you don't like that, you can just remove the ( after the \2.

You can use this options multiple times for the same kind. So, instead of trying to come up with a single regex that will match all calls, you can have several, simpler ones that capture different kinds of calls.

This isn't foolproof, and with the patterns I've built up, I still get non-call results, but it's definitely better than nothing! :)

1
0

I always use two tools together: Exuberant Ctags, same as you, plus GNU ID Utils. This project provides the mkid utility to build an ID database for fast querying with lid.

The Vim-side setup is this line in .vimrc:

:set grepprg=lid\ --word\ --result=grep\ '$*'\ \\\|\ sort\ -n\ -t\ :\ -k\ 2

The sorting step is in there because lid has a way of putting out matches in a funny order that jumps around in a file rather than being ordered by line number.

I make two more definitions in connections with this:

:nmap K "_y:execute count ? ( ":!man " . count . " " . expand("<cword>") ) : ( ":grep \\<" . expand("<cword>") . "\\>")^M
:vmap K "zy:execute ":grep " . getreg("z")^M

This gives me a K shortcut for searching for occurrences of identifiers using :grep.

The :nmap K provides dispatch for searching for the identifier under the cursor. Because K is an existing command for invoking man (with an optional numeric prefix to specify the man section number), I partially preserve the behavior: if a numeric prefix is given, K still does the man lookup. Without a prefix it does :grep.

The :vmap K is for searching for text that has been visually selected.

Your Answer

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

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