Java Autocompletion for Emacs

The past few weeks I have been using the great eclim, and the corresponding emacseclim package. It allows you to use many of Eclipse’s features in your favourite editor. The installation of emacs-eclim is rather easy, and the one for eclim is even easier, since it comes with a simple clickety-click-installer.

I use emacs-eclim for Java development, and it works rather well. I use the two functions ac-complete-emacs-eclim and ac-complete-eclim-c-dot for auto-completion, which is the most important aspect when using such heavily object oriented languages and when developing large projects. Also useful are the functions eclim-java-import-missing, and eclim-java-remove-unused-imports. The current project can be compiled by calling eclim-project-build.

In theory, you can also use eclim with CDT for C++ development and auto-completion, but I rather stick with my earlier clang based solution, which is very fast and accurate.

Updating GNU Global GTAGS file when Emacs is idle

GNU Global is a very useful code navigation tool. In order for it to work well, it needs to be run regularly. Until now, I used the after-save-hook, to keep it up to date. However, when using emacs-eclim (also see Eclim), saving becomes so frequent that performance takes a massive hit. So I whipped up this small code snippet to run Global only when Emacs is idle for some number of seconds (default is 10):


(defcustom my-gtags-update-idle-time 10
"Number of idle seconds before an incremental gtags update is launched"
:group 'my-group ;; Put whatever customization group you like here
:type 'integer
)
(run-with-idle-timer my-gtags-update-idle-time t
(lambda ()
(if (not (minibufferp) )
(progn
(message "Running gtags...")
(global-update-incrementally)
)
)
)
)

Switching to a Java package implementation in Emacs

There already quite a few methods to switch between header and implementation of C and C++ sources in Emacs. Maybe I will put one of those here as well later. But now I needed something different: In a big project, I would like to point at a line like import com.foo.tech.implementation.SomeClass; and Emacs automatically visits the file where this class has been implemented. I wrote two small Elisp functions to perform this:

(defun my-switch-to-java-implementation (packagename classname)
"Tries to switch to the java source file containing the package packagename and
the class classname."
(with-temp-buffer
(shell-command-to-string
(format "%s %s -iname '*.java' | xargs egrep -l '%s' | sort -u | xargs egrep -l 'class %s' | head -n 1"
"find"
"path/to/your/java/sources"
packagename
classname
)
(current-buffer) )
(if (= (count-lines (point-min) (point-max) ) 1)
(progn
(search-forward "n")
(replace-match "")
(find-file (buffer-string))
)
(message "Could not find suitable implementation.")
)
)
)

(defun my-switch-to-java-implementation-at-point ()
"Tries to switch to the java source file which contains the package and class imported
in the current line."
(interactive)
(save-excursion
(beginning-of-line)
(if (looking-at "^import \(.*\)\.\(.+\);$")
(let ( (packagename (buffer-substring (match-beginning 1) (match-end 1) ) )
(classname (buffer-substring (match-beginning 2) (match-end 2) ) ) )
(my-switch-to-java-implementation packagename classname)
)
(message "This is not an import")
)
)
)

You basically call my-switch-to-java-implementation-at-point (e.g. by binding it to a key) when you are on the import line. Emacs then launches find and grep to look for the definition of your class. Of course, using something like GNU Global would be faster, but also a bit more tricky, since it does not use the packagename, but rather only the class name, which might be used multiple times in your project.
Also note that you have to set the path to your Java source files. I suggest you make a customizable variable of that, or use your ede-project-root or something similar.