Citre: 先进的 Ctags 前端

快点加入。我想用带ctags的半人马 用了lsp我觉得体验不好

我没有碰到这个问题,用你给的例子测试也可以正常跳转。

请描述详细的情况:

  • 你是想从另外的文件跳转到这个定义吗?
  • 你的 tags 文件长什么样?请给我看里面所有以 !_ 开头的行,以及你想跳到的定义那一行。
  • 在你使用 jump 或 peek 的 buffer 里,求值 (buffer-file-name) 是什么结果?
  • 在想要找定义的符号上求值 (citre-definition-default-filter (citre-get-symbol)) 是什么结果?(可以用 eval-expression 命令求值)

已经有了,看 centaur-lsp 的文档

我大概找到原因了。在生成tag的时候可以使用

;; - C-c f: Insert a dir or file

来添加目录,我的项目里会引用到其他库,所以我一般会使用这个功能加入其它目录。

问题在于,加入了其它目录后,当前目录还需要显示的添加一次,也就形成了类似这样的:

ctags
-o
%TAGSFILE%
--languages=C,
--kinds-all=*
--fields=*
--extras=*
-R
/tmp/
./

这里/tmp/目录就是其它目录,然而当前目录,默认是 ./

问题就在于这个 ./

我试了一下,如果是插入的绝对路径就没有问题,用这个 ./ 相对路径,就会复现这个情况。

看了下 citre-edit-cmd-buf-add-dir-or-file,不是很理解为什么会有个分支加入相对路径?

失败的 tag:

!_CITRE_CMD	ctags|-o|%TAGSFILE%|--languages=C,|--kinds-all=*|--fields=*|--extras=*|-R|./	/command line to generate this tags file/;"
!_TAG_FILE_FORMAT	2	/extended format; --format=1 will not append ;" to lines/;"	extras:pseudo
!_TAG_FILE_SORTED	1	/0=unsorted, 1=sorted, 2=foldcase/;"	extras:pseudo
!_TAG_OUTPUT_EXCMD	mixed	/number, pattern, mixed, or combineV2/;"	extras:pseudo
!_TAG_OUTPUT_FILESEP	slash	/slash or backslash/;"	extras:pseudo
!_TAG_OUTPUT_MODE	u-ctags	/u-ctags or e-ctags/;"	extras:pseudo
!_TAG_PATTERN_LENGTH_LIMIT	96	/0 for no limit/;"	extras:pseudo
!_TAG_PROC_CWD	/tmp/temp/	//;"	extras:pseudo
!_TAG_PROGRAM_AUTHOR	Universal Ctags Team	//;"	extras:pseudo
!_TAG_PROGRAM_NAME	Universal Ctags	/Derived from Exuberant Ctags/;"	extras:pseudo
!_TAG_PROGRAM_URL	https://ctags.io/	/official site/;"	extras:pseudo
!_TAG_PROGRAM_VERSION	5.9.0	/p5.9.20210627.0/;"	extras:pseudo
args	./main.c	/^int main(int args,char *argv[])$/;"	kind:parameter	line:12	language:C	scope:function:main	typeref:typename:int	file:	roles:def	extras:fileScope
argv	./main.c	/^int main(int args,char *argv[])$/;"	kind:parameter	line:12	language:C	scope:function:main	typeref:typename:char * []	file:	roles:def	extras:fileScope
func	./main.c	/^static int func()$/;"	kind:function	line:5	language:C	typeref:typename:int	file:	signature:()	roles:def	extras:fileScope	end:10
main	./main.c	/^int main(int args,char *argv[])$/;"	kind:function	line:12	language:C	typeref:typename:int	signature:(int args,char * argv[])	roles:def	end:17
main.c	./main.c	1;"	kind:file	line:1	language:C	roles:def	extras:inputFile	end:17	epoch:1631108253
stdio.h	./main.c	/^#include <stdio.h>/;"	kind:header	line:1	language:C	roles:system	extras:reference
stdlib.h	./main.c	/^#include <stdlib.h>/;"	kind:header	line:2	language:C	roles:system	extras:reference
string.h	./main.c	/^#include <string.h>/;"	kind:header	line:3	language:C	roles:system	extras:reference

