2009-09-26 13 views
11

Chcę indeksować pliki clojure, używając etagów, aby móc korzystać z funkcji znaczników Emacs. Ale etagi nie rozpoznają funkcji clojure. czy możliwe jest rozszerzenie etagów o definicje clojure?Clojure Emacs etags

Odpowiedz

6

Patrząc na źródło, wydaje się, że wystarczy uruchomić etags za pomocą flagi --language=lisp, ponieważ program rozpoznający Lisp szuka łańcucha "def".

Jeśli to nie zadziała, musisz zmodyfikować etags, aby mógł rozpoznać Clojure i utworzyć dla niego plik znaczników. Here is the source of etags in htmlized form. Nie wygląda na to, że byłoby to trudne lub długie. Oto zasady ujmowania Python jako przykład:

/* 
* 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); 
    } 
    } 
} 

Lisp wsparcie jest trochę bardziej zaangażowani:

/* 
* 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

By poprawić odpowiedzi miner49 męska:

mam to w moim .emacs (nota nieznaczne zmiany w regex, ctags wrzeszczał o konieczności „-” w środku regex, gdy nie jest używany, aby określić zakres)

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

Kolejną przeszkodą było to, że na mojej szlamie skrzyni nadpisałem M-. używać własnej funkcji wyszukiwania zamiast tagu find, a funkcja ta nie działa poprawnie. e to własna funkcja wyszukiwania zamiast tagu find, a funkcja ta nie działa poprawnie. możesz wywołać seperatley seperatley , aby znaleźć znaczniki z pliku TAG, ale wbudowana funkcja przeskakuje do źródła wbudowanych funkcji po podłączeniu do serwera slime/swank, co jest całkiem zadbane. moje umiejętności elisp nie zdołały skonsolidować tych dwóch. szlam spodziewa się znaleźć tag powrotu zero, jeśli nie, który wydaje się nie stało, więc następujące

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

przywraca TAGI podstawie wyszukiwań, ale niszczy wyszukiwania Swank-serwer.

2

@ Odpowiedź millera49r bardzo ładna. Zmodyfikowałem go nieco, aby rozpoznać metadane i niektóre bardziej akceptowalne chalaratury symboli kłamstwa:

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/'