Citre: 先进的 Ctags 前端

试试(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」?

这些能弄成选项吗?每次创建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