Clojure Emacs etags
I want to index clojure files, using etags so that i can use Emacs's tag functionality. But etags does not recognize clojure functions. is it possible to extend etags to include clojure definitions?
Based on http://nakkaya.com/2009/12/13/getting-etags-to-index-clojure-files/
the following command is all on one line
find . ! -name '.*' -name '*.clj' | xargs etags --regex='/[ t(]*def[az]* ([az-!]+)/1/' --regex='/[ t(]*ns ([az.]+)/1/'
Looking at the source, it seems that you would just have to run etags
using the --language=lisp
flag, since the Lisp recognizer looks for the string 'def'.
If that doesn't work, you'll have to modify etags
so that it can recognize Clojure and produce a tags file for it. Here is the source of etags
in htmlized form. It doesn't look like it would be that difficult or long a job to do. Here are the rules for recognizing Python as an example:
/*
* Python support
* Look for /^[t]*def[ tn]+[^ tn(:]+/ or /^class[ tn]+[^ tn(:]+/
* Idea by Eric S. Raymond <esr@thyrsus.com> (1997)
* More ideas by seb bacon <seb@jamkit.com> (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);
}
}
}
The Lisp support is a little more involved:
/*
* 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 ();
}
}
}
}
}
To improve on miner49's answer:
I have this in my .emacs (note slight change in regex, ctags was yelling about having "-" in the middle of the regex when not used to specify a range)
; 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)))
)
Another obstacle was that on my box slime overrides M-. to use it's own lookup function rather then find-tag, and that function failed to work properly. e it's own lookup function rather then find-tag, and that function failed to work properly. you can invoke find-tag seperatley to find tags from the TAG file, but the builtin function jumps to the source of builtin functions when connected to a slime/swank server , which is pretty neat. my elisp skills failed to consolidate the two. slime expects find-tag to return nil if it fails which seems not to happen, so the following
(add-hook 'slime-edit-definition-hooks 'find-tag)
brings back TAGS based searches, but destroys swank-server searches.
链接地址: http://www.djcxy.com/p/6566.html上一篇: Python的Emacs批量缩进
下一篇: Clojure Emacs etags