帮助编写用于 emacs etags 搜索的 emacs lisp

发布于 2024-10-08 12:26:41 字数 670 浏览 0 评论 0原文

我正在寻求一些帮助来开发我认为应该是简单的程序。

我想要类似于 Emacs 标签搜索命令的命令,但我想将所有搜索结果收集到缓冲区中。 (我想查看 M- 的所有结果,)

我认为这个 python 风格的伪代码应该可以工作,但我不知道如何在 emacs lisp 中做到这一点?任何帮助将不胜感激。

def myTagsGrep(searchValue):
    for aFile in the tag list:
        result = grep aFile seachValue
        if len(result) > 0:
            print aFile  # to the buffer
            print result # to the buffer

我希望能够使用与 Tags-apropos 相同的功能浏览缓冲区。

请注意,之前已经问过类似的问题: 有没有办法让 emacs tag-search 命令将所有结果输出到缓冲区?

I'm looking for some help developing what I think should be an easy program.

I want something similar to Emacs tags-search command, but I want to collect all search results into a buffer. (I want to see all results of M-,)

I'm thinking this python style pseudo code should work, but I have no idea how to do this in emacs lisp? Any help would be greatly appreciated.

def myTagsGrep(searchValue):
    for aFile in the tag list:
        result = grep aFile seachValue
        if len(result) > 0:
            print aFile  # to the buffer
            print result # to the buffer

I would like to be able to browse through the buffer with the same features tags-apropos does.

Note that a similar question has been asked before:
Is there a way to get emacs tag-search command to output all results to a buffer?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

最近可好 2024-10-15 12:26:41

因为我是 igrep,我会用它作为构建块。从那里开始,有两个简单的例程,您就完成了。有了这个库和这两个函数,您所要做的就是:

M-x igrep-tags ^SomeRegexp.*Here RET

这是代码:

