Most software developers encounter the vi editor at some point in their career—if not at college, on production UNIX machines when installing work they coded on their Windows desktop machines in full-blown IDEs. It’s rare to find a developer except in the most Microsoft-beholden shops who doesn’t have to fire up vi at least once a month. Some developers love vi, while others loathe it. But there’s a lot that can be done to make vi a better environment for a Java developer.

Java and vi don’t go together in many people’s estimation. Whereas vi is synonymous with diminutive utilitarianism, Java is likened to a huge, lumbering beast. Java developers who select vi as their primary work environment may be few and far between, but even the occasional vi user can benefit from a little time spent configuring it to be more Java friendly. You might be shocked to see how many of the features in your IDE can be provided by vi when all is said and done.

Getting started
First, make sure your vi command is connected, or is symbolically linked or aliased, to the vim binary. Vim stands for Vi IMproved and has almost complete dominance of the vi and vi clone space. It’s fast, well maintained, feature-rich, and available on most every platform.

Once you’ve got vim installed, create a file in your home directory named .vimrc. Listing A shows a good starter .vimrc file. The lines contained in the file tell vi to color Java source code to make it more readable. Their derivation isn’t terribly important, and if you don’t like the resulting appearance, you can remove them safely.

Tag jump support
Tags are Java identifiers that can be package names, class names, method names, or field names. The creation of a large index of all the tags in your code allows you to jump to the definition of any class, method, or field with a single keystroke. These index files are created using the ctags program, which is available with the vim distribution.

Ctags takes a list of Java source files or directories containing Java source files, extracts identifier information, and produces the sorting index required by vi for jumping to tags. The line of code here shows a sample ctags invocation that produces a tag file containing all the identifiers in the project’s source and, so long as the JAVA_HOME variable is defined correctly, Sun’s core library source code as well:
ctags -f ~/.tags -R ~/myprojects/src $JAVA_HOME/src

Once the tags index has been created you need only tell vi where it can be found. This is done by including the line set tags=~/.tags in your ~/.vimrc file. With the tags index file available and vi knowing where to find it, you can now jump to any identifier by pressing [CTRL] ]. Although useful for jumping to the location where you’ve defined methods, classes, and fields you’ve written yourself, it’s even more useful if you included the Java core class library source in your tags index. Now, simply pressing [Ctrl] ] on any core class library class or method will jump to its definition complete with javadoc.

Tag name completion
Jumping to the locations where classes, methods, and fields are defined is nice for viewing their javadoc and checking their internals, but far more often, you just need to check the definition of a keyword. This is accomplished in most IDEs by typing the keyword. However, if you have your tags file setup as explained in the previous section, keyword completion in vi is just a configuration directive away.

Placing the line set complete=.,w,b,u,t,i in your ~/.vimrc file allows you to automatically complete any class, method, or field name by pressing [Ctrl]N while in insert mode. Successive presses of [Ctrl]N bring up the next matches. When you see the tag you want, just continue typing the rest of your source code. You can find additional tag name completion tips, including using the Tab key for completion, on the vim Web site.

Method folding
Good practice suggests that you keep classes small and uncomplicated, with program complexity showing up in the class hierarchy rather than 500 line methods. Unfortunately, some classes just spiral out of control and become virtually unnavigable.

IDEs frequently buffer developers from sheer source length by offering a method table of contents in a narrow left pane. In contrast, vi offers collapsible program blocks it calls “method folding.” Folding allows you to hide all the code between the start of an indented block and its end. To enable folding, insert set foldmethod=indent in your ~/vimrc.

Once method folding is enabled, you can greatly condense a Java source file using the command :set foldlevel=0. With the fold level set to zero, you’re telling vi to show only lines that aren’t indented at all, which in most Java source files means the package, import, and class or interface definition lines. Setting foldlevel=1 tells vi that lines indented a single time should be shown in addition to unindented lines, which includes method signatures and probably not much else. To open a fold and view the hidden contents of a method, type zO on the folded line.

Method folding is easy to enable and disable by setting the foldlevel. I like it for debugging and dislike it when writing new code. You’ll just have to see how it fits with the way you like to work.

Compiling and quick-fix editing
IDEs aren’t just about editing; they’re also compilation environments. Vi does a great job of calling off to external compilers and parsing the resulting messages. Many Java projects use the easily scriptable Ant as a build environment nowadays. Rather than load a lot of Ant-specific settings into my .vimrc file, I created a separate script called vimAnt, which is shown in Listing B.

This script invokes the Ant executable with a few parameters and then filters the output to include only compiler output. You’re almost ready to invoke Ant from within vi. You just have to add the lines in Listing C to your ~/.vimrc file. Those lines tell vi to invoke the vimAnt script you created and give it clues on how to parse Ant’s jikes output.

With the vimAnt script in your system path, you can now initiate a compilation using the :make command. The current directory and all its parent directories will be searched for a build.xml file whose classes target will be invoked. Error output will be automatically parsed by vi.

Once you’ve done a compilation with errors in vi, you can use quick fix mode to rapidly go to the errors for easy repair. The :cn command take you to the next error regardless of what file it’s in. The :cc command shows you the compiler output message for the current error, and :cl will bring up a list of all the project’s errors for easy navigation to any of them. Fix up your errors, and you’re just a :make away from a clean compile.