Emacs and JDEE as software development environment.

Artur Hefczyc

Abstract

This is guide to aid starting with emacs and JDEE as software development environment.

Well, emacs only has that many capabilities I could write a book about it. Additionally another book should be written for JDEE. However there are many good books about emacs and there is detailed documentation for JDEE on project site. So this guide will be only basic introduction for Java developers. I will describe installation, configuration and the most commonly used functions during work on Java code assuming you are familiar with programming work and emacs but you are new to Java and JDEE on emacs.


Table of Contents

Emacs and JDEE
Getting, installing and configuring software
How to use this stuff
A. Common JDEE and emacs commands table
B. Abbreviations available in JDEE

Emacs and JDEE

Emacs is not Java IDE. However it can be treated like multi-language IDE without a GUI builder. If you are not a GUI designer or developer emacs is well worth considering for a software development environment.

The most important features for GeoTools developers (most of them provided by JDEE) are:

  • Efficient and extremely customizable editor which supporting almost all programming and natural languages.

  • Excellent Java support provided by Java Development Environment for Emacs (JDEE). JDEE provides all standard features provided by dedicated Java IDEs like class browsing, code completion, imports management and so on. In many cases built in wizards and code templates makes emacs better.

  • Built in Java code formatter as well as interface to Jalopy. It is worth noting that the "native" JDEE code formatter has capabilities almost equal to Jalopy's and with a little time spent on configuration you can have on-line code formating.

  • Java-Doc generator and Java-Doc browser.

  • Java-Debug built-in interface and remote debugging support.

  • Doc-Book support. emacs's default simple support or full SGML and XML support provided by PSGML.

  • Built in CVS support.

Getting, installing and configuring software

Emacs and JDEE work best on Linux and other Unix like systems. It is possible to use all features of emacs on Windows machine but it requires additional software and effort.

Below is list of locations for necessary software.

Emacs for Linux users

In most cases emacs should be installed with distribution. If not, search package list for your distribution and install emacs separately.

Emacs for Windows users

I suggest you download full precompiled binaries “fullbin” from http://ftp.gnu.org/. This directory contains source and full emacs, elisp documentation. The easiest way to make emacs fully functional is to install CygWin. CygWin provides a Unix environment under windows. CygWin contains an emacs package but the native install contains configuration problems relating to ANT and Java so I don't recommend it.

Emacs for other systems or source lovers

Sources and manuals

JDEE - Java Development Environment for Emacs

JDEE project main page. The best source for all necessary information about JDEE.

CygWin - UNIX environment for Windows

CygWin project main page. It contains link to last available setup.exe CygWin installation program.

install-jde.sh - automatic installer of JDEE and all required libraries.

JDEE installation script with some additional information about using it in particular cases.

Installation procedure for each piece of software

I work on the same Java projects on machines with Linux and Windows+CygWin systems. So I will present configuration options necessary to use it transparently regardless of the environment you use.

Emacs installation is really simple. Put it in any convenient location on HDD and make it available using the system environment variable: "PATH". On Unix like system emacs is Plug and Play software and without any additional effort it can be used immediately after installation. For use of JDEE and Java look in environment variables setting description.

There are some tricks to use it on windows system with CygWin so I will describe it with all details. Below are step by step instructions:

  1. Run setup.exe - CygWin installation program. All default settings should be good for our needs even default packages set is sufficient. I am not sure if libxslt is installed in basic - default set. To ensure go to Text category, expand it and check libxslt package.

  2. Unpack downloaded emacs binaries to CygWin root directory d:/gnu in my case. Because emacs binaries are packed with gzip and gnu tar tools the easiest way to unpack emacs package is to run CygWin console and execute following commands:

    Example 1. Unpacking emacs binaries in CygWin root.

    # assuming downloaded emacs binaries are
    # stored in c:\tmp\emacs-21.2-fullbin-i386.tar.gz
    cd /
    tar -xzvf /cygdrive/c/tmp/emacs-21.2-fullbin-i386.tar.gz
  3. Put install-jde.sh script in your CygWin home directory and run it. (If you are an experienced emacs user, look in information at the beginning of the script about how to customize it.) It is necessary to make emacs binaries available in PATH environment variable or set full path name to emacs at the beginning of the script.

All the most necessary components are now installed. To use them effectively some customization should be done.

Step by step configuration