(require 'igrep)
(defun igrep-tags (regex)
  (interactive "sTAGS Regexp: ")
  (igrep igrep-program regex (tags-file-names)))

(defun tags-file-names ()
  (save-excursion
    (visit-tags-table-buffer)
    (mapcar (lambda (f) (file-truename f))
            (tags-table-files))))

而且,因为文件列表可能会变得非常长,并且您可能不关心该列表是什么,所以您可以添加这两部分grep 完成后将使文件名不可见的代码:

(add-hook 'compilation-finish-functions 'igrep-tags-hide-filenames)

(defun igrep-tags-hide-filenames (buffer stat)
  "hide the filenames b/c they can get long"
  (save-excursion
    (set-buffer buffer)
    (save-match-data 
      (goto-char (point-min))
      (if (search-forward (combine-and-quote-strings (tags-file-names))
                          nil
                          (save-excursion (forward-line 10) (point)))
          (let ((display-string "..<files from TAGS>.."))
            (put-text-property (match-beginning 0) (match-end 0) 'invisible t)
            (put-text-property (match-beginning 0) (match-end 0) 'display display-string))))))

为了避免非常长的命令行,您可以使用以下代码(它创建一个包含 TAGS 文件中所有文件名的临时文件并使用它):

(defun igrep-tags (regex)
  (interactive "sTAGS Regexp: ")
  (let ((igrep-find t)
        (igrep-use-file-as-containing-files t))
    (igrep igrep-program regex nil)))

(defvar igrep-use-file-as-containing-files nil)

(defadvice igrep-format-find-command (around igrep-format-find-command-use-filename-instead activate)
  "use the second argument as a file containing filenames"
  (if igrep-use-file-as-containing-files
      (progn (with-temp-file
                 (setq igrep-use-file-as-containing-files (make-temp-file "tags-files"))
               (insert (combine-and-quote-strings (tags-file-names))))
             (setq ad-return-value (format "cat %s | xargs -e %s"
                                           igrep-use-file-as-containing-files
                                           (ad-get-arg 0))))
    ad-do-it))

并且,对于使用 Emacs 22 或更早版本的用户,您需要 Emacs 23 附带的例程(来自 subr.el)

(defun combine-and-quote-strings (strings &optional separator)
  "Concatenate the STRINGS, adding the SEPARATOR (default \" \").
This tries to quote the strings to avoid ambiguity such that
  (split-string-and-unquote (combine-and-quote-strings strs)) == strs
Only some SEPARATORs will work properly."
  (let* ((sep (or separator " "))
         (re (concat "[\\\"]" "\\|" (regexp-quote sep))))
    (mapconcat
     (lambda (str)
       (if (string-match re str)
           (concat "\"" (replace-regexp-in-string "[\\\"]" "\\\\\\&" str) "\"")
         str))
     strings sep)))

Since I'm such a fan of igrep, I'd use it as the building block. From there it's two simple routines and you're done. With that library and these two functions, all you have to do is:

M-x igrep-tags ^SomeRegexp.*Here RET

Here's the code:

(require 'igrep)
(defun igrep-tags (regex)
  (interactive "sTAGS Regexp: ")
  (igrep igrep-program regex (tags-file-names)))

(defun tags-file-names ()
  (save-excursion
    (visit-tags-table-buffer)
    (mapcar (lambda (f) (file-truename f))
            (tags-table-files))))

And, because the list of files can get really long, and you likely don't care what that list is, you can add these two pieces of code which will make the filenames invisible after the grep has finished:

(add-hook 'compilation-finish-functions 'igrep-tags-hide-filenames)

(defun igrep-tags-hide-filenames (buffer stat)
  "hide the filenames b/c they can get long"
  (save-excursion
    (set-buffer buffer)
    (save-match-data 
      (goto-char (point-min))
      (if (search-forward (combine-and-quote-strings (tags-file-names))
                          nil
                          (save-excursion (forward-line 10) (point)))
          (let ((display-string "..<files from TAGS>.."))
            (put-text-property (match-beginning 0) (match-end 0) 'invisible t)
            (put-text-property (match-beginning 0) (match-end 0) 'display display-string))))))

To avoid the really long command line, you can use the following code (which creates a temporary file containing all the names of files from TAGS file and uses that instead):

(defun igrep-tags (regex)
  (interactive "sTAGS Regexp: ")
  (let ((igrep-find t)
        (igrep-use-file-as-containing-files t))
    (igrep igrep-program regex nil)))

(defvar igrep-use-file-as-containing-files nil)

(defadvice igrep-format-find-command (around igrep-format-find-command-use-filename-instead activate)
  "use the second argument as a file containing filenames"
  (if igrep-use-file-as-containing-files
      (progn (with-temp-file
                 (setq igrep-use-file-as-containing-files (make-temp-file "tags-files"))
               (insert (combine-and-quote-strings (tags-file-names))))
             (setq ad-return-value (format "cat %s | xargs -e %s"
                                           igrep-use-file-as-containing-files
                                           (ad-get-arg 0))))
    ad-do-it))

And, for those using Emacs 22 or earlier, you'll need the routine that's shipped with Emacs 23 (from subr.el)

(defun combine-and-quote-strings (strings &optional separator)
  "Concatenate the STRINGS, adding the SEPARATOR (default \" \").
This tries to quote the strings to avoid ambiguity such that
  (split-string-and-unquote (combine-and-quote-strings strs)) == strs
Only some SEPARATORs will work properly."
  (let* ((sep (or separator " "))
         (re (concat "[\\\"]" "\\|" (regexp-quote sep))))
    (mapconcat
     (lambda (str)
       (if (string-match re str)
           (concat "\"" (replace-regexp-in-string "[\\\"]" "\\\\\\&" str) "\"")
         str))
     strings sep)))
明媚如初 2024-10-15 12:26:41

这是我用来为我的个人笔记创建标签系统的代码。它使用书签并将书签中的每个单词视为单个标签。它不完全是您正在寻找的东西,但它可能会帮助您开始。

前几个函数可能已经在 emacs 中实现了,但我自己编写了这些函数,原因我已不记得了。

;; FILTER keeps only elements of li for which pred returns true
(defun filter (pred li)
  (let (acc)
    (dolist (elem li)
      (if (funcall pred elem)
    (setq acc (cons elem acc))))
  (reverse acc)))


(defun string-match-all-p (str li)
   (if li
      (if (string-match-p (car li) str)
    (string-match-all-p str (cdr li))
   nil)
   t))

;;bookmarks as tags

(defun lookup-bookmark-tags (tagstring)
  (interactive "s")
   (let ((taglist (split-string tagstring " ")))
      (let ((bookmark-alist (filter 
           (lambda (elem)
             (string-match-all-p (car elem) taglist))
           bookmark-alist)))
    (call-interactively 'list-bookmarks))))

然后,我将“标记”行为绑定到一个键 (F11),将“查找”行为绑定到另一个键 (F12)。

(global-set-key [f11] 'bookmark-set)
(global-set-key [f12] 'lookup-bookmark-tags))

希望这对您有用。

Here is the code I use to create a tag system for my personal notes. It uses bookmarks and treats each word in a bookmark as a single tag. Its not quite what you're looking for but it might get you started.

The first couple of functions are probably already implemented in emacs, but I wrote my own for reasons that I no longer recall.

;; FILTER keeps only elements of li for which pred returns true
(defun filter (pred li)
  (let (acc)
    (dolist (elem li)
      (if (funcall pred elem)
    (setq acc (cons elem acc))))
  (reverse acc)))


(defun string-match-all-p (str li)
   (if li
      (if (string-match-p (car li) str)
    (string-match-all-p str (cdr li))
   nil)
   t))

;;bookmarks as tags

(defun lookup-bookmark-tags (tagstring)
  (interactive "s")
   (let ((taglist (split-string tagstring " ")))
      (let ((bookmark-alist (filter 
           (lambda (elem)
             (string-match-all-p (car elem) taglist))
           bookmark-alist)))
    (call-interactively 'list-bookmarks))))

I then bind the 'tagging' behavior to a key (F11) and the 'lookup' behavior to another (F12).

(global-set-key [f11] 'bookmark-set)
(global-set-key [f12] 'lookup-bookmark-tags))

Hope that is useful to you.

情定在深秋 2024-10-15 12:26:41

这就是您想要的:

http://www.emacswiki.org/emacs /Icicles_-_Emacs_Tags_Enhancements#icicle-tags-search

这是 icicle-tags-search 的文档字符串:

    Search all source files listed in tags tables for matches for REGEXP.
    You are prompted for the REGEXP to match.  Enter REGEXP with `RET'.
    You do not need `M-,' - you see all matches as search hits to visit.

    All tags in a tags file are used, including duplicate tags from the
    same or different source files.

    By default, all tags files are used, but if you provide a prefix
    argument then only the current tag table is used.

    If your TAGS file references source files that no longer exist, those
    files are listed.  In that case, you might want to update your TAGS
    file.


    You can alternatively choose to search, not the search contexts as
    defined by the context regexp you provide, but the non-contexts, that
    is, the text in the files that does not match the regexp.  To do this,
    use `C-M-~' during completion.  (This is a toggle, and it affects only
    future search commands, not the current one.)

另请参阅此页面以获取有关 Icicles 搜索的更多说明:

http://www.emacswiki.org/emacs/Icicles_-_Search_Commands%2c_Overview

This is what you want:

http://www.emacswiki.org/emacs/Icicles_-_Emacs_Tags_Enhancements#icicle-tags-search

This is the doc string for icicle-tags-search:

    Search all source files listed in tags tables for matches for REGEXP.
    You are prompted for the REGEXP to match.  Enter REGEXP with `RET'.
    You do not need `M-,' - you see all matches as search hits to visit.

    All tags in a tags file are used, including duplicate tags from the
    same or different source files.

    By default, all tags files are used, but if you provide a prefix
    argument then only the current tag table is used.

    If your TAGS file references source files that no longer exist, those
    files are listed.  In that case, you might want to update your TAGS
    file.


    You can alternatively choose to search, not the search contexts as
    defined by the context regexp you provide, but the non-contexts, that
    is, the text in the files that does not match the regexp.  To do this,
    use `C-M-~' during completion.  (This is a toggle, and it affects only
    future search commands, not the current one.)

See also this page for more explanation about Icicles search:

http://www.emacswiki.org/emacs/Icicles_-_Search_Commands%2c_Overview

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文