Citre: 先进的 Ctags 前端

这方面我也有一些想法,但可能不是用自动补全的形式来实现。参见这一楼我的回复:

感谢大佬,体验非常滴好 :+1: 。目前我是 lsp 和 citre 一起用,有些地方 lsp 没法补全的时候(比如 java 里写 sql 的 query)可以用 citre 补,还可以用 citre-peek 边查看类、函数的信息边码代码。感觉好久没有碰上这么爽的插件了,哈哈。

3 个赞

希望你能一直用 Citre 一直开心 :wink:

可以告诉我这个功能大概是怎么配的吗?

像 golang 这种可以 --exclude $GOPATH/pkg/mod/… 来把第三方库的代码加到 tag 中,我试了一下 ok, 但是 python 这种我就不熟悉了。

这不对吧,你给的这个命令应该是排除这个目录才对。

我考虑到了添加第三方库的需求,在生成 tag 的向导中会允许选择多个要扫描的目录,包括当前工程外面的。

Edit: 其实我和 Masatake 讨论过让 Ctags 自己找到依赖的那些模块的路径,但是现在找不到那个 issue 了。感觉短期也不太可能有。

另外,如果有很大的依赖库被 tag 了,那么增量更新就更重要了。

Edit2: 我刚又看了一遍才理解你和懒猫的意思。你们意思是 ctags 只扫当前工程目录,所以没有外部库的符号。但我说的意思一直是「在 tag 了那些库的符号的情况下,怎么把它们挖掘出来」。

1 个赞

@manateelazycat @rua 关于你们说到的扫描库的问题,我想提供一些信息。

Ctags 其实有 reference tags,但是目前关注的并不是函数、类等等的引用,而是模块的引用。比如在 Julia 的一个文件中如果有

using Module1

Ctags 会生成这样的 tags:

Module1	input.jl	/^using Module1$/;"	kind:module	roles:used

目前就我所知,Ctags 对大多数语言都实现了这种模块引用的 tag,其目的就是在扫描完一份代码之后,知道它使用了哪些模块。如果能再配合模块名 <-> 路径名的转换规则,就可以做到把库也一起扫描了。

(Citre 也稍微利用了一下这种 tag。如果你在 dired 里面,对头文件找定义的话(比如用 citre-peek),会把所有用到这个头文件的地方找出来。)

我现在仍然不好说这个功能什么时候会有,但 Masatake 确实一直很注重模块的 reference tags,所以还是很有希望的。

4 个赞

难过了,平时写的语言都不支持。。。。。

:rofl: 我的天,你平时都写些什么

最近是 Clojure 和 Elixir…

  ada        .ads .adb .ada
  asm        .a .asm .def .inc .ins .s .sa .S .src
  c          .c .h
  c++        .C .c++ .cc .cpp .cxx .H .h++ .hh .hpp .hxx .M .pdb
  c*         .cs .hs
  cobol      .COB .cob
  erlang     .erl .hrl
  forth      .fth .tok
  fortran    .F .f .f90 .for
  go         .go
  html       .htm .html .shtml
  java       .java
  lisp       .cl .clisp .el .l .lisp .LSP .lsp .ml
  lua        .lua .LUA
  makefile   Makefile makefile GNUMakefile Makefile.in Makefile.am
  objc       .lm .m
  pascal     .p .pas
  perl       .pl .pm
  php        .php .php3 .php4
  postscript .ps .psw
  proc       .pc
  prolog     .prolog
  python     .py
  ruby       Rakefile Thorfile .rb .ru .rbw
  scheme     .oak .sch .scheme .SCM .scm .SM .sm .ss .t
  tex        .bib .clo .cls .ltx .sty .TeX .tex
  texinfo    .texi .texinfo .txi
  yacc       .y .y++ .ym .yxx .yy

我这里显示是支持这些语言。

你这个估计不是 Universal Ctags。我手机上的 uctags 都支持 clojure 和 elixir :rofl:

$ ctags --list-languages | grep -E "(Clojure|Elixir)"
Clojure
Elixir

