Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clojure Emacs etags

Tags:

emacs

clojure

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?

like image 625
Hamza Yerlikaya Avatar asked Sep 26 '09 18:09

Hamza Yerlikaya


2 Answers

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[a-z]* \([a-z-!]+\)/\1/' --regex='/[ \t\(]*ns \([a-z.]+\)/\1/'

like image 139
miner49r Avatar answered Nov 15 '22 05:11

miner49r


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[ \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);
     }
   }
}

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 ();
                }
            }
        }
    }
}
like image 41
Pinochle Avatar answered Nov 15 '22 05:11

Pinochle