System, CygWin, emacs and JDEE customization hints.

  1. On Windows systems some variables should be set in system level and others in CygWin level. On Unix systems all variables can be set from user startup - profile files. On Windows they must be separated because CygWin paths are Unix-like and CygWin root directory starts in CygWin installation directory. So some programs will use Windows paths and others will use CygWin paths.

    To set environment variable on system level right-click on My-Computer and choose Properties. Go to Advanced tab and click on System environment button.

    To set environment variable on CygWin level or on all levels in native Unix system add the following to .bashrc in the way presented in Example 3, “CygWin level variables list with sample values.”.

    Example 2. System level variables list with sample values.

    JAVA_HOME=d:/jdk1.4.1
    ANT_HOME=d:/projects/jakarta-ant-1.5.1
    MAVEN_HOME=d:/projects/maven-1.0-beta-8
    PROJECTS_HOME=d:/projects

    On Unix like system above variables should be set to proper Unix file system locations.

    Example 3. CygWin level variables list with sample values.

    export PATH="/emacs-21.2/bin:$PATH"
    export CVS_RSH='ssh'
    export CVSROOT=":ext:user@cvs.geotools.sourceforge.net:/cvsroot/geotools"
    
    # Unix users should uncomment lines below:
    
    # export JAVA_HOME=/usr/local/jdk1.4.1
    # export ANT_HOME=/usr/local/jakarta-ant-1.5.1
    # export MAVEN_HOME=/usr/local/maven-1.0-beta-8
    # export PROJECTS_HOME=$HOME/projects

    For CVSROOT replace user with your Source Forge user name.

  2. To start emacs with your home directory set to CygWin home directory and make visible some CygWin variables for emacs, add the following script to your CygWin root directory:

    Example 4. Script for starting emacs - D:\gnu\startemacs.bat

    @echo off
    d:
    chdir d:\gnu\bin
    set HOME=/home/Administrator
    start "Emacs console" /min bash --login -c -c "/emacs-21.2/bin/emacs"
  3. Main emacs configuration file .emacs is located in your home directory. Example below present sample file with necessary settings and some number of not necessary but very useful especially for emacs beginners.

    Example 5. Sample .emacs content.

    It is rather big sample file, so to prevent scrolling through the number of lines of lisp code I have made my .emacs working file available on web page. I tried to make them readable and well commented. Especially with every external package used I have also added URL to place where the last version is available.

  4. If you work on several projects with different settings (like coding standards), you will fully appreciate the power of emacs and JDEE. This is one of the biggest advantages emacs has over other IDEs.

    JDEE has it's own configuration file where you can set all possible project options. If some of them are common for all projects than they can be moved to .emacs file. If you are working on Java code and you have opened Java file, JDEE looks for project configuration file - prj.el in current directory and all parent directories. Project file located in current directory inherits all parameters from projects files in parent directories and of course from .emacs file. So it is also possible to customize each package if necessary. For example you can set a different class as main executable class for each package. Anyway below I present sample JDEE project file with almost all common settings:

    Example 6. Sample prj.el file.

    As you can see, it is possible to use environment variables in prj.el file. With this feature it is not a problem to have the one project file for all operating systems you use.

How to use this stuff

Many commands are available through the main and context menu. Others are not. But all commonly used commands are binded to some key sequence. Sometimes the same key sequence has different meaning depending on what we are currently doing. But in many of such cases the main idea of key sequence is the same. For example for sequence C-c C-c idea is complete action. It can mean send ready e-mail message when you working with your e-mail box or commit changes to CVS repository if you are working in CVS mode.

As a result the big number of key bindings is not that difficult to learn as you might think at start. Look in Appendix A, Common JDEE and emacs commands table for most useful and frequently used functions and their key sequences.

General suggestions

Working on this...

Is it working?

If you already installed all the software, you should check if it works first. The easiest way to check your JDEE installation is to load any Java file. If you can see new Menu element called JDE it means JDEE mode is selected and activated.

Compiling and building

Working on this...

Adding modules and directories

Working on this...

Access to CVS repository from emacs

Emacs has built in functions to operate on CVS repository. Indeed there are at least two built in packages supporting version control systems what can confuse beginners. One is VC and another is PCL-CVS. I suggest to use further one. It is much simpler - easier to use, supports well all common CVS functions and works transparently with CVS over SSH configuration. So I am going to describe how to use that one.

PCL-CVS has several function binded to key sequences. But these key bindings are active only when emacs is in CVS mode. To switch to CVS mode you must first execute one of a few functions which starts CVS command and automatically switches to CVS mode.

Warning! Do not use M-x cvs-mode command to switch to CVS mode when editing file.

Table 1. PCL-CVS commands switching to cvs-mode.

Function nameKeyDescription
cvs-quickdir

 none 

