I\'m having the problem that ctags in vim/gvim takes me to a forward declaration a lot of times instead of to the actual definition of the function.
Any way to get a
You can press 2 then CTRL+], this will go directly to the second match, in java, this is usually the implementation of some interface.
I think that the easiest way is to use "g ctrl-]" instead of just "ctrl-]". If there is only one match, it will take you there. If there are multiple matches, it will list them all, letting you choose the one you want, just like :tselect. The best of both worlds. :)
This option worked for me better
Put the following line in your .vimrc and now you can use double click of the mouse (on the variable/entry
in your file) to jump to the tagged location. If single match is found, it will jump right away. If multiple entries are matches, it will prompt for user input..
:map <2-LeftMouse> g< c-]>
:tselect my_little_function
and you would get a list of matches. or if you jump to a tag and you are not happy with it, then type
:tselect
And you get a list of alternative for the last active tag.
This can happen because the pattern match stored in the tags file finds the declaration before the definition.
When Exuberant Ctags creates an entry for an identifier, it adds the entire containing line as a match.
However, sometimes the forward declaration matches that pattern. This can happen under certain coding styles.
First, here is an example file, foo.c
which doesn't have this problem:
static int foo(int x);
static int foo(int x)
{
}
Ctags creates an entry which looks like this:
foo foo.c /^static int foo(int x)$/;" f file: signature:(int x)
The match is anchored with ^
and $
, and since the forward declaration ends with ;
, it does not match.
However, the following coding convention triggers the issue:
static int foo(
int x
);
static int foo(
int x
)
{
}
The tags
entry is now:
foo foo.c /^static int foo($/;" f file: signature:( int x )
This will find the first line of the declaration, which is indistinguishable from the first line of the definition.
The fix is to make these two somehow different, while staying within the coding convention. In this case we are in C, so one thing we can do is drop the static
from the definition.
A C file scope declaration that has no storage class specifier declares a name with linkage. The linkage type (internal or external) is inherited from any previous declaration of the name that specified linkage. Thus:
static int foo(
int x
);
int foo(
int x
)
{
}
And now the tag looks like:
foo foo.c /^int foo($/;" f signature:( int x )
which matches only the definition; Vim no longer jumps to the first declaration.
If this solution is not workable, then it may be necessary to write a tags
filtering tool which scans the tags
file and identifies this problem, fixing up the offending tags. For example, for the second file with the ambiguous lines, we can fix up the tag manually like this:
foo foo.c /^static int foo($/;/^static int foo($/;" f file: signature:( int x )
I added a second Ex command into the tag-address, to search for the same pattern again. Now it jumps to the correct line. (Note: however, this is broken if the forward declaration is the very first line of the file.)
Finding ambiguous tags which have more than one match in the file and editing them in the above manner (or some other idea) can be automated, turned into a post-processing pass done each time the tags
file is generated. The additional scan of the files is expensive, though; this really should be done in Ctags.
Add the following to your .vimrc file:
noremap <c-]> 2<c-]>
This line causes vim to automatically jump to the second match (instead of the first one), which is usually the function definition.