成功的tag:

!_CITRE_CMD	ctags|-o|%TAGSFILE%|--languages=C,|--kinds-all=*|--fields=*|--extras=*|-R	/command line to generate this tags file/;"
!_TAG_FILE_FORMAT	2	/extended format; --format=1 will not append ;" to lines/;"	extras:pseudo
!_TAG_FILE_SORTED	1	/0=unsorted, 1=sorted, 2=foldcase/;"	extras:pseudo
!_TAG_OUTPUT_EXCMD	mixed	/number, pattern, mixed, or combineV2/;"	extras:pseudo
!_TAG_OUTPUT_FILESEP	slash	/slash or backslash/;"	extras:pseudo
!_TAG_OUTPUT_MODE	u-ctags	/u-ctags or e-ctags/;"	extras:pseudo
!_TAG_PATTERN_LENGTH_LIMIT	96	/0 for no limit/;"	extras:pseudo
!_TAG_PROC_CWD	/tmp/temp/	//;"	extras:pseudo
!_TAG_PROGRAM_AUTHOR	Universal Ctags Team	//;"	extras:pseudo
!_TAG_PROGRAM_NAME	Universal Ctags	/Derived from Exuberant Ctags/;"	extras:pseudo
!_TAG_PROGRAM_URL	https://ctags.io/	/official site/;"	extras:pseudo
!_TAG_PROGRAM_VERSION	5.9.0	/p5.9.20210627.0/;"	extras:pseudo
args	main.c	/^int main(int args,char *argv[])$/;"	kind:parameter	line:12	language:C	scope:function:main	typeref:typename:int	file:	roles:def	extras:fileScope
argv	main.c	/^int main(int args,char *argv[])$/;"	kind:parameter	line:12	language:C	scope:function:main	typeref:typename:char * []	file:	roles:def	extras:fileScope
func	main.c	/^static int func()$/;"	kind:function	line:5	language:C	typeref:typename:int	file:	signature:()	roles:def	extras:fileScope	end:10
main	main.c	/^int main(int args,char *argv[])$/;"	kind:function	line:12	language:C	typeref:typename:int	signature:(int args,char * argv[])	roles:def	end:17
main.c	main.c	1;"	kind:file	line:1	language:C	roles:def	extras:inputFile	end:17	epoch:1631108253
stdio.h	main.c	/^#include <stdio.h>/;"	kind:header	line:1	language:C	roles:system	extras:reference
stdlib.h	main.c	/^#include <stdlib.h>/;"	kind:header	line:2	language:C	roles:system	extras:reference
string.h	main.c	/^#include <string.h>/;"	kind:header	line:3	language:C	roles:system	extras:reference

谢谢,我知道了。最新版在匹配路径时增加了对 ./../ 的判断。另外在 recipe 中插入当前目录时会改为 .,这样生成的 tags 文件路径前面就会没有那个 ./,可以省一些空间。

这个没有什么必然的理由。因为 !_TAG_PROC_CWD 记录了 ctags 运行时的 current working directory,tags 文件又允许使用相对于该目录的路径,所以就这样做了。起码可以省一些空间,另外假设你因为一些原因要把 tags 文件移到别的地方,改一下 !_TAG_PROC_CWD 就又可以继续用了。

明白了。知道原因我就已经搞定了。直接改tag里面的内容以前没操作过。

不过,已经不影响citre很好用了。简单够用,快,就好了。peek也很好用。 :slight_smile:

不过还是上面提到的,还是觉得citre-jump可以提供一个类似的可选参数,让用户可以直接定制要搜什么。我看了代码,发现我搞不定。然后用上面提到的 xref-xxxxxxx 。我这边会卡半天。

