Citre: 先进的 Ctags 前端

写一个 UI 帮用户装配命令行倒不是难事,难的是 tags 文件需要反复生成。遂,这个命令行要保存到哪?

如果用户想在一个工程的不同部分用不同的 tags 文件(Citre 是可以做到的,见 citre-tags-file-alist),是不是还要提供分别更新的功能呢?

如果用户不用 uctags,而是 hasktags、gotags 怎么办呢?

我在设计的时候考虑到的小问题还要更多。每一个其实都不难解决,可是都解决掉的话,连我自己都不想用这个工具了。

所以最后做成了现在这样极简的样子。

我认为生成 tags 文件应该是构建系统干的事。Citre 提供的东西可以开箱即用,能覆盖 80% 的场景就可以了。

3 个赞

好的 感谢正在努力尝试中

另外,用 “~/.cache/emacs-citre/” 作为默认 cache 目录,是不是更直观一点?

这个自己改就好啦

不过关于你说的这个,其实 Universal Ctags 有计划把命令行参数也写到 tags 文件里,这样可以保证增量更新时参数一致。如果这个做出来了,Citre 就不需要设计别的工具了,像你说的这样把命令行装配出来,然后只管第一次生成就行。

Edit: 我发现其实可以直接让 Citre 往 tags 文件里注入 pseudo tags,这样就不用等 uctags 帮我们实现了:Request: pseudo tags to record command line arguments · Issue #3085 · universal-ctags/ctags · GitHub

Ctags 有辦法做到 fuzzy search 嗎? 像是 lsp workspace symbol 可以列出所有symbol 在用 completion engine (helm, ivy) 補全

citre-jump 目前需要 cursor 在 symbol上 有時想找某個 symbol 但不知他在哪個 file or 哪個file 引用他

在空白处用一下 xref-find-definitions 应该就可以。

你说的这个需求很有价值,我觉得 xref 的界面还是过于简陋。一直想做一个交互式过滤 tags 文件的工具,参见 Citre: 先进的 Ctags 前端 - #24,来自 kinono

目前对于怎么实现还是没有太好的想法。初步计划是这样:

  • 先给 citre-peek 增加一个过滤工具,当找出太多定义以后可以用这个来排除掉一部分。初步探索一下这种 UI 应该怎么设计。
  • 做一个模糊补全工具,像上面说的这样可以交互式过滤,可能基于 consult 或 completing-read(当然不依赖外部库是最好的)。
  • 把这个补全工具拓展一下,使得过滤出来的结果可以插入到当前 buffer(补全),可以跳转过去,也可以转换成一个 citre-peek 或 xref 会话。

这就是我设想中 Citre 的终极形态,可以最大限度地利用 tags 记录的信息和 readtags 提供的过滤功能。

1 个赞

试试(setq projectile-tags-command "ctags -R -f \"%s\" %s \"%s\"")

试用了Citre,感觉真不错,tags的使用体验提升和很多; 很喜欢Citre-peek的功能,可是不知道打开Citre-peek窗口后,咋关闭呢?而且,咋能在peek窗口中移动光标啊?

read the lovely manual

可不可以增加一个 citre-mode-map 呢,这样可以不污染全局快捷键设置。

citre-mode 提供的是 capf、xref 和 imenu 的整合,这些组件在 Emacs 里都有标准的快捷键。citre-mode 不需要绑定自己的快捷键。

更新后很好用,不错不错

: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