为什么 emacs 在 windows 下总是查找不到引用

发布时间:2024年01月06日

为什么emacswindows下总是查找不到引用

最近迷上了emacsTAGS,因为它比使用clangd阅读源代码来得更快,可能还更准确。但是现实情况是cygwinTAGS用起来很好,windows上只能用M-.来查找定义,想要查找引用却始终失败。

在这里插入图片描述
更完整的*Messages*的错误显示:

Searching d:/demos/emacs-28.2/src/... done
xref--not-found-error: No references found for: stack_bottom
  1. 生成TAGS的方法是:在编译emacs完成后,顺便运行一下make TAGS即可。
  2. 我用到的edebug的一些快捷键:C-u C-M-x-设置edebugC-M-x-取消edebugSPC-单步步过,b-设置断点,i-步入,o-步出。
  3. 查找引用xref-find-referencesM-?)。
  4. xref里没有我所相像的peek,在查找到的结果窗口内按n或者p可以直接跳转而不会失去焦点。
  5. edebug中想要查看某变量的值,将光标移到它的结尾,按C-x C-e
  6. edebug上执行C-x C-e出现Debugger entered--Lisp error: (void-variable cmd)时,不要按q,这会导致整个edebug退出,而要按c让它继续。
  7. edebug上执行C-x C-e出现省略号时,如下,按M-:运行(setq edebug-print-length 200)
"find -H d:/demos/emacs-28.2/src  -type f \"-name\" \"..."

xref-find-references处启动edebug,经过一堆无聊的步入步出操作后,最终定位了关键函数xref-references-in-directory

;;;###autoload
(defun xref-references-in-directory (symbol dir)
  "Find all references to SYMBOL in directory DIR.
Return a list of xref values.

This function uses the Semantic Symbol Reference API, see
`semantic-symref-tool-alist' for details on which tools are used,
and when."
  (cl-assert (directory-name-p dir))
  (require 'semantic/symref)
  (defvar semantic-symref-tool)

  ;; Some symref backends use `ede-project-root-directory' as the root
  ;; directory for the search, rather than `default-directory'. Since
  ;; the caller has specified `dir', we bind `ede-minor-mode' to nil
  ;; to force the backend to use `default-directory'.
  (let* ((ede-minor-mode nil)
         (default-directory dir)
         ;; FIXME: Remove CScope and Global from the recognized tools?
         ;; The current implementations interpret the symbol search as
         ;; "find all calls to the given function", but not function
         ;; definition. And they return nothing when passed a variable
         ;; name, even a global one.
         (semantic-symref-tool 'detect)
         (case-fold-search nil)
         (inst (semantic-symref-instantiate :searchfor symbol
                                            :searchtype 'symbol
                                            :searchscope 'subdirs
                                            :resulttype 'line-and-text)))
    (xref--convert-hits (semantic-symref-perform-search inst)
                        (format "\\_<%s\\_>" (regexp-quote symbol)))))

如上,这里(semantic-symref-perform-search inst)是关键代码,即:

(cl-defmethod semantic-symref-perform-search ((tool semantic-symref-tool-grep))
  "Perform a search with Grep."
  ;; Grep doesn't support some types of searches.
  (let ((st (oref tool searchtype)))
    (when (not (memq st '(symbol regexp)))
      (error "Symref impl GREP does not support searchtype of %s" st))
    )
  ;; Find the root of the project, and do a find-grep...
  (let* (;; Find the file patterns to use.
	 (rootdir (semantic-symref-calculate-rootdir))
	 (filepatterns (semantic-symref-derive-find-filepatterns))
         (filepattern (mapconcat #'shell-quote-argument filepatterns " "))
	 ;; Grep based flags.
	 (grepflags (cond ((eq (oref tool resulttype) 'file)
                           "-l ")
                          ((eq (oref tool searchtype) 'regexp)
                           "-nE ")
                          (t "-nw ")))
         (searchfor (oref tool searchfor))
         (greppat (if (eq (oref tool searchtype) 'regexp)
                      searchfor
                    (semantic-symref-grep--quote-grep searchfor)))
	 ;; Misc
	 (b (get-buffer-create "*Semantic SymRef*"))
	 (ans nil)
	 )

    (with-current-buffer b
      (erase-buffer)
      (setq default-directory rootdir)
      (let ((cmd (semantic-symref-grep-use-template
                  (directory-file-name (file-local-name rootdir))
                  filepattern grepflags greppat)))
        (process-file semantic-symref-grep-shell nil b nil
                      shell-command-switch cmd)))
    (setq ans (semantic-symref-parse-tool-output tool b))
    ;; Return the answer
    ans))

如上,注意变量cmd的值就是我想要的,semantic-symref-grep-shell在不同平台有不同的值:

  1. windowsD:\Program Files\Emacs\emacs-28.2\libexec\emacs\28.2\x86_64-w64-mingw32\cmdproxy.exe
  2. cygwin/bin/bash

因此在windows平台,它会调用cmdproxy.exe -c "cmd"来执行命令,那么这串命令到底是啥?来看这里打印cmd的值为:

;; cygwin
"find -H /cygdrive/d/demos/emacs-28.2/src  -type f -name \\*.\\[ch\\] -exec grep -nw  -nH --null -e stack_bottom \\{\\} +"
;; windows
"find -H d:/demos/emacs-28.2/src  -type f \"-name\" \"*.[ch]\" -exec grep -nw  -nH --null \"stack_bottom\" \"{}\" \";\""

因此我在命令行里运行了一下试试,果然出错。所以这里问题其实就已经找到了,命令行里的find调用的是windows平台的,所以出错,替换成cygwinfind就可以了:

在这里插入图片描述

(defun semantic-symref-grep-use-template (rootdir filepattern flags pattern)
  "Use the grep template expand feature to create a grep command.
ROOTDIR is the root location to run the `find' from.
FILEPATTERN is a string representing find flags for searching file patterns.
FLAGS are flags passed to Grep, such as -n or -l.
PATTERN is the pattern used by Grep."
  ;; We have grep-compute-defaults.  Let's use it.
  (grep-compute-defaults)
  (let* ((semantic-symref-grep-flags flags)
         (grep-expand-keywords semantic-symref-grep-expand-keywords)
	 (cmd (grep-expand-template
               (if (memq system-type '(windows-nt ms-dos))
                   ;; FIXME: Is this still needed?
                   ;; grep-find uses '--color=always' on MS-Windows
                   ;; because it wants the colorized output, to show
                   ;; it to the user.  By contrast, here we don't show
                   ;; the output, and the SGR escapes get in the way
                   ;; of parsing the output.
                   (replace-regexp-in-string "--color=always" ""
                                             grep-find-template t t)
                 grep-find-template)
               pattern
               filepattern
               rootdir)))
    cmd))

所以这里要需要解决find的路径问题,见上面代码,我发现在grep-find-template变量中设置了find,所以可以将该变量的find替换成D:\cygwin64\bin\find.exe。试了一下果真可以:

(custom-set-variables
 ;; custom-set-variables was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 '(grep-find-template
   "D:\\cygwin64\\bin\\find.exe -H <D> <X> -type f <F> -exec grep <C> -nH --null <R> \"{}\" \";\"")
 '(inhibit-startup-screen t)
 '(make-backup-files nil))

在这里插入图片描述
完美,打完收工!

文章来源:https://blog.csdn.net/ftuc5dn/article/details/135377335
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。