所以现在我要自己决定搜其它字符而不是当前光标下的,还得先用 color-rg 搜一下,然后移到symbol下面去再使用citre-jump。感觉有点麻烦 :frowning:

等着就是了。参考 freeze when call citre-jump on space character · Issue #82 · universal-ctags/citre · GitHub

这个有计划:freeze when call citre-jump on space character · Issue #82 · universal-ctags/citre · GitHub

这个是不一样的,你给字符串的话 Citre 就只知道符号名字,但是光标在那的话 Citre 可以从周围获取信息,给的结果会更准。

弱弱问下,citre可以设置查询多个tags文件吗?比如c的标准库生成一个tags文件,项目代码生成另一个tags文件,两个文件可以一起索引吗?好像tags-table-list是可以配置多个tags文件的,但我找了一下citre的代码里并没有使用这个变量。不知道是不是可以支持这种使用方式呢? 标准库文件在多个项目中可以重用,所以也不太想在每个项目中都把标准库的目录增加进去,导致tags文件太大。

谢谢;

不可以。原因是 Citre 使用 readtags 过滤和排序,readtags 一次只能读一个 tags 文件。

如果要支持多个 tags 文件,我们需要把多次 readtags 查询的结果放到一起排序,排序的部分必须用 elisp 实现。当然这个事情并不是特别难,只不过我测试过性能比不上 readtags。

citre-peek 的窗口会让 line-number 挡住

我是默认没有开 line-number ,是在想看下行号手动打开的,然后 citre-peek 的窗口就被挡住了一部分

citre-peek-fill-fringe 设为 nil。它跟行号都是用的 fringe,肯定不能共存的。

1 个赞

好奇怪呀,居然还把左边的 margin 也给挡住了…

:rofl: 不太想管这个问题,我的左边没那么多东西,用起来挺舒服的 :rofl:

之后我把 citre-peek-fill-fringe 的默认值改一下吧,文档也说明一下和行号什么的相性不好(

Edit: 我自己用起来是这样的,挺好看的

其实发那个图是想说明 margin 默认显示在 fringe 左边,但是居然也把 margin 给遮住了(这是 Emacs 的锅

为什么我会发现呢?

因为我不小心打开了 diff-hl-margin-mode,想看下效果 :rofl: 结果自然是它也被挡住了

原来如此 :rofl: 我也不太懂 fringe、margin 啥的,这块代码是 masatake 写的(

Edit: 刚想起来有个 issue 说这个东西把 Emacs(27.1)搞 crash 了:emacs x windows crashed when calling citre-peek · Issue #95 · universal-ctags/citre · GitHub

我试了一下,是正常的:

感觉你还是开了 diff-hl-mode,并没有开 diff-hl-margin-mode

另外 peek window 的边框(不管是上下的还是左右的)主要是和 display-line-numbers-mode 打架,跟 diff-hl-mode 还挺和谐的。

我又仔细看了一下昨天那个图,发现只是"感觉"起来遮住了,实际没有。。我本来只是是类似个 childframe 显示在上面,后来才发现不是。所以也就没上面说的那个问题了

确实很爽,特别是citre-peak,挺好用的,不过补全可能是因为我和lsp共用的问题,没生效,后面再调整,很少遇到这么简单的东西了

注释掉lsp以后基本正常,不过部分变量或者成员变量补全稍微好像有点问题,不过基本可用了,在某些时候lsp server不可用的时候,用这个看代码临时修改啥的还是挺给力的,赞一个

今天发布了 0.2 版本,增加了一个 GNU Global 插件。现在可以借助 global 来查引用了,支持 xref 以及类似 citre-peekcitre-jump 的界面。

global 插件支持 sort by nearness,也就是当前文件中的引用会被放在最上面,接下来是当前目录的,上一级目录的,上上一级目录的… 离当前文件越远就会越在下面。我觉得这个用起来相当舒服。

详细请看文档

话说是不是时间太长了就不能编辑主题了?我还想在主贴里说一下这次更新呢…

2 个赞