kinono
2022 年12 月 2 日 16:38
631
谢谢,我看了一下 cscope-database-regexps
,不确定自己完全理解了,但看上去就是可以给一个目录指定多个 cscope 数据库,然后查符号的时候就挨个查,直到有结果为止。我觉得这个就是有我在楼下说的问题
因为很多语言是允许符号重名的,您说的这种方案可能遇到「我知道我想查一个库里面的符号,但 Citre 只给我自己代码里面的同名符号」的问题。
当然把所有 tags 文件的结果都合在一起也是一个办法,不过那样的话后续过滤也要麻烦一些(用 citre-jump
的话),我觉得比起让用户先挑一个 tags 文件也没有少一点负担。
在vim里面就是直接把所有available的symbol给你列出来,不管是在哪个tags里的,让你选择一个location去跳转,也不会显示这两个symbol来自哪个tags文件,就直接显示symbol的定义的位置。这个截图是一个例子,这两个定义来自不同的两个tags文件
假设使用场景是需要查第三方库的不同类的同名方法名定义的话,这样确实效率可能会很低,因为很可能会出现可选项占满整个屏幕根本选不过来的情况。按照你的想法,先选tags(先定位第三方库),再选定义可能会效率高一些。
至于补全的话,我觉得应该直接搜索所有的tags文件,把所有匹配到的符号都列入补全里。同一个符号的上下文信息不同的问题,之前citre是怎么处理的现在就怎么处理就好。(原生vim的处理方式是同名的符号只显示一个candidate,不考虑同名symbol上下文不同的情形)
是的。所以我感觉如果支持多个tags的话,应该是需要两个功能:
在多个tags里面全部都查找,把所有找到的都显示出来。
按顺序查找。
kinono:
然后查符号的时候就挨个查,直到有结果为止
cscope里面,应该是不是查到为止。而是会全部给显示出来。
如果是多个tags,我觉得不需要实现“查到为止”也就是顺序查找这个功能。因为会有您上面提到的问题。
所以,我觉得就参考cscope这样应该就够了。如果一个项目只需要一个tag,默认还是按当前citre找tags的逻辑就够用。
如果像一个项目里面还需要另一个项目的tags,其实目前也是可以的,就是在做tags的时候,把另一个项目的tag也做到一起,做一个大的tag。
但是可能会导致空间的浪费。比如我A项目需要查jdk定义的东西,B项目也需要查。那jdk的tags就需要在A项目的tag和B项目的tag里面都存在。
我理解这种情况下,其实就可以单独为A,B和jdk都建立自己的tags。然后为A项目做配置,在A项目里面的时候,查A和jdk的tags,在B项目里面的时候,查B和jdk的tags。在jdk里面,不配置就只查jdk的tag。这样的话,jdk的tag其实就只需要在硬盘上存一份。
以上是我个人的想法哈,不知道说清楚没有
my2817
2022 年12 月 5 日 03:37
635
@kinono hi, 发现一个问题,工作区使用git submodule进行组织多个仓库,配置如下
citre version: citre-20221202.531
(custom-set-variables '(citre-completion-backends '(tags global))
'(citre-find-definition-backends '(tags global))
'(citre-find-reference-backends '(tags global))
'(citre-tags-in-buffer-backends '(tags global))
'(citre-auto-enable-citre-mode-backends '(tags global)))
如果文件放在submodule的根目录, citre-imenu-create-index-function()
可以正常返回值
如果放在 submodule 的二级目录、或更深的目录下,tags文件中可找到相关定义,但 citre-imenu-create-index-function()
如下
citre-get-output-lines: Process global exits 3:
global: GTAGS not found.
kinono
2022 年12 月 5 日 03:56
636
tags 文件怎么生成的?放在哪个位置?这是你全部的配置吗?
我盲猜修改 citre-project-root-function
让它能在 submodule 的文件中返回根目录就好了。或者直接在根目录里面生成 tags 或者 .tags 文件应该也可以。
my2817
2022 年12 月 5 日 04:03
637
还真是,把 submodule 的tags文件删除后就正常
PS: tags 放在 ~/.catch/tags
目录
(setq citre-edit-cmd-buf-default-cmd
"ctags
-o
%TAGSFILE%
--kinds-all=all
--fields=*
--extras=*
--extras=-{qualified}
-R
./
" )
大佬,我刚开始使用,遇到点问题请教。
我的配置是照抄官网主页的,
(use-package citre
:defer t
:init
(require 'citre-config)
(global-set-key (kbd "C-x c j") 'citre-jump)
(global-set-key (kbd "C-x c J") 'citre-jump-back)
(global-set-key (kbd "C-x c p") 'citre-ace-peek)
(global-set-key (kbd "C-x c u") 'citre-update-this-tags-file)
:config
(setq citre-edit-cmd-buf-default-cmd "ctags\n-o\n%TAGSFILE%\n;; programming languages to be scanned, or \"all\" for all supported languages\n--languages=all\n--kinds-all=*\n--fields=*\n--extras=*\n--exclude=**/.ccls-cache/*\n-R\n;; add dirs/files to scan here, one line per dir/file\n")
(setq
citre-project-root-function #'projectile-project-root.
citre-default-create-tags-file-location 'global-cache
citre-use-project-root-when-creating-tags t
citre-prompt-language-for-ctags-command t
citre-auto-enable-citre-mode-modes '(prog-mode)))
由于citre-create-tags-file
自动生成的ctags command line参数不符合我需求(我想都加上--exclude=xxx
),于是我用citre-edit-tags-file-recipe
编辑,弹出buffer,编辑好之后我C-c C-c提交,minibuffer提示:Opening output file: Is a directory, /home/dark/.cache/tags/
,这个我要如何处理呢?
生成的tags文件:
drwxr-xr-x 1 dark dark 4096 Dec 7 01:29 .
drwxr-xr-x 1 dark dark 4096 Dec 7 01:02 ..
-rw-r--r-- 1 dark dark 58973506 Dec 7 01:29 '!d!Source!MCU!AC701N!ac701n!.tags'
➜ tags pwd
/home/dark/.cache/tags
kinono
2022 年12 月 6 日 18:10
639
可能是个 bug,我醒来看下吧。您如果急用的话可以先把
citre-default-create-tags-file-location 'global-cache
这行拿掉,然后在工程根目录生成 tags。
工程目录下生成.tags/tags(我不记得是选哪个选项了)也会有同样的问题导致不可以commit编辑
工程目录下直接生成tags文件就不会有这个现象,麻烦你有空时分析一下了
不能在输入 .
或 ->
的时候触发补全吗?
;; init.el
(require 'citre)
(require 'citre-config)
(require 'company)
(add-hook 'c-mode-hook #'company-mode)
(setq company-minimum-prefix-length 0)
macOS 10.13.6
Emacs 28 & 29
company-20221206.2122
citre-2022-12-05 (86c346b)
kinono
2022 年12 月 7 日 09:23
642
我用您的配置试了一下,由于我没有装 projectile 所以就把那一行去掉了,其他的都是一样的。
在我这里可以正常编辑,提交之后也可以更新,没有任何问题。在工程目录下生成 .tags
文件的话也可以正常编辑。
建议您先更新下 citre 版本,如果仍然有问题,请在干净的 Emacs 环境下($ emacs -Q
)提供一个复现的详细步骤。
kinono
2022 年12 月 7 日 09:29
643
不能在输入 .
或 ->
的时候触发补全吗?
不能的。Citre 只是搜索 tags 文件里面,以光标下面符号作为前缀的符号。针对 C 语言有一些优化,比如 .
和 ->
后面,member
符号会排序在前面,但做不到辨认 .
前面是哪个 struct,所以不能做到敲个 .
就自动补全,这需要语义分析。
Citre 的自动补全其实主要是起个拼写检查的作用。我计划做一个搜索 tags 文件的工具,让用户可以问「某个 struct 的所有 member」之类的问题,这样就可以稍微弥补一些 tags 流工具不够智能的缺陷。
1 个赞
这个好。期待啊。lsp那些,智能是智能,但是一方面对机器的cpu这些消耗大。还有一方面就还是感觉不够快。要等。等就是中断。就影响效率。反正机器一定不能比人慢。让人等机器就不行。
citre我就觉得它快。查定义基本可以做到心随形动。
3 个赞
我尝试了一下用emacs -Q来安装use-package等再测试了一下,在没有projectile的情况下,确实没有复现问题。没有试安装projectile后的情况,目前tags放项目根目录也能用,暂时不纠结了,感谢大佬
my2817
2022 年12 月 12 日 08:16
646
hi, 大佬,在submodule中使用还是有问题,请帮忙看看,信息如下。仅在dotfile目录中生成tags文件,tags 文件放在 ~/.catch/tags
目录中
目录结构:
dotfile
|-- .emacs.d
|-- .spacemacs.d
tags文件内容至少包含下面两行
hy/pre-init-pyenv-mode ./.emacs.d/layers/+lang/hy/packages.el /^(defun hy\/pre-init-pyenv-mode ()$/;" kind:function line:98 language:EmacsLisp roles:def
my-config/post-init-cc-mode ./.spacemacs.d/layers/my-config/packages.el /^(defun my-config\/post-init-cc-mode ()$/;" kind:function line:1274 language:EmacsLisp roles:def
目前 debug 抓到的 readtags 执行的命令如下,不能返回 .spacemacs.d
的相关内容
readtags -t "/home/foo/.cache/tags/\!home\!foo\!dotfile\!.tags" \
-Q "(and (or (and \$input \
(eq\\? \$input \"/home/foo/dotfile/.spacemacs.d/layers/my-config/packages.el\")) \
(and \$input (eq\\? \$input \".spacemacs.d/layers/my-config/packages.el\")) \
(and \$input ((string->regexp \"(^|/)..?/packages\\\\.el\$\" :case-fold false) \$input))) \
(not (or (and \$extras \
((string->regexp \"(^|,) ?(anonymous|inputFile)(,|\$)\" :case-fold false) \$extras)) \
(and \$kind \
((string->regexp \"^(file|F)\$\" :case-fold false) \$kind)))))" \
-S "(<or> (if (and \$line &line) (<> \$line &line) 0))"\
-Ene -l
kinono
2022 年12 月 12 日 11:43
647
您是在用 imenu 吗?我试了一下我这里是可以的。
首先编一个测试用的 tags 文件
$ pwd
/home/kino/ctags-file-field-test
$ cat test.tags
!_TAG_PROC_CWD /home/foo/dotfile/ //;"
hy/pre-init-pyenv-mode ./.emacs.d/layers/+lang/hy/packages.el /^(defun hy\/pre-init-pyenv-mode ()$/;" kind:function line:98 language:EmacsLisp roles:def
my-config/post-init-cc-mode ./.spacemacs.d/layers/my-config/packages.el /^(defun my-config\/post-init-cc-mode ()$/;" kind:function line:1274 language:EmacsLisp roles:def
用 Citre 读 imenu 所需的 tags,是可以读出来的
(let ((citre--tags-file "~/ctags-file-field-test/test.tags")
(buffer-file-name "/home/foo/dotfile/.spacemacs.d/layers/my-config/packages.el"))
(citre-tags--imenu-tags-from-tags-file))
;; =>(#s(hash-table
;; size 16 test eq rehash-size 1.5 rehash-threshold 0.8125 data
;; (name "hy/pre-init-pyenv-mode" pattern "/^(defun hy\\/pre-init-pyenv-mode ()$/;\"" line "98" ext-kind-full "function")))
按照 citre-tags--imenu-tags-from-tags-file
内部构建 filter 的方式,构建出来的 filter 和您提供的是一样的
`(and ,(citre-readtags-filter-input
"/home/foo/dotfile/.spacemacs.d/layers/my-config/packages.el"
"~/ctags-file-field-test/test.tags")
(not (or ,(citre-readtags-filter
'extras
'("anonymous" "inputFile")
'csv-contain)
,(citre-readtags-filter-kind "file"))))
;; => (and
;; (or
;; (and $input
;; (eq\? $input "/home/foo/dotfile/.spacemacs.d/layers/my-config/packages.el"))
;; (and $input
;; (eq\? $input ".spacemacs.d/layers/my-config/packages.el"))
;; (and $input
;; ((string->regexp "(^|/)..?/packages\\.el$" :case-fold false)
;; $input)))
;; (not
;; (or
;; (and $extras
;; ((string->regexp "(^|,) ?(anonymous|inputFile)(,|$)" :case-fold false)
;; $extras))
;; (and $kind
;; ((string->regexp "^(file|F)$" :case-fold false)
;; $kind)))))
my2817
2022 年12 月 12 日 13:14
648
刚发现两台电脑上的表现不一样,现在用的电脑是正常的,明天再到有问题的电脑上查查看
my2817
2022 年12 月 13 日 01:48
649
大佬,找到差异啦,如果用下面的命令,引入外部项目
“./” 表示当前项目,则会导致生成的 “$input” 的每一行前面都有前缀:“./”, 此时中使用 imenu 就不正常
如果把 “./” 换成 “.”,生成的 tags 文件中 “$input” 就不会有前缀 “./”,imenu 就可正常使用
ctags
-o
%TAGSFILE%
--languages=all
--kinds-all=*
--fields=*
--extras=*
-R
./
/external/lib/used/in/the/project/
kinono
2022 年12 月 13 日 03:14
650
这应该是我已经修过的问题,可能您现在用的电脑上装的是比较旧的版本?
tags 文件里面的路径可以是各种形式的相对路径,比如说您给的路径是 ./../this-dir/
的话,tags 文件也会原样抄过去,但仍然表示当前目录。citre 生成的 filter 里面的这部分:
(string->regexp "(^|/)..?/packages\\.el$" :case-fold false)
就是说如果路径中有 .
或者 ..
这样的目录的话,就认为只要最后的文件名是 package.el
,就算和 /home/foo/dotfile/.spacemacs.d/layers/my-config/packages.el
是匹配的。这其实是一个比较糟糕的方法,但在 readtags 不提供文件名比较运算的前提下也只能这样。
Readtags 后面会加一个打印绝对路径的选项(https://github.com/universal-ctags/ctags/pull/3304 ),等这个实现之后就不需要这些 hack 了。