2009-09-26 14 views
11

Quiero indexar archivos clojure, usando etags para poder usar la funcionalidad de etiqueta de Emacs. Pero etags no reconoce las funciones de clojure. ¿Es posible ampliar etags para incluir definiciones de clojure?Clojure Emacs etags

Respuesta

6

Mirando la fuente, parece que solo tendrías que ejecutar etags usando la bandera --language=lisp, ya que el reconocedor Lisp busca la cadena 'def'.

Si eso no funciona, tendrá que modificar etags para que pueda reconocer Clojure y producir un archivo de etiquetas para él. Here is the source of etags in htmlized form. No parece que sería un trabajo tan difícil o largo de hacer. Estas son las reglas para el reconocimiento de Python como un ejemplo:

/* 
* Python support 
* Look for /^[\t]*def[ \t\n]+[^ \t\n(:]+/ or /^class[ \t\n]+[^ \t\n(:]+/ 
* Idea by Eric S. Raymond <[email protected]> (1997) 
* More ideas by seb bacon <[email protected]> (2002) 
*/ 
static void 
Python_functions (inf) 
    FILE *inf; 
{ 
    register char *cp; 

    LOOP_ON_INPUT_LINES (inf, lb, cp) 
    { 
     cp = skip_spaces (cp); 
     if (LOOKING_AT (cp, "def") || LOOKING_AT (cp, "class")) 
     { 
     char *name = cp; 
     while (!notinname (*cp) && *cp != ':') 
     cp++; 
     make_tag (name, cp - name, TRUE, 
      lb.buffer, cp - lb.buffer + 1, lineno, linecharno); 
    } 
    } 
} 

El soporte Lisp es un poco más complicado:

/* 
* Lisp tag functions 
* look for (def or (DEF, quote or QUOTE 
*/ 

static void L_getit __P((void)); 

static void 
L_getit() 
{ 
    if (*dbp == '\'')  /* Skip prefix quote */ 
    dbp++; 
    else if (*dbp == '(') 
    { 
    dbp++; 
    /* Try to skip "(quote " */ 
    if (!LOOKING_AT (dbp, "quote") && !LOOKING_AT (dbp, "QUOTE")) 
     /* Ok, then skip "(" before name in (defstruct (foo)) */ 
     dbp = skip_spaces (dbp); 
    } 
    get_tag (dbp, NULL); 
} 

static void 
Lisp_functions (inf) 
    FILE *inf; 
{ 
    LOOP_ON_INPUT_LINES (inf, lb, dbp) 
    { 
     if (dbp[0] != '(') 
    continue; 

     if (strneq (dbp+1, "def", 3) || strneq (dbp+1, "DEF", 3)) 
    { 
     dbp = skip_non_spaces (dbp); 
     dbp = skip_spaces (dbp); 
     L_getit(); 
    } 
     else 
    { 
      /* Check for (foo::defmumble name-defined ... */ 
     do 
     dbp++; 
     while (!notinname (*dbp) && *dbp != ':'); 
     if (*dbp == ':') 
     { 
      do 
      dbp++; 
      while (*dbp == ':'); 

       if (strneq (dbp, "def", 3) || strneq (dbp, "DEF", 3)) 
       { 
        dbp = skip_non_spaces (dbp); 
        dbp = skip_spaces (dbp); 
        L_getit(); 
       } 
      } 
     } 
    } 
} 
5

Para mejorar la respuesta de miner49:

tengo esto en mi .emacs (nota ligero cambio en la expresión regular, ctags estaba gritando acerca tener "-" en el medio de la expresión regular cuando no se utiliza para especificar un rango)

; Recursively generate tags for all *.clj files, 
; creating tags for def* and namespaces 
(defun create-clj-tags (dir-name) 
"Create tags file." 
(interactive "Directory: ") 
(shell-command 
    (format "%s --langdef=Clojure --langmap=Clojure:.clj --regex-Clojure='/[ \t\(]*def[a-z]* \([a-z!-]+\)/\1/' --regex-Clojure='/[ \t\(]*ns \([a-z.]+\)/\1/' -f %s/TAGS -e -R %s" path-to-ctags dir-name (directory-file-name dir-name))) 
) 

Otro obstáculo fue que en mi baba de caja anula M-. usar su propia función de búsqueda en lugar de find-tag, y esa función no funcionó correctamente. Es su propia función de búsqueda en lugar de find-tag, y esa función no funcionó correctamente. puede invocar la etiqueta find-tag Seperatley para encontrar las etiquetas del archivo TAG, pero la función incorporada salta al origen de las funciones integradas cuando se conecta a un servidor slime/swank, que es bastante limpio. mis habilidades de elisp no pudieron consolidar las dos. limo espera encontrar en etiquetas para volver a cero si no que no parece suceder, por lo que el siguiente

(add-hook 'slime-edit-definition-hooks 'find-tag) 

trae de vuelta TAGS búsquedas basadas, sino que destruye búsquedas Swank-servidor.

2

@ la respuesta de miller49r es realmente agradable. Lo modifiqué un poco para reconocer los metadatos y algunos caracteres de símbolo de clojure más aceptables:

find . \! -name '.*' -name '*.clj' \ 
    | xargs etags \ 
    --regex='/[ \t\(]*def[a-zA-Z!$%&*+\-.\/:<=>[email protected]^_~]*[ \n\t]+\(\^{[^}]*}[ \n\t]+\|\)\([a-zA-Z!$%&*+\-.\/:<=>[email protected]^_~]+\)/\2/s' \ 
    --regex='/[ \t\(]*ns \([a-z.]+\)/\1/' 
Cuestiones relacionadas