*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. > MyServlet org.foo.MyServlet MyServlet /my-servlet < 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?)]*?name=['"](.*?)['"]/, "\$2"); regex.addPattern('i', ~/(s?)]*?file=['"](.*?)['"]/, "\$2"); regex.addPattern('t', ~/(s?)]*?name=['"](.*?)['"]/, "\$2"); regex.addPattern('r', ~/(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