Populate the `*cvs*' buffer by just looking at the `CVS/Entries' files. This is very much like `cvs-examine' except that it does not access the CVS repository, which is a major advantage when the repository is far away. But of course, it will not be able to detect when a file needs to be updated or merged.
cvs-examine

 M-e 

Run a `cvs -n update' command. This is identical to the 'cvs-update' command, except that it will only check what needs to be done but will not change anything. You will be asked for the directory in which the `cvs -n update' will be run. Available also from main menu -> Tools -> PCL-CVS -> Examine Directory
cvs-update

 M-u 

Run a `cvs update' command. You will be asked for the directory in which the `cvs update' will be run. Available also from main menu -> Tools -> PCL-CVS -> Update Directory
cvs-status

 M-s 

Run a `cvs status' command. You will be asked for the directory in which the `cvs status' will be run. Available also from main menu -> Tools -> PCL-CVS -> Directory Status
cvs-checkout

 none 

Run a `cvs checkout' command. You will be asked for the directory in which the `cvs update' will be run and the module to be checked out. Available also from main menu -> Tools -> PCL-CVS -> Checkout Module

As most of similar libraries interacting with CVS repository PCL-CVS requires that you have a copy of a module somewhere in the file system. You can create this copy with any other CVS client as well as directly from emacs using PCL-CVS.

Formating code and using Jalopy

There is one package allowing you to use Jalopy from emacs with JDEE. This is jde-jalopy. It is not part of JDEE yet, so must be downloaded separately from it's home page.

