标题说明了问题,所以这里是上下文。我有一个很小的C ++文件
void f(
int x
) { }
void f(
) { }
我在上面运行ctags。
ctags --recurse --sort=1 --c++-kinds=+p --fields=+iaS --extra=+q --language-force=C++ -f tags f.C
检查标签文件会按预期显示f的两个条目,并带有正确的签名。
当我尝试在Vim中使用它时,Vim用ctrl-]定位该函数,但是当我使用:tnext和:tprev时,消息显示tag 1 of 2
或tag 2 of 2
,但光标不会移动他们之间。
答案 0 :(得分:3)
如果您查看:help tags-file-format
,Vim将第三列(命名为{tagaddress}
)用作(搜索)命令(:help tag-search
)。在生成的标签文件中,它看起来像这样:
f foo.cpp /^void f($/;" f signature:( )
f foo.cpp /^void f($/;" f signature:( int x )
两个重载(/^void f($/
)的搜索模式都相同;这就是为什么每个标签跳转都将定位第一个实例的原因!换句话说,虽然标签程序添加了签名很不错,但不幸的是,Vim不考虑签名。
因此,解决该问题的明显方法是重新格式化源代码,以使签名(的一部分)包含在同一行中。然后,会有不同的模式:
b bar.cpp /^void b()$/;" f signature:()
b bar.cpp /^void b(int x)$/;" f signature:(int x)
解决此问题的更正确(但也更复杂)的方法是扩展ctags
程序以识别这些歧义,然后使用正向超前扩展模式考虑下一行中的内容。
f foo.cpp /^void f(\%(\n\s*int x\)\@=/;" f signature:( )
f foo.cpp /^void f(\n\s*)/;" f signature:( int x )
不幸的是,Vim似乎不理解这种语法(无论是否具有先行)。我刚得到E435: Couldn't find tag, just guessing!
。
答案 1 :(得分:1)
根据Ingo Karkat的回答,这是一个可能适合您的解决方案。如果您使用void append(text *t1, text *t2) {
int length1 = strlen(t1->content);
int length2 = strlen(t2->content);
int lengths = length1 + length2; // calculate the required length. You can change this to have some "reserve" such as in newText. In this example, it will be 24
t1->content = realloc(t1->content, lengths); // set the correct size for the buffer
for (int i = length1; i < length1 + length2; i++) {
t1->content[i] = t2->content[i - length1];
t1->content[i + 1] = '\0';
} // append the second string
t1->capacity = lengths;
printf("%s \n", t1->content);
printf("%d \n", t1->capacity);
}
运行ctags
(至少是旺盛的Ctags),它将输出行号而不是标签位置的搜索命令,这将解决歧义。
--excmd=number
不利之处在于,一旦您开始编辑文件,这些标记将无效,直到您再次运行ctags为止。搜索模式比行号更不容易受到这种影响。
还有其他一些答案(Vim auto-generate ctags是),这些答案涵盖了在更改时自动运行ctags的情况;两种方法的某种组合可能对您有用。