可以,我装个 universal ctags 试试。

ludovicchabant/vim-gutentags

这个vim插件自动生成tag的体验非常好,因为:

  1. 开箱即用,除了安装不用做任何事情.

  2. 可以指定tag文件的储存位置,日常使用的时候完全不用操心tag文件的管理(比如误入版本控制系统)

let g:gutentags_cache_dir = expand('~/.cache/tags')
  1. 它用了一些hack,来实时增量更新tag,让tag保持在最新状态的同时,性能也让人满意.
1. Incremental tags generation: don't re-generate the whole project all the time. This may be fine for small projects, but it doesn't scale.
2. External process management: if the ctags process is taking a long time, don't run another one because I saved a file again.
3. Keep the tag file consistent: don't just append the current file's tags to the tag file, otherwise you will still "see" tags for deleted or renamed classes and functions.
4. Automatically create the tag file: you open something from a freshly forked project, it should start indexing it automatically, just like in Sublime Text or Visual Studio or any other IDE.
1 个赞

Citre 主要不方便的地方是要手动生成 tags,现在我在做一个生成 tags 的向导,一旦生成过以后用一个命令就可以更新了。

我还是不打算帮用户把这些事全干了,因为稍微了解过 Ctags 就会知道,可以根据工程的需求来调整命令行参数,甚至定制 tag 生成规则(在大量用 macro 的工程里尤其有用)。我看目前大多数 Ctags 插件都用一个变量储存 ctags 命令,对所有工程都用这一个命令,这个我认为只是图省事的设计。我需要考虑到用户以后自己 tweak 命令参数的需要。

Citre 这方面做得比这个强。请读这个文档 About the name of the tags file 一节。

这个我现在还是不打算做,Universal Ctags 有可能要加这个功能。

关于 gutentags 我就想问一下:它更新出来的 tags 还是按字母顺序排序的吗?如果不是的话就没法做二分搜索了,在大工程里会没法用。

前两天我已经集成进 Centaur Emacs 了,多一个选择。univeral-tags其实从本质上讲和LSP干的事情差不多,但是由于没有JSON 解析之类的会轻量很多,但是也缺少一些功能。citre正好弥补了一些,希望能增加更多有效的小功能。加油!:+1:t2::+1:t2:

3 个赞

多谢你的工具,速度很快,也可以和lsp 配合同时使用,有一些场景lsp解析不出来,利用citre就很好work,反之亦然。

我现在遇到问题是,如在读取python 文件时,会提示“Error loading tags-file: (user-error File /home/test/TAGS is not a valid tags table)”, 但里面跳转等都正常,看起来没有问题,你知道这是什么原因么?

你的改动是不是不可以lsp与citre 同时开?另外,似乎快捷键里面少了 citre-peek,这个作者主要推荐的一个功能~

这和 Citre 无关。

TAGS 和 tags 是两个东西。TAGS 是 etags $ ctags -e 默认生成的文件名;tags 是 ctags 默认生成的文件名。二者具有不同的格式,Citre 只支持后者。

如果你没有乱动某些变量,Citre 根本不会去读 TAGS 文件。所以这肯定是其他插件的报错。

考虑到 Emacs 玩家一般不熟 Ctags,而且最近碰到不少人都有这个误解,我会在文档里仔细说明一下这个事。

我看了一下应该不行。为什么你们都可以同时开呢,我都没想明白你们怎么配的 :rofl:

其实没有少。citre-ace-peek 的功能完全覆盖 citre-peek 了,另外还能做到类似「在写函数参数的时候直接 peek 函数定义」 的功能。恰恰说明 @seagle0128 仔细读过文档并且跟着操作了。

@kinono 其实我觉得tags统一放在一个 cache 目录的思想挺好的,这样就不用每个要Index的项目都要手动写 git ignore 文件。

我是自己配置同时开的,没有利用Seagle那里的。自己配置就当作两个独立的package就好了。citre-ace-peek 在调用时还需要再输入一些字符定位,我看直接citre-peek 当下cursor的位置,在我这里就很好了。