Citre: 先进的 Ctags 前端

好的 感谢正在努力尝试中

另外,用 “~/.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

你指第一步吗?加了一个 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」?