Citre: 先进的 Ctags 前端

大佬这个咋用的?我执行 consult-citre后 mini-buffer 提示一个 “#”,输入第二个字母的时候,会将会将第一个字母删除,把 “#” 删除后,可以输入单词,但一值不能返回结果

之前那个有些问题,下面这个是我现在的版本:

;; -*- lexical-binding: t; -*-

(require 'citre)
(require 'consult)
(require 'consult-xref)

(defun consult-citre-readtags--build-cmd
    (tagsfile &optional name match case-fold filter sorter action)
  "Build readtags command.
See `citre-readtags-get-tags' to know about NAME, MATCH, CASE-FOLD,
FILTER, and SORTER.  ACTION can be nil, to get regular tags, or
any valid actions in readtags, e.g., \"-D\", to get pseudo tags."
  (let* ((match (or match 'exact))
         (extras (concat
                  "-Ene"
                  (pcase match
                    ('exact "")
                    ('prefix "p")
                    (_ (error "Unexpected value of MATCH")))
                  (if case-fold "i" "")))
         (tagsfile (substring-no-properties tagsfile))
         (name (when name (substring-no-properties name)))
         (filter (citre-readtags--strip-text-property-in-list filter))
         (sorter (citre-readtags--strip-text-property-in-list sorter))
         inhibit-message
         cmd)
    ;; Program name
    (push (or citre-readtags-program "readtags") cmd)
    ;; Read from this tags file
    (push "-t" cmd)
    (push (file-local-name tagsfile) cmd)
    ;; Filter expression
    (when filter (push "-Q" cmd) (push (format "%S" filter) cmd))
    (when sorter (push "-S" cmd) (push (format "%S" sorter) cmd))
    ;; Extra arguments
    (push extras cmd)
    ;; Action
    (if action (push action cmd)
      (if (or (null name) (string-empty-p name))
          (push "-l" cmd)
        (push "-" cmd)
        (push name cmd)))
    (nreverse cmd)))

(defun consult-citre-readtags--builder (input)
  (pcase-let* ((`(,arg . ,opts) (consult--command-split input))
               (`(,re . ,hl) (funcall consult--regexp-compiler arg 'extended t)))
    (setq re (consult--join-regexps re 'extended))
    (cons
     (append (consult-citre-readtags--build-cmd
              (citre-tags-file-path)
              nil nil t
              `((string->regexp ,re :case-fold true) $name)
              nil
              (car-safe opts))
             (cdr-safe opts))
     hl)
    ))