To make it functional in your installation do as follows:

  1. It needs Jalopy console plug-in package available on project download page. So get it and unpack in some convenient for you place. For my case it is $PROJECTS_HOME/jalopy-1.0.2/ directory.

  2. Put jde-jalopy.el file in your custom packages location. (Look in the section called “General suggestions” for suggestion where to keep custom emacs packages.) Make sure it is in your emacs “load path”. And add to .emacs:

    Example 7. Loading package jde-jalopy in to emacs/jdee environment.

    ;;; If it is in different than others package
    ;;; directory you must add this location to emacs load path
    (add-to-list 'load-path "~/.emacs.d/jde-jalopy/location")
    ;;; Make jde-jalopy available under emacs
    (require 'jde-jalopy)
  3. Some jalopy options are global to all your projects and some can vary between projects. Global options should be placed in .emacs and the rest should go to prj.el files.

    Example 8. Global Jalopy settings in .emacs.

    (custom-set-variables
     '(jde-jalopy-option-path "$PROJECTS_HOME/jalopy-1.0.2")
     '(jde-jalopy-option-force t)
    )

    Please note that can be only one expression with custom-set-variables in your .emacs file. If there is already such expression you should only append to it lines with parameters.

    Example 9. Project local Jalopy settings in prj.el.

    (jde-set-variables
     '(jde-jalopy-option-preferences-file
       "$PROJECTS_HOME/geotools2/geotools-src/docs/sdocbook/resources/jalopygeotools.xml")
    )

    As in above example if there is already jde-set-variables expression in your prj.el file add your settings to existing list instead of creating new one.

Now you can start using it. When you are editing Java file and want to use Jalopy for it run command jde-jalopy-file (M-x jde-jalopy-file). Compilation buffer will open and you can see messages Jalopy generates during formating. Current version does not automatically refreshes changes in emacs buffer so you must “revert buffer” to see changes and work on file when formating is done.

Editing XML files

There are at least 3 solutions for editing SGML and XML files with emacs.

Built in sgml-mode - major mode.

Working on this...

Additional package xml-lite providing minor mode working with built in SGML major mode.

Simple extension for built in emacs SGML mode. It provides support for indentation and colorizing edited files. It adds a few parameters and key bindings to major mode.

Table 2. xml-lite customization options.

Variable nameDefault valueDescription
xml-lite-indent-offset4Specifies the default indentation level for `xml-lite-indent-line'.
xml-lite-indent-comment-offset5Specifies the indentation level for XML comments.
xml-lite-electric-slash'closeIf non-nil, inserting a '/' after a '<' behaves electrically. If set to `indent', typing '</' just triggers reindentation. If set to `close', typing '</' inserts an end-tag for the enclosing XML element.

Table 3. xml-lite commands added to sgml-mode

Function nameKeys bindingDescription
indent-for-tab-command

 TAB 

This is emacs built in function indeed. However it does not work in pure emacs sgml-mode. xml-lite adds support for intending for SGML and XML files and now it works in usual emacs way: “Indent line in proper way for current major mode or insert a tab.
xml-lite-slash

 / 

Behaves electrically if `xml-lite-electric-slash' is non-nil. See xml-lite-electric-slash description for detailed info.
xml-lite-insert-end-tag

 C-C / 

Insert an end-tag for the current element.
xml-lite-show-context

 C-c C-s 

Display the current context. Parse until it finds a start-tag as the first thing on a line. The context is a list of tag-info structures. The last one is the tag immediately enclosing the current position.

Future versions of emacs will contain xml-lite functions integrated into built in emacs sgml-mode. However at the moment you can download the last version of this package from this location .

Additional package PSGML providing major mode for editing XML and SGML files.

I started to work on this document using xml-lite mode. It works well and helps a lot if you don't spend too much time editing XML like documents. However, for large XML editing you definitely need more advanced library. PSGML gives you almost all you can need for your work with SGML/XML documents.

Installation and initial setup is easy. Just download the last available SGML version. I use the last alpha 1.3.1 version with no problems. Unpack it somewhere and put to your .emacs file following lines:

Example 10. .emacs file code to load and activate PSGML library for XML and SGML files.

(add-to-list 'load-path "~/.emacs.d/site-lisp/psgml")
(require 'psgml)
(autoload 'sgml-mode "psgml" "Major mode to edit SGML files." t)
(autoload 'xml-mode "psgml" "Major mode to edit XML files." t)

There is one important trick for PSGML customization. Not all (if any) settings are visible in SGML, XML mode if you put them directly in custom-set-variables or setq expressions. To have them working they should be set at the time of switching to SGML or XML mode. The best and most common way is to add function setting all variables to sgml-mode-hook and xml-mode-hook. So they will be set correctly every time you will open SGML or XML file. The sample code doing this is in file available at following addresses.

Example 11. Sample settings for PSGML package.

This file can be loaded from .emacs with command (load-file "~/.emacs.d/site-lisp/sgml-adds.el") or you can copy entire code to your .emacs. It contains not only my PSGML hook definition but also some more useful functions which can speed up XML/SGML coding. If you are interested only in sample code of personal hook setting look for function definition my-psgml-mode-hook.

Table 4. The most important commands and their keys for package PSGML.

Function nameKeys bindingDescription
sgml-insert-element

 C-c C-e 

Reads element name from mini-buffer and inserts start and end tags. Required elements in the content will be automatically inserted if the option `sgml-auto-insert-required-elements' is non-nil.
sgml-tag-region

 C-c C-r 

Makes the region into a new element. Reads element name from mini-buffer with completion.
sgml-insert-end-tag

 C-c / 

Inserts an end-tag for the current element.
sgml-split-element

 C-c RET 

Split the current element at point. If repeated, the containing element will be split before the beginning of then current element. Typical use is to start a new paragraph element when inside a paragraph.
sgml-insert-attribute

 C-c + 

Read attribute name and value from mini-buffer and insert attribute specification. If point is immediately after a start-tag, this command operates on that start-tag. Otherwise the command will operate on the element after point. The attribute name will be read with completion. If the attribute has a token list as declared value the attribute value will also be read with completion.
sgml-beginning-of-element

 C-M-a 

Move to the (content) beginning of the current element.
sgml-end-of-element

 C-M-e 

Move to the (content) end of the current element
sgml-forward-element

 C-M-f 

Move forward by element.
sgml-backward-element

 C-M-b 

Move backward by element.
sgml-down-element

 C-M-d 

Move down to the (content) beginning of the next element.
sgml-change-element-name

 C-c = 

Change the name of the current element. Tries to translate attribute specifications. An attribute will be translated to an attribute with the same name.
sgml-kill-element

 C-M-k 

Kill the element following the cursor.
sgml-untag-element

 C-c - 

Remove tags from current element.
sgml-make-character-reference

 C-c # 

Convert character under point to a character reference. If called with a numeric argument, convert a character reference back to a normal character.
fill-paragraph

 M-q 

Fill paragraph at or after point. It is standard emacs function but can is useful for filling current paragraph. It does not takes a lot of time nor CPU but also does not work well when there is a mixed content in current tag.
sgml-fill-element

 C-c C-q 

Fills an element as a paragraph. This is a substitute for the normal `fill-paragraph'. The command uses heuristics to decide what should be a paragraph.
  1. If point is in an element content, recursively fill the sub-elements.

  2. Find the biggest element with mixed content containing point.

  3. If the above element is mixed but contains elements with pure element content then fill what is between the pure elements as paragraphs and fill the pure elements recursively.

sgml-list-valid-tags

 C-c C-t 

List contextually valid tags.
sgml-next-trouble-spot

 C-c C-o 

The built-in parser can find some mark-up errors. To check the whole file go to the beginning of the buffer and use this command.
sgml-validate

 C-c C-v 

PSGML can not validate an SGML document. If you have a validating SGML parser, like sgmls or xmllint, you can run the parser on your file with the command. Go to PSGML configuration section to see how to set your favorite XML parser.
sgml-normalize

 none 

Normalize the document in the buffer.

A. Common JDEE and emacs commands table

I have put here table with the most important and often used functions of JDEE. Of course you can find all available functions in both off-line and on-line JDEE documentation. But I find it useful to have the most important functions in a table. In most cases descriptions were fully or partially copied from original JDEE documentation. So for many of them you can find more information in on-line JDEE documentation using: M-x describe-function, then ENTER, then write function name.

To see all JDEE key-bindings, call the function jde-keys under emacs. (M-x jde-keys)

Table A.1. Most often used commands quick reference table.

Function nameKeys bindingDescription
jde-keys

 none 

Displays JDEE key bindings.
jde-bug-keys

 none 

Displays JDEbug key-bindings.
describe-bindings

 none 

Show a list of all emacs defined keys, and their definitions.
jde-abbrev-mode

 none 

It is not used interactively indeed. Abbreviations in JDEE are very powerful and you should always have JDEE abbreviations turned ON. To turn them permanently on you don't have to use this function. Set value of jde-enable-abbrev-mode variable to true in your .emacs or prj.el file instead. Look in Appendix B, Abbreviations available in JDEE for more details.
next-error

 C-x ` 

Visit next compilation error message and corresponding source code.
jde-find

 C-c C-v C-f 

Find a regular expression REGEXP in all of the files in the current JDEE project.
jde-open-class-at-point

 C-c C-v C-y 

Find definition for symbol under cursor. Opens the Java file which defines the class where current point is and jumps to the definition of current thing at point (this can be a variable name, class name, method name, attribute name).
jde-complete-in-line

 C-c C-v . 

Completes the method or field name at point. Repeating the command cycles through all potential completions for the name. This function displays the signature of a method completion as specified by `jde-complete-display-current-signature'
jde-complete

 C-c C-v C-. 

Displays completions for the Java symbol at point. Depends on user settings possible completions can be displayed as context menu or in minibufer.
jde-gen-try-catch-wrapper

 C-c C-v t 

Wrap the region from BEG to END into a try/catch block. BEG and END are modified so the region only contains complete lines.
jde-gen-try-finally-wrapper

 C-c C-v f 

Wrap the region from BEG to END into a try/finally block. BEG and END are modified so the region only contains complete lines.
jde-import-find-and-import

 C-c C-v C-z 

Insert an import statement for a class in the current buffer. CLASS is an unqualified class name. This function searches the CLASSPATH for a class (or classes) that match CLASS. If it finds only one, it inserts an import statements for the class at the head of the current buffer. If it finds more than one class that matches CLASS, it prompts you to select which class to import.
jde-show-superclass-source

 C-c C-v C-x 

Show the source for the parent of the class at point.
jde-wiz-update-class-list

 C-c C-v C-q 

Update the class list used to resolve class names. The first time you invoke a JDEE wizard, the JDEE builds a list of all classes on the CLASSPATH defined by jde-global-classpath. Wizards use this list to resolve unqualified class names. If you add any classes to the CLASSPATH after invoking a wizard, you should update the class list.
jde-gen-println

 C-c C-v C-l 

Insert println statement.
jde-compile

 C-c C-v C-c 

Compile the Java program in the current buffer. This command invokes the compiler specified by `jde-compiler' with the options specified by the JDEE customization variables that begin with `jde-compile'.
jde-build

 C-c C-v C-b 

Rebuild the entire project. This command invokes the function defined by `jde-build-function'.

B. Abbreviations available in JDEE

This is list of abbreviations taken from version of JDEE - 2.3.2. To see list of abbreviations in your current version execute describe-variable emacs function with parameter jde-mode-abbreviations: M-x describe-variable, then ENTER, then jde-mode-abbreviations.

Table B.1. JDEE abbreviations table.

AbbreviationExpansionAbbreviationExpansionAbbreviationExpansion
ababstractbobooleanbrbreak
bybytebyvbyvaluecascast
cacatchchcharclclass
coconstconcontinuededefault
doudoubleelelseexextends
fafalsefifinalfinfinally
flfloatfoforfufuture
gegenericgogotoimplimplements
impoimportinsinstanceofinint
inteinterfacelolongnanative
nenewnunullpapackage
priprivateproprotectedpupublic
rereturnshshortststatic
susuperswswitchsysynchronized
ththisthrthrowthrowthrows
tratransienttrtruevovoid
volvolatilewhwhile