2010-12-17 2 views
6

Ich bin auf der Suche nach etwas Hilfe bei der Entwicklung, was ich denke, sollte ein einfaches Programm sein.Hilfe schreiben Emacs Lisp für Emacs Etags Suche

Ich möchte etwas ähnlich wie Emacs Tags-Suchbefehl, aber ich möchte alle Suchergebnisse in einen Puffer sammeln. (Ich will alle Ergebnisse von M sehen-)

Ich denke, dass dieser Python-Stil-Pseudo-Code funktionieren sollte, aber ich habe keine Ahnung, wie man dies in Emacs Lisp zu tun? Jede Hilfe würde sehr geschätzt werden.

Ich möchte in der Lage sein, durch den Puffer mit den gleichen Funktionen durchsuchen Tags-apropos tut.

Beachten Sie, dass eine ähnliche Frage vor gefragt wurde: Is there a way to get emacs tag-search command to output all results to a buffer?

+1

als nur zur Seite, an der Lisp Schleife Makro aussehen (einige Beispiele hier http: // www. ai.sri.com/pkarp/loop.html) Ich denke du wirst es mögen. – ocodo

Antwort

1

Da ich so ein Fan von igrep bin, würde ich es als Baustein verwenden. Von dort sind es zwei einfache Routinen und du bist fertig.Mit dieser Bibliothek und diese beiden Funktionen, alles, was Sie tun müssen, ist:

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

Hier ist der 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)))) 

Und weil die Liste der Dateien kann wirklich lange, und Sie wahrscheinlich don‘ t egal, was diese Liste ist, können Sie diese beiden Teile des Codes hinzufügen, die die Dateinamen unsichtbar machen, nachdem der grep beendet hat:

(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)))))) 

die wirklich lange Befehlszeile zu vermeiden, können Sie den folgenden Code verwenden (die alle die Namen der Dateien aus TAGS-Datei erstellt eine temporäre Datei enthält, und verwendet diese anstelle):

(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)) 

Und für diejenigen, Emacs mit 22 oder früher, werden Sie die Routine benötigen, die mit Emacs 23 (von subr.el versendet hat)

(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

Ich mag diese Lösung, aber für einige meiner TAGS ist die Anzahl der Dateien zu lang. Irgendeine Möglichkeit, dies zu tun, indem man über jede Datei in den TAGS iteriert? – eflanigan00

+0

@ user535707 Ich habe eine Lösung hinzugefügt, die Ihr Problem anspricht. –

+0

Vielen Dank für den Vorschlag, aber ich kann nicht kombinieren-und-Zitat-Strings auf Emacs22. Gibt es eine andere Funktion, die ich schreiben kann, um sie zu ersetzen? – eflanigan00

1

Hier ist der Code Ich benutze ein Tag-System für meine persönlichen Notizen zu erstellen. Es verwendet Lesezeichen und behandelt jedes Wort in einem Lesezeichen als einzelnes Tag. Es ist nicht ganz das, wonach Sie suchen, aber es könnte Ihnen den Anfang machen.

Die ersten paar Funktionen sind wahrscheinlich schon in emacs implementiert, aber ich habe aus Gründen, die ich nicht mehr kenne, eigene geschrieben.

;; 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)))) 

ich dann binde das 'Tagging' Verhalten auf eine Taste (F11) und das 'Lookup' Verhalten auf einem anderen (F12).

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

Ich hoffe, das ist nützlich für Sie.

+0

Good Eye Victor, ich glaube, ich habe nur ein- oder zweimal gepostet. Ich werde es mir ansehen. –

1

Dies ist, was Sie wollen:

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

Dies ist die doc-String für 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.) 

finden Sie weitere Erklärung auch diese Seite über Icicles Suche:

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

+0

Das funktioniert gut genug, aber es gibt wirklich nicht genug Informationen, um eine gute Wahl zu treffen. Die von Trey veröffentlichte igrep-Lösung stellt den gesamten Quellcode auf der von grep zurückgegebenen Zeile bereit. Ich würde es lieben, wenn Eiszapfen so etwas einkreisen und sogar die Option -A und -B hinzufügen könnte. – eflanigan00

+1

@flanigan: Nicht sicher, was du meinst. Was "icicle-tags-search" bewirkt, ist folgendes: Besuchen Sie Ihre TAGS-Dateien, um eine Liste aller Dateien mit definierten Tags zu erhalten, und durchsuchen Sie alle diese Dateien. Die Suche ist die Icicles-Suche, was bedeutet, dass Sie eine Regexp bereitstellen, die die Suchkontexte definiert. Wenn Sie möchten, dass jede Zeile ein Kontext wie in 'grep' ist, verwenden Sie'. * 'Als kontextdefinierenden Regexp. Sie geben dann einen Text (z. B. einen Teilstring oder einen regulären Ausdruck) in den Minipuffer ein, um den Kontextsatz (aus allen Dateien) zu filtern. Sie können 'S-SPC' verwenden, um weitere Filtermuster hinzuzufügen, um die Kontexte schrittweise einzugrenzen. – Drew

+1

Wenn Sie mit der Icicles-Suche nicht vertraut sind, empfehle ich Ihnen, zuerst eine einfache Suche zu starten: eine einzelne Datei zum Beispiel. Starten Sie [* hier *] (http://www.emacswiki.org/emacs/Icicles_-_Search_Commands%2c_Overview). Meine Vermutung ist, dass Sie bezüglich der Kontext-Regexp verwirrt sind, vielleicht denkend, dass es verwendet wird, um die Dateien zu suchen. Für eine zeilenweise Suche a la 'grep' sollte der Kontext regexp nur'. * 'Sein. Die Suche erfolgt über die dynamischen Suchmuster, die Sie in den Minipuffer eingeben. – Drew