Citre: 先进的 Ctags 前端

更新后很好用,不错不错

:rofl: 很高兴你喜欢,但是生成 tags 文件那块已经打算重写了 :rofl:

1 个赞

fork了ctags-update,按我自己的使用习惯改了改,支持uctags,加了几个配置(从counsel-etags也拷贝了一些代码)。有需要的自取 我的ctags-update .

            (setq ctags-update-languages (list
                                          "C"
                                          "C++"
                                          ))
            (setq ctags-update-other-options (list
                                              "--kinds-all=*"
                                              "--fields=*"
                                              "--fields-all=*"
                                              "--extras=*"
                                              "--extras-all=*"
                                              ))
            ;; 针对不同的项目单独配置
            (setq ctags-update-project-option-alist '(
                                                      ("/mnt/Personal/Sources/emacs/" . (
                                                                                         ("--languages" . ("C" "C++" "Make" "EmacsLisp" "Autoconf" "Automake"))
                                                                                        ;; ("--exclude" . (".ccls" ".ccls-root"))
                                                                                        ;; ("OTHER" . ("--langmap=c++:+.h+.c"))
                                                                                         ))
                                                      )
                  )

其实我是打算做一个完全不用配置这些变量的系统。

秘密在于 readtags 读取 tags 文件时,会把 !_ 开头的视为特殊的(普通 tag 经过转义,保证开头不会长这个样子)。这叫做 pseudo tag 或者 ptag。

如果打开 uctags 生成的 tags 文件,会看到很多 ptag 记录了一些额外的信息。比如有个叫 !_TAG_PROC_CWD 的记录了 ctags 程序运行时的目录。这样我们就知道 tag 里面的相对目录的根目录了。

我的计划是让 Citre 生成完 tags 文件以后直接往里注入一个 CITRE_CTAGS_CMD ptag,大概长这个样子:

ctags|-f|%thisfile%|--fields=*|-R|./src

这样再次生成的时候,只要读这个 ptag 就知道命令行。这样我们完全不需要利用 tags 文件之外的信息来更新一个 tags 文件。

这个概念和增量更新的关系也很大,因为增量更新必须保证再次扫描的时候命令行参数和第一次扫描是一致的。uctags 的开发者和我现在就在研讨这个事情。

1 个赞

赞!

我是图省事儿,先有个可以用的再说。而且我是一份配置在多台电脑上用,写一次就完事儿了。

折腾了几晚,终于把新的 tags 文件生成和更新工具做出来了。

特点:

  • 命令行完全可定制,比如你可以把要用的外部库一起扫描了。
  • 命令行编辑完以后就直接写到 tags 文件里面,不需要复杂的配置文件或者 dir-local 变量。只要生成一次之后就可以一键更新。
  • 兼容 hasktags、gotags 等所有能够生成 tags 文件格式的工具。
  • tags 文件存储的位置非常灵活。
  • 比之前用起来稍微复杂一点点(相信我,只有一点点)

用法:

请读 README这个文档

还是请大家多多试用,多提意见!

4 个赞
  1. 第二步选择 cache 存在什么地方可以通过选项来自定义,因为每个人的喜好不一样,通过选项设置比每次都问一遍更方便

  2. In which dir you want to use tag file 这一步是啥意思? 为啥要问用户两次 root dir ?

  3. 大部分用户就选择一下语言就可以了,自定义buffer的方式,建议做到 C-u 的方式中,默认就选择一下语言,高级用户可以 C-u 然后 citre-update-this-tags-file

  4. 自定义buffer提供了 C-c C-c 确认就需要匹配一个 C-c C-k 取消,同时buffer就直接手写吧,语言选择 C-c l bug很多

  5. 原来的 citre-update-tags-file 命令不用的话可以删除了

总体来说新版的自由度高了,但是易用性差了,建议考虑上述方式减少问题数量,提升用户体验。

1 个赞

加一条:生成tag的buffer应该readonly

你指第一步吗?加了一个 citre-default-create-tags-file-scheme(在 develop 分支)。

就是说你想在哪个目录里用这个 tags 文件。当你编辑那个目录里的文件,Citre 就会帮你找到这个 tags 文件。一般想在整个工程里都用同一个 tags 文件的话就选工程的根目录就行。

我在 README 里加了一句:

Pick a directory in which to use the tags file. This means when you visit a file in that directory, this tags file is used for it.

我没有碰到问两次的情况。你指的是问一次 “In which dir you want to use tag file” 然后再问一次 root dir 吗?

root dir 就是指运行 Ctags 的时候,先 cd 到这里,然后再运行。我在文档里写了:

After you’ve decided where to save the tags file, Citre asks you to specify a root dir. It has 2 uses:

  • Ctags command runs in it, i.e., it’s the current working directory when running ctags.
  • In the command editing buffer, The path of added dir/files relative to the root dir are used, if they are inside the root dir.

