Citre: 先进的 Ctags 前端

加了一个选项 citre-update-tags-file-when-no-definitions

1 个赞

我在 Windows 上试了一下,在我这里 find-file-noselectfind-buffer-visiting 都对盘符大小写不敏感,用 Citre 也没有出现你所说的现象。这个有点怪。总之我现在在 Windows 上把盘符都转小写了,在 develop 分支,希望你能测试一下。如果没问题的话我再合并到主分支。

试了一下还是不行;我发现一个很奇怪的现象,在我没有用过citre-jump的时候,我用find-file-noselect,也是大小写不敏感的;但是只要我调用citre-jump,生成了一个重复的buffer后,find-file-noselect大小写就开始敏感;不同大小写的文件会返回不同的buffer;我把那个生成的buffer关闭,在scratch中尝试,find-file-noselect大小写又返回同一个buffer了; 现象好像是,只有在citre的函数里,find-file-noselect这个函数,无法准确找到buffer;但是在scratch中调用find-file-noselect,就可以找到相关的buffer; 我用counsel-etags和lsp-find-definition来在同一个文件中跳转,都不会产生新buffer;

这个现象太奇怪了,不知道是不是citre中定义了什么临时变量?

我回去再看看吧 :rofl: 要是复现不了就很难搞

下午又观察了一下现象,有个新发现:在citre-jump这个函数刚进入时,原来buffer list的文件名是全小写的,在进入citre-jump函数后,buffer-list中文件名还是小写,但调用了citre-get-definitions-maybe-update-tags-file这个函数后,本文件的文件名盘符在buffer-list中变成了大写;我试了一下发现find-file-noselect函数,如果文件名全小写,是大小写不敏感的查找,但是文件名中如果出现大小写都有的情况,就自动变成大小写敏感的操作了;所以原因应该是citre在处理中,改动了原先buffer-list中的文件名组成,才导致后面的查找操作成了大小写敏感的了;

这个地方我跟到最近的地方是citre-get-definitions,在citre-get-symbol返回值中看到了大写盘符的文件名;我觉得把这里的大写盘符改成小写,可能就可以解决问题;

所以后面把find-file-noselect的入参改成全小写不能解决问题,因为此时buffer-list中的文件名已经变成大小写组合的了,所以无法匹配到正确的buffer。

1 个赞

在Java代码里,跳转到Enum成员的时候会失败,应该是跟filter有关,但只是稍微看了下代码,对readtags的filter也不了解,所以不清楚问题在哪儿。

一个现象是,我如果把citre-jump中的(citre-get-definitions-maybe-update-tags-file) 改成 (citre-get-definitions-maybe-update-tags-file (substring-no-properties symbol)),就可以正常跳转。改了之后,跳转到函数或者类也没问题。

请告诉我你想要跳转到的 tag(在 tags 文件里找到它,把那一行贴上来),还有当前 buffer 的文件路径。

tag:

SHIP_ERR /mnt/Work/.../common/constant/state/LogType.java /^ SHIP_ERR("出库异常", 7);$/;" kind:enumConstant line:17 language:Java scope:enum:LogType file: access:public roles:def extras:fileScope end:17

当前buffer文件路径:

/mnt/Work/.../core/log/factory/LogTaskFactory.java

两个路径中的…是相同的部分。

extras:fileScope

这个意思是 ctags 认为这个符号只能在它所属的文件中使用,从外边应该是用不到的。Citre 会把不在当前文件,且具有 file scope 的 tag 排除掉。

如果从外边确实能使用到这个符号,建议给 universal ctags 报 bug。

好的,多谢。

我知道了,是 citre-core-filter-input 里面转换了一下盘符大小写,里面直接修改了传进来的路径,估计这个路径又是一层层引用到 Emacs 自己内部使用的一个变量。。。

等我全面检查下是不是有其他类似问题。

Edit: 已经在 master 上修复。试一下?

fixed,太感谢了。

请教一下,citre-jump都是正向查找,即找到当前函数调用了的函数定义。

我想反向查找一下,当前函数被谁调用,类似于 cscope-find-functions-calling-this-function这样的功能。这个能支持不?

帖子前面几楼也在讲查引用的事情,应该还没有实现查引用的功能。

ctags 不支持查引用。我接下来一阵子应该比较闲,打算给 citre 做个 gtags 插件,这样就可以查引用了。

Edit: 事实上 ctags 支持一些查引用的功能。看 C 代码的时候,如果看头文件的定义,citre 会给你所有使用了这个头文件的地方。我记得看宏的定义的话也是能看到引用的。Citre 会把引用排到最后,然后会有个 <R> 标记,直接翻到最后看看就知道了。

3 个赞

了解。多谢多谢。

另外,我发现有时候用citre-jump不能跳转,但是用citre-peek却可以找到对应的定义?比如C的静态函数就是这样的。暂时还不知道原因。

还有就是citre-peek有没有历史的功能呢?比如刚才我peek了一堆调用关系,再重新peek的时候,这个信息就没有了。

先更新一下吧,我感觉最近好像修了类似的 bug,如果还不行的话请开个 issue。

有三种方法保留历史:

  1. 如果你按 C-g 关掉了一个 peek 会话,过一会想重新恢复,可以用 citre-peek-restore
  2. 新的 peek 会话会覆盖掉旧的。如果你想在关闭 Emacs 之前都可以恢复一个 peek 会话,用 citre-peek-save-sessioncitre-peek-load-session
  3. 如果你想关闭 Emacs 以后还保存,这个目前做不到,但我有另一个插件叫 clue,用来写代码阅读笔记,citre-peek 和这个有整合。

这些在文档里都有写。

实际上可能 citre-jump 的行为是对的(我最近修了 citre-peek 的问题)。如果从 tags 文件给的信息可以推断出一个符号无法被当前文件引用到,Citre 就不会给你展示。所以我们应该先确定你要看的定义确实是当前符号的定义。

如果有例子的话我们可以讨论一下,看看是 Citre 的问题,ctags 的问题,还是你使用的问题。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

static int func()
{
    printf("[%s:%d]\n", __FUNCTION__, __LINE__);

    return 0;
}

int main(int args,char *argv[])
{
    func();

    return 0;
}

这样的一个C代码,func这个静态函数citre-jump跳不过去。

不过我更新了最新的citre后,好像citre-peek也查不到这个函数了 :frowning:

嗯嗯。试了一下,很好用,保存session后,可以从任意地方进去。太好用了。谢谢