2010-12-17 8 views
6

Estoy buscando ayuda para desarrollar lo que creo que debería ser un programa fácil.Ayuda escribiendo emacs lisp para emacs etags search

Quiero algo similar al comando de búsqueda de etiquetas de Emacs, pero quiero recopilar todos los resultados de búsqueda en un búfer. (Quiero ver todos los resultados de M-,)

Estoy pensando que este pseudo código de estilo python debería funcionar, pero no tengo idea de cómo hacerlo en emacs lisp? Cualquier ayuda sería muy apreciada.

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 

Me gustaría poder navegar a través del búfer con las mismas características que las etiquetas-apropos.

Tenga en cuenta que una pregunta similar se ha hecho antes: Is there a way to get emacs tag-search command to output all results to a buffer?

+1

Como nota aparte, mira la macro bucle de Lisp (algunos ejemplos aquí http: // www. ai.sri.com/pkarp/loop.html) Creo que te gustará. – ocodo

Respuesta

1

Como soy tan fan de igrep, lo usaría como el bloque de creación. A partir de ahí hay dos rutinas simples y listo.Con esa biblioteca y estas dos funciones, todo lo que tiene que hacer es:

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

Aquí está el código:

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

Y, debido a que la lista de archivos puede ser muy largo, y es probable que don' importa lo que la lista es, puede agregar estas dos piezas de código que hará que los nombres de archivo invisibles después de la grep ha terminado:

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

Para evitar la línea de comandos muy larga, puede utilizar el siguiente código (que crea un archivo temporal que contiene todos los nombres de los archivos de archivo de etiquetas y utiliza el siguiente comando):

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

Y, para aquellos que utilizan Emacs 22 o más temprano, tendrá la rutina que se envía con Emacs 23 (de 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

Me gusta esta solución, pero para algunas de mis ETIQUETAS la cantidad de archivos es demasiado larga para manejar. ¿Alguna forma de hacerlo iterando sobre cada archivo en TAGS? – eflanigan00

+0

@ user535707 Agregué una solución que resuelve su problema. –

+0

Gracias por la sugerencia, pero no puedo usar las cadenas de combinar y presupuestar en emacs22. ¿Hay otra función que pueda escribir para reemplazarla? – eflanigan00

1

Aquí está el código que utilizo para crear un sistema de etiquetas para mis notas personales. Utiliza marcadores y trata cada palabra en un marcador como una sola etiqueta. No es exactamente lo que estás buscando, pero podría ayudarte a empezar.

Las primeras dos funciones probablemente ya estén implementadas en emacs, pero escribí las mías por razones que ya no recuerdo.

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

entonces Ato el comportamiento 'etiquetar' a una tecla (F11) y el comportamiento 'de búsqueda' a otro (F12).

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

Espero que te sea útil.

+0

Good Eye Victor, creo que solo he publicado una o dos veces. Me aseguraré de verificarlo. –

1

Esto es lo que quiere:

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

Esta es la cadena de documentación para 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.) 

Véase también esta página para más explicación sobre carámbanos búsqueda:

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

+0

Esto funciona bastante bien, pero realmente no hay suficiente información para hacer una buena elección. La solución igrep publicada por Trey proporciona todo el código fuente en la línea devuelta por grep. Me encantaría que los carámbanos combinen algo como esto e incluso agregar la opción -A y -B a grep. – eflanigan00

+1

@flanigan: No estoy seguro de lo que quiere decir. Lo que 'icicle-tags-search' hace es esto: visite sus archivos TAGS para obtener la lista de todos los archivos que tienen etiquetas definidas, luego busque todos esos archivos. La búsqueda es Icicles search, lo que significa que proporciona una expresión regular que define los contextos de búsqueda. Si desea que cada línea sea un contexto como en 'grep', entonces use'. * 'Como la expresión regular que define el contexto. A continuación, escribe texto (por ejemplo, una subcadena o una expresión regular) en el minibúfer para filtrar el conjunto de contextos (de todos los archivos). Puede usar 'S-SPC' para agregar más patrones de filtrado, para reducir los contextos progresivamente. – Drew

+1

Si no está familiarizado con la búsqueda de Icicles, le sugiero que primero intente una búsqueda simple: un solo archivo, por ejemplo. Comience [* aquí *] (http://www.emacswiki.org/emacs/Icicles_-_Search_Commands%2c_Overview). Supongo que está confundido acerca de la expresión regular de contexto, pensando quizás que se usa para buscar en los archivos. Para una búsqueda de línea por línea a la 'grep', la expresión regular de contexto debería ser'. * '. La búsqueda se realiza a través de los patrones de búsqueda dinámica que escribe en el minibúfer. – Drew