(defun consult-citre-readtags--format (info lines)
  (mapcar (lambda (line)
            (let* ((tag (citre-readtags--parse-line
                         line
                         info
                         '(name input pattern line kind) '() '()
                         '(ext-abspath ext-kind-full) '() '() t))
                   (group (citre-get-tag-field 'ext-abspath tag))
                   (line (citre-get-tag-field 'line tag))
                   (cand (consult--format-file-line-match
                          group
                          line
                          (citre-make-tag-str tag nil
                                              '(annotation :prefix "(" :suffix ")"
                                                           ;; In xref buffer, we may want to jump to
                                                           ;; the tags with these anonymous names.
                                                           :full-anonymous-name t)
                                              '(content :ensure t)))))
              (add-text-properties 0 (length cand) `(consult-citre-tag ,tag consult--prefix-group ,group) cand)
              cand))
          lines))

;;;###autoload
(defun consult-citre (initial)
  "Read a tag from minibuffer and jump to the tag."
  (interactive "P")
  (let ((info (citre-readtags-tags-file-info (citre-tags-file-path))))
    (xref-pop-to-location
     (consult--read
      (consult--async-command
          #'consult-citre-readtags--builder
        (consult--async-transform consult-citre-readtags--format info)
        (consult--async-highlight #'consult-citre-readtags--builder))
      :prompt "Tag: "
      :keymap consult-async-map
      :require-match t
      :category 'consult-citre
      :initial (consult--async-split-initial initial)
      :group #'consult--prefix-group
      :state (consult-xref--preview #'switch-to-buffer)
      :lookup (lambda (&rest args)
                (when-let ((tag (apply #'consult--lookup-prop 'consult-citre-tag args)))
                  (citre-xref--make-object tag)))))))

(with-eval-after-load 'embark
  (defvar embark-exporters-alist)

  (defun consult-citre--embark-export-xref (items)
    "Create an xref buffer listing ITEMS."
    (let ((xrefs))
      (dolist-with-progress-reporter (item items)
          "Exporting Xrefs..."
        (redisplay)
        (push  (citre-xref--make-object (get-text-property 0 'consult-citre-tag item))
               xrefs))
      (set-buffer
       (xref--show-xref-buffer
        (lambda () nil)
        `((fetched-xrefs . ,xrefs)
          (window . ,(embark--target-window))
          (auto-jump . ,xref-auto-jump-to-first-xref)
          (display-action))))))
  (setf (alist-get 'consult-citre embark-exporters-alist)
        #'consult-citre--embark-export-xref))

(provide 'consult-citre)



1 个赞

@Chingyat,你好,将这段代码复制到了我的配置文件,但好像无法工作。

请问是否还有其它配置要求或依赖?

操作步骤:

打开一个项目文件buffer,执行 M-x consult-citre ,能出现minibuf,并提示Tag: #

我在 # 号后面输入了一个symbol字符串(直接在命令行通过readtags是可以查到这个symbol的)

期望能出现匹配的candidates列表,但是没有任何内容出现。如果直接回车,则提示 [Match required]

PS.

  • 项目tag文件是肯定存在的,我使用citre其它命令都是工作正常的,比如citre-jump/citre-peek

  • consult包也是安装好了的,其它consult命令都可以正常工作,比如consult-man/consult-grep

有没有开启 lexical-binding?

是指文件头部吗?有的,我是将你的代码直接存为文件 consult-citre.el 然后在init.el文件require它。

(require 'consult-citre)

;; -*- lexical-binding: t; -*-
;; -*- lexical-binding: t; -*-

(require 'citre)
(require 'consult)
(require 'consult-xref)

...

(provide 'consult-citre)

Hello, 想请教一下 citre 生成 tags 的时候会去读取 .gitignore 去忽略目录吗?

目前我用了一下好像是不会的,不知道是否有配置项?

它把 node_modules 也读进去了,最终的 tags 都 400 多 M,有点可怕。

看了看文档,我也可以自己写一个 --exclude 去忽略对吧?

如果可以的话,觉得自动读取 .gitignore 是比较方便的,不用去自己额外配置 exclude

如果只能自己配置,也没问题,但看没在的 prompt,里面没有关于 exclude 如何配置的提示。

是否可以增加一些提示,如何配置,以及增加快捷键,如 C-c C-e 之类的,模仿 C-c C-f 去读取目录帮我写好配置呢?

我尝试去增加 --exclude 去忽略,但我保存不下去,它读错了 tags 的路径,读回来是个目录:

这是因为执行 edit-recipe 的时候,它要我选之前的 tags 文件,但我选不了,我只能选 ./ 或 …/

highlight 没法移动到文件那里去选择,只能选到 ./

似乎是那个读文件的 prompt 吧 xxxx.tags 当作了目录了,我需要回到 tags 目录,直接选择文件,那就可以选中 tags 文件。但是如果我在 tags 目录,按 tab 补全,会把 xxxx.tags 当作目录。默认执行 recipe edit 也是把 xxx.tags 当作目录了…

关于 --exclude 的配置,倒是可以通过覆盖 citre-edit-cmd-buf-default-cmd ,自己加入一下常用的 exclude 的目录。

spacemacs下有相同问题,我就先选 “…”,再进目录选对应的tags文件

如果 exclude的东西较多,可参考Option files — Universal Ctags 0.3.0 documentation 的写法,不用直接放命令里面,还方便其他项目用

原来你也有这个问题,总觉得让人有些困扰。

thanks,我试试去