Help writing emacs lisp for emacs etags search

前端 未结 3 744
北荒
北荒 2021-01-05 17:17

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

相关标签:
3条回答
  • 2021-01-05 17:42

    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

    0 讨论(0)
  • 2021-01-05 17:45

    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)))
    
    0 讨论(0)
  • 2021-01-05 17:48

    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.

    0 讨论(0)
提交回复
热议问题