*vim-common-taglist*


Eclim & Taglist
***************


Taglist Enhancement
===================

Eclim provides a scripted ctags implementation that sits on top of the
original ctags to provide an alternative approach to adding new
languages for use by the excellent taglist
(http://www.vim.org/scripts/script.php?script_id=273) plugin for Vim.

The standard ctags, gives you two choices when you wish to add support
for a new language.  First, you can define a new language via regular
expression patterns in your .ctags file.  Or, using the second
approach, you can write the C code necessary to truly integrate the
new language into ctags.

The first approach, while fairly simple, is a bit limiting.  The most
frustrating limitation is that the file to be parse is processed one
line at a time, which prevents you from identifying tags that span two
or more lines.

For example, given the following web.xml file, you would not be able
to distinguish between the first block which is a servlet definition,
and the second which is a servlet mapping, because you would need to
process the parent tag, not just the servlet-name tag.

>

   <servlet>
     <servlet-name>MyServlet</servlet-name>
     <servlet-class>org.foo.MyServlet</servlet-class>
   </servlet>

   <servlet-mapping>
     <servlet-name>MyServlet</servlet-name>
     <servlet-class>/my-servlet</servlet-class>
   </servlet-mapping>

<


The second approach, is much more flexible, but writing a language
processor in C may not be a feasible solution for various reasons
(unfamiliarity with C, portability, etc.).

Taking into account these concerns, eclim provides a means to add new
languages by writing a groovy (http://groovy.codehaus.org) script
which can range from simple multi-line capable regular expression
matching, to a full blown language parser using a scripting language
that borrows many of its convenient language constructs from languages
such as Python, Ruby, and Smalltalk.

Adding a new language involves the following three steps:

1. Write a groovy script that conforms to a simple interface defined
   below.

2. Place the script in the appropriate plugin's
   resources/scripts/taglist dir.

   For example general purpose taglist scripts should be placed in:
   $ECLIPSE_HOME/plugins/org.eclim_version/resources/scripts/taglist
   While those specific to java programming should be placed in:
   $ECLIPSE_HOME/plugins/org.eclim.jdt_version/resources/scripts/taglist

3. Add a Vim variable that informs the taglist plugin about your new
   language.

   >
      let g:tlist_mylang_settings='mylang;t:mytype;f:myfield'

   <

   See the taglist documentation
   (http://vim-taglist.sourceforge.net/manual.html#taglist-extend) for
   more details.

The second step is self explanatory and the third step is well
documented by the taglist documentation
(http://vim-taglist.sourceforge.net/manual.html#taglist-extend) so the
rest of this document will concentrate on step one.

Note: When opening the taglist window, eclim will search for the taglist
  script in the directory noted above by looking for a file named
  filetype.groovy, where filetype is the case sensitive value of Vim's
  &filetype option.  If no script is found for the file type, then
  eclim will delegate the call to your system's ctags command as
  configured (http://vim-taglist.sourceforge.net/manual.html#%27Tlist_
  Ctags_Cmd%27) for taglist.vim.


Writing the Groovy Script
=========================

Writing the groovy script is a pretty simple process.  The script
simply needs to define one class which implements
org.eclim.command.taglist.TaglistScript.  This interface defines a
single method, execute(String) which takes the name of the file to be
processed and returns an array of org.eclim.command.taglist.TagResult.

Since regular expression matching tends to be the easiest way to add
new language support, eclim provides a helper class,
org.eclim.command.taglist.RegexTaglist which makes the pattern
matching process as painless as possible.

To see this all in action, lets look at the code for the ant.groovy
script (found in the org.eclim.ant plugin's resources directory),
which provides taglist support for ant build files.

>

   import org.eclim.command.taglist.RegexTaglist;
   import org.eclim.command.taglist.TaglistScript;
   import org.eclim.command.taglist.TagResult;

   /**
    * Processes tags for ant files.
    */
   class AntTags implements TaglistScript
   {
     public TagResult[] execute (String file)
     {
       def regex = null;
       try{
         regex = new RegexTaglist(file);
         regex.addPattern('p', ~/(s?)<project\s+[^>]*?name=['"](.*?)['"]/, "\$2");
         regex.addPattern('i', ~/(s?)<import\s+[^>]*?file=['"](.*?)['"]/, "\$2");
         regex.addPattern('t', ~/(s?)<target\s+[^>]*?name=['"](.*?)['"]/, "\$2");
         regex.addPattern('r', ~/(s?)<property\s+[^>]*?name=['"](.*?)['"]/, "\$2");

         return regex.execute();
       }finally{
         if (regex != null) regex.close();
       }
     }
   }

<


Lines 14 - 18 are the real meat of the script.  Here we create a new
RegexTaglist instance for our file and add the necessary patterns to
match our tags (project, import, target, and property).  There are a
few things to note about the regular expressions here.  The first is
the use of '(s?)' at the beginning of each.  This tells the java regex
matcher to include line breaks when dealing with the s operator.
Another thing to note, is that we do not use ^ or $.  Ctags processes
the file one line at a time so it's common to use ^ and $ in your
regex, but here we are processing the whole file, so ^ and $ would
denote the start and end of the file, not a line.

The third argument to addPattern also deserves some explanation.  This
value is the substitution to be made on the matched segment of the
file, which denotes the tag name.  In this instance we use $2 (groovy
requires that the $ be escaped), which means that the tag name should
be taken from the second group of the matched text.  Note, that the
first group is taken by (s?).

So, to summarize the meaning of line 15: Match the 'project' element
and use the value of the 'name' attribute of that element as the tag
name.

If you decide that you'd rather perform the ctags standard line by
line regex matching, that can be accomplished just as easily.  To show
an example of just that, let's look at the jproperties.groovy script
(found in the org.eclim.jdt plugin's resources directory) which is
used to process java property files.

>

   import java.io.File;

   import org.eclim.command.taglist.TaglistScript;
   import org.eclim.command.taglist.TagResult;

   /**
    * Processes tags for java property files.
    */
   class PropertiesTags implements TaglistScript
   {
     public TagResult[] execute (String file)
     {
       def results = [];
       def lineNumber = 0;
       new File(file).eachLine {
         line -> processTag(line, ++lineNumber, file, results)
       };

       return (TagResult[])results.toArray(new TagResult[results.size()]);
     }

     void processTag (line, lineNumber, file, results)
     {
       def matcher = line =~ /^\s*([^#]+)\s*=.*/;
       if(matcher.matches()){
         def name = matcher[0][1];
         def tag = new TagResult(
           file:file, pattern:line, line:lineNumber, kind:'p', name:name);

         results.add(tag);
       }
     }
   }

<


In this script you can see that on lines 15 - 17, it makes use of the
groovy added eachLine method of File to process each line
individually.


Configuration
=============

Vim Variables

*g:EclimTaglistEnabled*

- g:EclimTaglistEnabled (Default: 1) - If set to 0, disables usage of
  eclim's ctags implementation.

*taglisttoo*


TaglistToo: Alternate taglist implementation
============================================

The taglist (http://www.vim.org/scripts/script.php?script_id=273)
plugin written by Yegappan Lakshmanan is an excellent enhancement to
vim which provides an outline of the current file.  However, in my
usage I've found that there were enhancements that I wanted to make to
it, but since the plugin was written to support vim prior to 7.0, the
data structures used to hold and display the tags are very difficult
to modify.  So, I decide to implement an alternate version targeting
vim 7.x which would be easier to enhance.  Please note though, that
this new version does not duplicate all of the functionality provided
by the original (although I may add more of those features if user
feedback warrants it).

Note: The eclim taglist will not be activated if it detects that you have
  the original taglist plugin installed.  So if you want to try the
  eclim version out, please rename your taglist.vim to taglist.vim.bak
  or move it out of your plugins directory.

Here is a list of enhancements vs unimplemented features:

Enhancements

- Supports an extension mechanism allowing the taglist display to be
  customized by file type.

- Provides a custom display for java, javascript, and python files
  which groups methods and variables by object/class for easier
  viewing and navigation.

- Supports denoting tags based on their visibiltiy (+public, -private,
  *static, #protected).

Unimplemented features:

- Drop down list in gvim with the list of tags.

- Tag re-sorting

- Vim session support

- Support for tags for more than one file in the taglist window.

- ... possibly others.

Other than the feature differences the behavior of the eclim taglist
is very similar to the original taglist. To open / close the taglist
simply execute the command :TlistToo.

In an attempt to make your transition from the original taglist to the
eclim taglist as easy as possible, the eclim taglist also supports
some of the same configuration variables:

- g:Tlist_Ctags_Cmd - Sets the location or your ctags executable (if
  not configured it tries exuberant-ctags, ctags, ctags.exe, and tags
  on your path).

- g:Tlist_Auto_Open (Defaults to 0, disabled) - When non-zero, the
  taglist will auto open at vim startup for files that have taglist
  support.

- g:tlist_{ft}_settings - Supports file type specific configuration,
  but unlike the original taglist, uses a dictionary of taglist key to
  tag title.

  Ex:

  >
     let g:tlist_ant_settings = {
         \ 'lang': 'ant', 'tags': {
           \ 'p': 'project',
           \ 'i': 'import',
           \ 'r': 'property',
           \ 't': 'target'
         \ }
       \ }

  <

vim:ft=eclimhelp