大佬,公司开发服务器上多人使用 citre时,citre-tags–imenu-tags-from-temp-tags-file 似乎不会主动删除其产生的 /tmp/citre-imenu.tags,导致多人使用的时候该文件不能被其他人更新,有解决方法么?
应该修好了,您看一下。
大佬我按照文档配置了一下,但它似乎不能正常工作
系统版本:MacOS
Emacs版本:emacs-plus@29 doom emacs
ctags版本:
Universal Ctags 6.0.0(p6.0.20230219.0), Copyright (C) 2015-2022 Universal Ctags Team
Universal Ctags is derived from Exuberant Ctags.
Exuberant Ctags 5.8, Copyright (C) 1996-2009 Darren Hiebert
Compiled: Feb 22 2023, 00:49:05
URL: https://ctags.io/
Output version: 0.0
Optional compiled features: +wildcards, +regex, +gnulib_fnmatch, +gnulib_regex, +iconv, +option-directory, +xpath, +json, +interactive, +yaml, +case-insensitive-filenames, +packcc, +optscript
company-backends如下:
((:separate company-capf company-yasnippet))
在一个打开的html文件中不能正确提示和补全btn-primary等样式
但是tags文件看起来是正常的:
我同时还使用了lsp-mode,但我感觉应该不是lsp的问题,因为lsp在字符串里面没有补全信息
BTW, 上面能补全的内容可以使用citre-jump
进行跳转:
配置文件(config.el
)中只写了两行:
(require 'citre)
(require 'citre-config)
我仔细看了,但是补全变成了这样:
有些elisp的语法看的不是很懂,就直接复制粘贴了,下面是粘贴的内容(省略了一下):
(define-advice xref--create-fetcher (:around (-fn &rest -args) fallback)
(defun lsp-citre-capf-function ()
(defun enable-lsp-citre-capf-backend ()
(add-hook 'citre-mode-hook #'enable-lsp-citre-capf-backend)
(defmacro citre-backend-to-company-backend (backend)
(citre-backend-to-company-backend tags)
(citre-backend-to-company-backend global)
(setq company-backends '((company-capf ...
请问是这样弄吗,实在是不太懂,本来是想用lsp-bridge的citre,但是lsp-bridge安装在doom上有很多奇怪的问题,就想着切换到citre来用,奈何两条路都不好走
你可以参考下我以前发的帖 怎么在 doom 里用 lsp-bridge
或者在 doom 里用 eglot,
(defalias #'my-eglot-citre-capf
(cape-super-capf #'eglot-completion-at-point #'citre-completion-at-point))
(add-hook 'eglot-managed-mode-hook
(defun my-toggle-citre-eglot-capf ()
(if (eglot-managed-p)
(add-to-list 'completion-at-point-functions #'my-eglot-citre-capf))))
这个snippet也是我写的
应该是因为你的 lsp 的补全项太多了,然后 citre 的补全都压在最底下。
citre-auto-enable-citre-mode
和 magit
一起用的话,在打开 git 项目中的文件的时候,似乎经常会卡住,然后只能按 C-g
退出.
这是我的配置:
(defvar bootstrap-version)
(let ((bootstrap-file
(expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
(bootstrap-version 6))
(unless (file-exists-p bootstrap-file)
(with-current-buffer
(url-retrieve-synchronously
"https://raw.githubusercontent.com/radian-software/straight.el/develop/install.el"
'silent 'inhibit-cookies)
(goto-char (point-max))
(eval-print-last-sexp)))
(load bootstrap-file nil 'nomessage))
(straight-use-package 'magit)
(straight-use-package 'citre)
(require 'citre)
(require 'magit)
(add-hook 'find-file-hook #'citre-auto-enable-citre-mode)
操作:
- 把上面的配置文件保存为 test-init.el
- 启动 emacs -Q -l test-init.el
- 打开 test-init.el
- 光标移动到
straight-use-package
上,按M-.
。
正常情况下会打开 straight.el 文件,但实际上会卡住,只能按 C-g
退出。
这是 backtrace:
Debugger entered--Lisp error: (quit)
accept-process-output()
citre-get-output-lines(("global" "--print-dbpath"))
citre-global--get-output-lines(("--print-dbpath"))
#f(compiled-function (dir) #<bytecode -0xbcef4a6e16783e2>)(nil)
citre-global-dbpath()
citre-backend-usable-p(global)
citre-auto-enable-citre-mode()
run-hooks(find-file-hook)
after-find-file(nil t)
find-file-noselect-1(#<buffer straight.el> "~/.emacs.d/straight/repos/straight.el/straight.el" nil nil "~/.emacs.d/straight/repos/straight.el/straight.el" (33565986 2080))
find-file-noselect("/home/zhengyi/.emacs.d/straight/repos/straight.el/...")
find-function-search-for-symbol(straight-use-package nil "/home/zhengyi/.emacs.d/straight/repos/straight.el/...")
#f(compiled-function (l) #<bytecode -0x707c4b8ec200a20>)(#s(xref-elisp-location :symbol straight-use-package :type nil :file "/home/zhengyi/.emacs.d/straight/repos/straight.el/..."))
apply(#f(compiled-function (l) #<bytecode -0x707c4b8ec200a20>) #s(xref-elisp-location :symbol straight-use-package :type nil :file "/home/zhengyi/.emacs.d/straight/repos/straight.el/...") nil)
xref-location-marker(#s(xref-elisp-location :symbol straight-use-package :type nil :file "/home/zhengyi/.emacs.d/straight/repos/straight.el/..."))
xref-pop-to-location(#s(xref-item :summary #("(defun straight-use-package)" 1 6 (face font-lock-keyword-face) 7 27 (face font-lock-function-name-face)) :location #s(xref-elisp-location :symbol straight-use-package :type nil :file "/home/zhengyi/.emacs.d/straight/repos/straight.el/...")) nil)
xref-show-definitions-buffer(#f(compiled-function () #<bytecode -0x3ac2916c69a9850>) ((window . #<window 3 on init.el>) (display-action) (auto-jump)))
xref--show-defs(#f(compiled-function () #<bytecode -0x3ac2916c69a9850>) nil)
xref--find-definitions(#("straight-use-package" 0 20 (pos 960)) nil)
xref-find-definitions(#("straight-use-package" 0 20 (pos 960)))
funcall-interactively(xref-find-definitions #("straight-use-package" 0 20 (pos 960)))
call-interactively(xref-find-definitions nil nil)
command-execute(xref-find-definitions)
继续借大佬的楼请教一下,糊了一个保存文件后自动更新 tags的轮子,为了不卡,调用了shell,目前几乎可以工作,使用中有下面的问题。
下面的代码中,如果在 get-ptag-from-cache 中直接调用 set-ptag-to-cache,emacs就会被卡住,但 M-x 执行 set-ptag-to-cache 时,又没有问题,请大佬解惑
(defun citre-auto-update-get-ptag-from-cache (ptag)
"return ptag's value from `citre-auto-update-ptag-cache';
or update cache if value is nil"
(let* ((project-root (funcall citre-project-root-function))
(pvalue (assoc-default ptag (gethash project-root citre-auto-update-ptag-cache))))
(unless pvalue
(message "Please run `citre-auto-update-set-ptag-to-cache', and will update tagsfile next time.")
;; (citre-auto-update-set-ptag-to-cache) ;; if automatic do this, eamcs been blocked, UNKNOWN CASE
)
pvalue))
(defun citre-auto-update-set-ptag-to-cache ()
"read CITRE_CMD and TAG_PROC_CWD from tagsfile, write to `citre-auto-update-ptag-cache'.
Because of ctags runing on a async sub-process in `citre-update-this-tags-file', so can't
run this function immediately.
"
(interactive)
(let* ((tagsfile (citre-tags-file-path))
(cmd-ptag (citre--get-pseudo-tag-value "CITRE_CMD" tagsfile))
(cwd-ptag (citre--get-pseudo-tag-value "TAG_PROC_CWD" tagsfile))
(project-root (funcall citre-project-root-function)))
(puthash project-root
(list (cons "CITRE_CMD" cmd-ptag) (cons "TAG_PROC_CWD" cwd-ptag))
citre-auto-update-ptag-cache)))
感谢作者,我想用它看c++代码,首次输入 citre-jump+的时候转到定义处,不要弹出框让我选,再次输入的时候就在.h 和.cpp里来回切换,不知道这个好实现吗
大佬好久不出现了,继续在大佬的基础上造轮子,利用 read-string查询任何tag,match 使用 substr 方法:
(defun citre-jump-from-input ()
"Like `citre-jump', but get symbol `read-string'
"
(interactive)
(let* ((symbol (read-string "symbol: "))
(tagsfile (citre-tags-file-path))
(buf (current-buffer))
(defs (citre-tags-get-tags
tagsfile symbol `substr
:filter (or (citre-tags--get-value-in-language-alist
:definition-filter symbol)
(citre-tags-definition-default-filter symbol))
:sorter (or (citre-tags--get-value-in-language-alist
:definition-sorter symbol)
citre-tags-definition-default-sorter)
:require '(name ext-abspath pattern)
:optional '(ext-kind-full line typeref scope extras)))
(result (cdr defs)))
(if (null defs)
(user-error "Can't find definition: %s" symbol))
(citre-jump-show defs)
(citre-after-jump-action buf)))
巧了,我刚用 consult 糊了个类似的功能 。
;; -*- lexical-binding: t; -*-
(require 'citre)
(require 'consult)
(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
(consult-citre-readtags--build-cmd
(citre-tags-file-path)
nil nil t
`((string->regexp ,re :case-fold true) $name)
nil
nil)
hl)
))
(defun consult-citre-readtags--format (lines)
(mapcar (lambda (line)
(let* ((tag (citre-readtags--parse-line
line
(citre-readtags-tags-file-info (citre-tags-file-path))
'(name input pattern line kind) '() '()
'(ext-abspath ext-kind-full) '() '() t
))
(str (citre-get-tag-field 'name tag)))
(propertize str 'citre-tag tag))
)
lines))
(defun consult-citre-readtags--annotate (root str)
(let ((tag (get-text-property 0 'citre-tag str)))
(consult--annotate-align str (citre-make-tag-str tag nil
'(annotation)
`(location :suffix ":" :root ,root)
'(content :ensure t)))))
;;;###autoload
(defun consult-citre (initial)
"Read a tag from minibuffer and jump to the tag."
(interactive "P")
(citre-goto-tag
(consult--read
(consult--async-command #'consult-citre-readtags--builder
(consult--async-transform consult-citre-readtags--format)
(consult--async-highlight #'consult-citre-readtags--builder))
:prompt "Tag: "
:keymap consult-async-map
:annotate (apply-partially #'consult-citre-readtags--annotate (citre-project-root))
:require-match t
:category 'citre-tag
:initial (consult--async-split-initial initial)
:lookup (apply-partially #'consult--lookup-prop 'citre-tag))))
哇塞,这个高级,抄了抄了 强调文本
大佬这个实现的好啊,试用了一下 使用体验很好。又没有考虑把它抽出来做个包?这样我肯定给个星星。
又改了改,使用 consult-xref 的一些设施,支持 preview 和 embark-export.
;; -*- 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 (lines)
(let ((root (citre-project-root))
(info (citre-readtags-tags-file-info (citre-tags-file-path))))
(mapcar (lambda (line)
(let* ((tag (citre-readtags--parse-line
line
info
'(name input pattern line kind) '() '()
'(ext-abspath ext-kind-full) '() '() t
))
(xref (citre-xref--make-object tag))
(loc (xref-item-location xref))
(group (if (fboundp 'xref--group-name-for-display)
;; This function is available in xref 1.3.2
(xref--group-name-for-display
(xref-location-group loc) root)
(xref-location-group loc)))
(cand (consult--format-file-line-match
group
(or (xref-location-line loc) 0)
(xref-item-summary xref))))
(add-text-properties 0 1 `(consult-xref ,xref 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* ((candidates (consult--async-command
#'consult-citre-readtags--builder
(consult--async-transform consult-citre-readtags--format)
(consult--async-highlight #'consult-citre-readtags--builder)))
(consult-xref--fetcher (lambda ()
(mapcar (apply-partially #'get-text-property 0 'consult-xref)
(funcall candidates nil)))))
(xref-pop-to-location
(consult--read
candidates
:prompt "Tag: "
:keymap consult-async-map
:require-match t
:category 'consult-xref
:initial (consult--async-split-initial initial)
:group #'consult--prefix-group
:state
(consult-xref--preview #'switch-to-buffer)
:lookup (apply-partially #'consult--lookup-prop 'consult-xref)))))
@milanglacier @my2817 可以看看。
另外我不打算把它做成个包,我没有太多时间去维护它
不错啊 用起来看起来很完美
大佬这个咋用的?我执行 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)
@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