我特别讨厌 Emacs 那个 C-u :rofl: 时间长了根本不记得哪个命令有 C-u

关于你说的这个,我现在把默认的命令改成了这样:

...
--languages=[add languages here]
...
-R
;; add dirs/files to scan here, one line per dir/file

最后一行被注释掉了,所以可以修改完语言那一行以后就提交。-R 后面没有文件名的话 Ctags 就会扫整个 root dir。

你也可以自定义 citre-edit-cmd-buf-default-cmd,直接把它写成一个合法的命令,这样大多数时候不需要编辑那个 buffer,直接提交就可以了。

谢谢提醒,已经加了(其实这种情况直接 kill-buffer 就行,不过用户感觉上可能不太对)

我没有碰到任何 bug。这个功能是要用 uctags 的,你的 ctags 指向的是 Universal Ctags 提供的 ctags 程序吗?不是的话要改一下 citre-ctags-program

是有用的:

2 more commands dealing with tags files are not mentioned in README:

  • citre-update-tags-file: Select a tags file to update
  • citre-create-tags-file: Create a new tags file.

You can also pass the name of a tagsfile as an argument to citre-update-tags-file, and it will update it. Based on this, you could write scripts to update tags files created using Citre.

哪个是「生成 tag 的 buffer」?

这些能弄成选项吗?每次创建tags的时候,问那么多问题真的不方便:

  1. 设置选项可以默认用全局cache存储
  2. 设置选项直接直接使用当前文件的project-root目录,不要问我在哪个目录使用和为哪个目录创建tags
  3. 设置选项不要弹出自定义命令,我就设置一下编程语言就可以了

如果有一个人选项编辑文件空闲后多少秒(类似auto-save.el)自动更新tags就好,计算机的资源应该用来帮助我们自动更新tags

提供一些选项吧,那样插件会更好用,也不会和作者的使用习惯冲突。

1 用 citre-default-create-tags-file-scheme 就可以了(目前在 develop 分支)

2 我可以做,但是目前的设定其实就是能检测到工程根目录的时候,这两个东西的默认值就都是工程根目录,所以你可以直接敲两下回车。即使这样你也觉得不够方便吗?创建 tags 文件并不是天天都要做的事情。

3 我知道这个是目前主要的不够快的地方。如果我做了 3,你觉得可以接受选两次目录吗?

自动更新的功能我自己完全不需要,弄了的话我反而担心在巨型工程上跑太久,期间会影响 Citre 的使用。如果你有好的实现,可以写在 wiki 里。

只要探测工程根目录的代码很准,能给我个选项不要问我吗?每次都是工程跟目录为啥要问?:joy:

我很懒,自定义的功能不是说不要,而是能否给个选项让我不要填?

选项是解决作者和用户使用习惯冲突的一种方法,爱咋用咋用,萝卜白菜各有所爱 :stuck_out_tongue:

1 个赞

其实单纯就是为了追求和命令行一样的可定制性。实际上也可能出现想在同一个工程的不同目录用不同的 tags 文件的情况。

你说的我理解了,会做的。

你要的功能,除了空闲时更新 tags file,在 develop 分支都已实现。

文档:GitHub - universal-ctags/citre at develop

配置:根据你的需要,建议这样设置:

(setq
 citre-default-create-tags-file-location 'global-cache
 citre-use-project-root-when-creating-tags t
 citre-prompt-language-for-ctags-command t)

如果你试用后觉得可以的话我就合到 master 了。

我试了一下develop分支,现在只问语言了,但是发现两个新问题:

  1. develop分支不是异步的? 创建tag把整个Emacs卡住了。
  2. Tags创建完会问 /home/andy/.cache/tags/!home!andy!emacs-application-framework!.tags doesn't contain recipe for updating. Edit its recipe? (y or n) n

我没有碰到这两个问题。按照我给的设置,选完语言就会直接更新,然后 message 告诉你完成了。

我后面在 develop 分支 force push 了几次,可不可以试下最新的版本?如果还是不行的话,请给一个能复现的 recipe。

Edit 我注意到 Citre 在工程下创建了一个 %TAGSFILE 文件,我修一下这个问题

关于补全的一个问题。补全触发的时候,光标会跳来跳去的,然后才弹出补全列表。

下面这个gif压缩了,但是还是能看出来会跳到407行,而且不止一次。大概看了下代码,像是在citre-get-symbol得到当前symbol的时候触发的这个行为。

citre_small

用最新的 develop 分支没有卡顿的问题,但是会在工程目录下创建一个 %TAGSFILE

那个是写入 ptag 的时候漏了一个百分号 :rofl: 已经修复了,麻烦再试一下

你推送补丁了吗? 为啥我又回到卡的状态了?