views:

366

answers:

1

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?

+4  A: 

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 ();
             }
            }
        }
    }
}
Pinochle