ToC DocOverview CGDoc RelNotes FAQ Index PermutedIndex
Allegro CL version 11.0

The Emacs-Lisp Interface

See franz.com/emacs/ for information on obtaining Emacs (which is no longer supplied with the Allegro CL distribution). That location links to a downloadable installer for GNU Emacs on Windows and to locations from which to download Emacs for Unix platforms. Once you have Emacs installed on your machine, you need to have it load the Emacs-Lisp interface files when it starts up. You do this by putting the appropriate form in your .emacs file, as described:

The page at franz.com/emacs/ has additional recommendations for the .emacs file, along with a list of convenient key bindings. The rest of this document is a more complete description of the Emacs-Lisp interface.

Platform-specific notes

Windows notes

ELI was previously incompatible with GNU Emacs on Windows which was compiled and run under Cygwin but was fixed with an update in March, 2006. For information on Cygwin, see www.cygwin.com.


1.0 Introduction to the Emacs-Lisp interface

An integral part of the Allegro CL programming environment is the interface between various implementations of Emacs (XEmacs or GNU Emacs) and Allegro CL, hereafter referred to as the Emacs-Lisp interface. This interface allows the editing and running of Common Lisp programs, and contains enhancements that allow a tight coupling between Emacs and Lisp, very similar to those which used to be available only on Lisp machines.

This document provides a technical description of the emacs-lisp interface. See Running Lisp as a subprocess of Emacs in startup.html for information on starting Allegro CL from emacs. Be sure that the necessary definition files are loaded so that the commands to start Allegro CL (using fi:common-lisp) are defined. See What should be in your .emacs file in this document.

Note that we do not include function definitions in this document. To see the documentation for a specific object, do C-h-f and specify the function name (including the fi:). Similarly for variables, but with C-h-v instead of C-h-f.

Unless otherwise specified, when we say Emacs in this document, we mean XEmacs or GNU Emacs.

We have tried to make the editor seem as if it is implemented in Lisp. However, such an editor would be able to manipulate objects not as text but as first-class Lisp objects and would then be able to know more about programs and be able easily to extract information from them. Emacs with the Emacs-Lisp interface cannot do all that.

Because the Emacs-Lisp interface uses Emacs, which runs as a separate OS process from Lisp, a protocol, called the Lisp-Editor protocol, was designed and implemented to make the communication of information between Emacs and Lisp easier and more natural. A strong requirement of this communication and information exchange is that the user not be aware of it--it must happen in the background. This hidden communication is accomplished by using multiprocessing (commonly called threads) in Allegro CL and process filters in Emacs. The latter is necessary because Emacs does not have multiprocessing.

The Lisp-Editor protocol is not documented in this release of Allegro CL.

This document is broken into several sections:

  1. Introduction to the Emacs-Lisp interface, the section you are now reading. This section presents an overview of the Emacs-Lisp interface and describes the organization of the whole document.
  2. Starting the Emacs-Lisp interface. This section discusses starting up the primary mechanism for Emacs-Lisp interaction. A troubleshooting guide suggests what may be wrong if things do not work as expected.
  3. Running Common Lisp. This section describes how Common Lisp can be started as a subprocess of Emacs.
  4. Editing Common Lisp Programs. This section discusses the facilities for editing of Lisp programs.
  5. Writing and Debugging Common Lisp Programs. This section discusses the finer points of debugging programs written in Lisp. In this section, many of the features associated with Lisp machines are discussed in detail.
  6. Shell modes. This section discusses other useful modes for creating shells, rlogins, telnets, etc. It is here for completeness and because many of the features in the Lisp subprocess modes are also available in these subprocess modes.
  7. Advanced miscellaneous features. This section discusses when Emacs Lisp hooks are called.

In the remainder of this section we discuss a number of topics related to Emacs and the Emacs-Lisp interface. The following headings describe the topics discussed. Each heading appears in large type later in this section, followed by one or more paragraphs describing the topic.

Note particularly What should be in your .emacs file. To use the Emacs-Lisp interface, you need only ensure that the correct files are loaded into your running Emacs. What should be in your .emacs file tells you what to put in your .emacs file in your home directory in order to ensure the files are loaded.

The topics are:


1.1 If you are new to Emacs

If you have never used Emacs before, then you should obtain an Emacs manual. A good one that describes GNU Emacs specifically but is generally applicable to all three supported versions is the GNU Emacs Manual. It is available from the Free Software Foundation (www.gnu.org/software/emacs/.

We assume in this document that you are familiar with Emacs although we do provide occasional hints for beginners.

Emacs has a few different forms of on-line help. Type Control-h (also called C-h for short) three times to find out about the on-line Emacs help facilities. To start the Emacs tutorial, type Control-h t.

The entire Emacs manual is available on-line through the Emacs Info program. Type Control-h i to start up the Info program. To run the Info tutorial, type h after starting the Info program.


1.2 Starting Allegro CL as a subprocess of Emacs

See Running Lisp as a subprocess of Emacs for information on starting Allegro CL as a subprocess of Emacs (the recomemnded way to use Allegro CL when developing applications, particularly on UNIX machines).


1.2.1 How to run two Emacs's connected to two different Lisps

You cannot run two different Lisp images from the same running Emacs. However, it is possible to run two Emacs's and have each connected to a different Lisp, and you may wish to do this when one Lisp image is performing some general function (such as running a server of some sort) and you wish to do some different work in a separate Lisp. On both Windows and UNIX, this can be done by starting two Emacs's and using fi:common-lisp in each Emacs to start a Lisp.

This also works (try it, particularly on Windows, if using fi:common-lisp in both Emacs processes does not work for any reason).

  1. In Emacs 1: run fi:common-lisp, which starts Lisp 1.

  2. Start Lisp 2, and in it evaluate (new-start-emacs-lisp-interface :port 9999 :announce-to-file "c:/tmp/eli").

  3. Start Emacs 2, and evaluate the following in the scratch buffer: (fi:start-interface-via-file "localhost" "*common-lisp*" "c:/tmp/eli"). Recall that you evaluate a form in the scratch buffer by entering Control-J at the end of the form.


1.3 Notation conventions used in this document

When discussing an editor, one needs to have a clear convention which identifies keyboard keys and combinations of keys. Also, Emacs needs to access certain files whose location depends on how Emacs was installed; we have to refer to these files in an unambiguous fashion even though we cannot know the exact location on your system.

We start with the conventions for files.

Now we discuss the conventions for identifying keyboard keys. The important point is that most Emacs commands are effected by entering one or more keystrokes, with each keystroke being a single key or a combination of keys pressed simultaneously. The most common keys used in combination with others are the CONTROL key, the ESCAPE key and the META key. (Most keyboards do not have a key labeled META, so another key is usually designated as the META key. On PC keyboards, for example, the ALT key is used for the META key. On Sun keyboards the LEFT key is used for the META key. Note also that in most cases, pressing the META and another key simultaneously has the same effect as pressing ESCAPE and the other key sequentially. Of the keys mentioned, only ESCAPE is pressed prior to rather than simultaneously with another key.)

Some more points about designating keys. First we say press to mean enter or depress a keyboard key. Second, CONTROL-a and CONTROL-A are the same character; whereas ESCAPE-a and ESCAPE-A are two different characters.


1.4 Format of this document

We loosely follow the format of the Emacs manuals in this document. That means that the templates for function and variable definitions are different from those used elsewhere in this manual. Each section starts with descriptive text describing the features of the section. At the end of each section, there is a complete list of the Emacs Lisp commands, functions, user options, and variables that apply to the general discussion in that section. The format of the function and variable descriptions follows the accepted documentation conventions in the GNU Emacs Lisp Reference Manual. Four types of objects are defined: interactive commands, program callable functions, user-settable options and variables. Here is how the definitions for each look.

command-name [Emacs command]
Arguments: formal arglist
function-name [Emacs function]
Arguments: formal arglist
user-option-name [Emacs user option]
Initial value: value
variable-name [Emacs variable]
Initial value: value

1.5 Previous versions of Emacs

The Emacs-Lisp interface works with all recent versions of GNU Emacs and XEmacs. Evaluating M-x emacs-version in your Emacs will print the version number. It is possible that the interface will not work with a version that was released after the release of Allegro CL. If that occurs, please contact us for assistance.

XEmacs users only:

You should use the xeli/ directory instead of the eli/ directory. elc (compiled emacs) files are not compatible between the GNU Emacs and XEmacs. The correct compiled files are in the appropriate directory.

The Emacs function fi:verify-emacs-support will determine if your Emacs has the internal code necessary for the Emacs-Lisp interface. Evaluating M-x fi:verify-emacs-support in your Emacs will print:

everything looks fine!

in the minibuffer if it finds the required support. Otherwise an error is signaled specifying the missing feature(s).


1.6 What should be in your .emacs file

The code for the Emacs-Lisp interface needs to be loaded into Emacs when Emacs starts up. There are different directories for GNU Emacs (the eli/ directory) and XEmacs (the xeli/ directory).

The simplest way to ensure that the interface is loaded is to have the proper forms in your $HOME/.emacs file (that is, the .emacs file in your home directory). On Windows, the "HOME" directory (not a defined concept) is c:\, so that is where Emacs will look for a .emacs file. You can use -l to specify a startup file to load and have that file be the equivalent of .emacs.

The exact forms depend on where Allegro CL was installed on your system.

Assuming that Allegro CL was installed into /usr/local/acl110/ on UNIX machines, here is the correct form to place in .emacs for GNU Emacs users:

(load "/usr/local/acl110/eli/fi-site-init")

Here is the correct form to place in .emacs for XEmacs users:

(load "/usr/local/acl110/xeli/fi-site-init")

In both cases, replace the directory with the correct directory if it is not what is shown.

On Windows machines, the standard location for the Allegro CL directory is *c:\acl110* (there may be additional characters like .64 or .smp or express). Use that or whatever directory was actually used in the .emacs file on Windows machines, again using eli/ or xeli/ as you are using GNU Emacs or XEmacs.


1.7 Emacs Documentation

Two manuals available from the Free Software Foundation will help users of Emacs: the GNU Emacs Manual (mentioned above) and the GNU Emacs Lisp Reference Manual. The latter manual describes the version of Lisp used internally by Emacs (called Emacs Lisp, which is not Common Lisp). Both are available from the Free Software Foundation, whose address can be found above in the section If you are new to Emacs.

All of the documentation available in the Emacs Info program may be printed on hardcopy, including the GNU Emacs Manual. To start the Emacs Info program, type C-h i. For information about printing hardcopy, see the Texinfo section of the Info program. Note that printing the Emacs manual is easiest if you have TeX.


1.8 Licensing issues and The Free Software Foundation

Users of the Emacs-Lisp interface are bound by the GNU Emacs copyright agreement. Note that all of the Emacs code may be redistributed.

Files whose type is el may be distributed with GNU Emacs under the terms of the GNU Emacs license agreement. Files without the extension el are not covered by the GNU Emacs License agreement and use is restricted according to the Franz Inc. License Agreement.


1.9 Quirks of the Emacs-Lisp Interface

Below is a brief list of Emacs-Lisp Interface features that have caused users trouble.


1.10 Security of the Emacs-Lisp Interface

You can limit the interface to the local host by modifying the value of *eli-daemon-socket-hook* as shown in the description of that variable.

There are other security issues. The password chosen to protect the connection is a small number, which can be bruteforced in a few seconds and some LEP variables appear to get overwritten even on error. Please note that the ELI was engineered before threats in common use today existed. We make improvements from time to time but if you have reason to be concerned about security, ELI may not be for you.


1.11 Bug reports and fixes

You may report bugs and problems with the Emacs-Lisp interface to us, just like Common Lisp bugs. If you report a bug or problem, please be sure to include the version of Lisp that you are running. Bugs in Emacs may also be reported however we are not always able to fix them.


1.12 Changes in the interface in Release 6.2

The Emacs/Lisp Interface was significantly changed in release 6.2. There have not been major changes since. In this section, we review the 6.2 changes.

There are five major areas of change, each described in its own section:

  1. Improved menu-bar menus

  2. Compliance with major mode conventions

  3. New keybindings

  4. Auto-arglist on SPC

  5. Pop-up buffer handling


1.12.1 Improved menu-bar menus

There are improved menus for Emacs and XEmacs 21 (and later). Previously in Emacs, Allegro CL-specific menu items were not mode specific. (They were mode-specific in XEmacs.) They are now mode-specific in Emacs. Previously, in both XEmacs and Emacs, there were several Allegro CL-specific menus on the menu-bar. Now, by default, there is a single Allegro CL-specific menu on the menu-bar, with sub-menus. The following variable can be used to retrieve previous functionality:

(defvar fi:menu-bar-single-item t
  "If non-nil then put a single item onto the menu-bar.  Otherwise, the
sub-menus in the single menu are put onto the menu-bar.  This variable is
ignored in all but XEmacs and Emacs 21 and later.")

Set this variable to nil in your .emacs file before loading "fi-site-init" if you want the previous behavior of multiple menus on the menu-bar.

For Emacs (and not XEmacs) the following additional changes have been made:


1.12.2 Compliance with major mode conventions, including user-visible changes after installing the patch

We now offer the option of complying with the major mode conventions outlined in the GNU Emacs Lisp Reference Manual, edition 2.5.

The variable fi:legacy-keybindings controls whether you use major mode convention compliant keybindings, or not. The compliant keybindings will be in effect when fi:legacy-keybindings is nil. Its initial value is t so that users downloading the patch will see only minimal behavior change.

(defvar fi:legacy-keybindings t
  "If non-nil then define the global, legacy keybindings, which in some
cases are in violation of the Elisp major mode conventions outlined in the
Emacs Lisp Manual.  For compatibility reasons the value of this variable is
t by default.")

More details on how keybindings relate to this variable are given below. (fi:legacy-keybindings subsumes the actions of fi:define-global-lisp-mode-bindings.) If you want to change the value of fi:legacy-keybindings, it should be set in your .emacs file before loading "fi-site-init".

Our goal with the patch was to minimize incompatibilities while offering compliance.

Consider the three different version/states of ELI:

  1. Pre-patch (version 2.3.5 or earlier), with fi:define-global-lisp-mode-bindings unchanged from the default value.

  2. Post-patch (version 2.4.0 or later), with fi:legacy-keybindings unchanged from the default value (which is t).

  3. Post-patch, with fi:legacy-keybindings changed to nil.

The differences between first two and second two states are outlined under the heading User-visible changes after installing the patch just below and User-visible changes (post patch) with fi:legacy-keybindings set to nil below that.

User-visible changes after installing the patch

Here are the changes to keybindings after the patch is downloaded but fi:legacy-keybindings has its initial value t. NEW means a new binding, DEL means a removed binding, FROM/TO denote a changed binding.

fi:common-lisp-mode:

        NEW     C-c C-a         fi:lisp-arglist
        NEW     C-c i           fi:insert-arglist
        NEW     C-c C-f         fi:lisp-function-documentation
        NEW     C-c C-j         fi:toggle-to-lisp
        NEW     C-c C-y         fi:kill-definition
        NEW     C-c C-z         fi:list-who-calls
        NEW     C-c RET         fi:lisp-macroexpand
        NEW     C-c (           fi:lisp-macroexpand-recursively
        NEW     C-c *           fi:pop-definition-mark


fi:inferior-common-lisp-mode:

        NEW     C-a             fi:subprocess-beginning-of-line
        NEW     C-c C-f         fi:lisp-function-documentation
        NEW     C-c C-j         fi:toggle-to-lisp
        NEW     C-c C-z         fi:list-who-calls
        NEW     C-c (           fi:lisp-macroexpand-recursively
        NEW     C-c *           fi:pop-definition-mark

        DEL     C-c -           fi:log-functional-change

        FROM    C-c C-a         fi:subprocess-beginning-of-line
        TO      C-c C-a         fi:lisp-arglist

        FROM    C-c C-y         fi:pop-input
        TO      C-c C-y         fi:kill-definition

        FROM    C-c RET         fi:subprocess-input-region
        TO      C-c RET         fi:lisp-macroexpand

C-a is added in accordance with the major mode conventions: it is reasonable for a major mode to rebind a key sequence with a standard meaning, if it implements a command that does "the same job" in a way that fits the major mode better. This makes C-c C-a obsolete and available for fi:lisp-arglist.

fi:pop-input (C-c C-y) was redundant (same as C-c C-p).

fi:subprocess-input-region (C-c RET) was obscure and little used, so C-c RET was used for fi:lisp-macroexpand.

fi:lisp-listener-mode:

        NEW     C-a             fi:subprocess-beginning-of-line
        NEW     C-c C-f         fi:lisp-function-documentation
        NEW     C-c C-j         fi:toggle-to-lisp
        NEW     C-c C-z         fi:list-who-calls
        NEW     C-c (           fi:lisp-macroexpand-recursively
        NEW     C-c *           fi:pop-definition-mark

        DEL     C-c -           fi:log-functional-change

        FROM    C-c C-a         fi:subprocess-beginning-of-line
        TO      C-c C-a         fi:lisp-arglist

        FROM    C-c C-y         fi:pop-input
        TO      C-c C-y         fi:kill-definition

        FROM    C-c RET         fi:subprocess-input-region
        TO      C-c RET         fi:lisp-macroexpand

fi:emacs-lisp-mode:

        DEL     C-c l           fi:toggle-to-lisp

fi:rlogin-mode, fi:shell-mode, fi:su-mode, fi:remote-su-mode:

        NEW     C-a             fi:subprocess-beginning-of-line
        NEW     C-c C-g         fi:telnet-start-garbage-filter
        NEW     DEL             backward-delete-char-untabify

        DEL     C-c C-a         fi:subprocess-beginning-of-line
        DEL     C-c C-y         fi:pop-input

fi:telnet-mode:

        NEW     C-a             fi:subprocess-beginning-of-line
        NEW     C-c C-g         fi:telnet-start-garbage-filter
        NEW     DEL             backward-delete-char-untabify

        DEL     C-c C-a         fi:subprocess-beginning-of-line
        DEL     C-c C-y         fi:pop-input
        DEL     C-c m           fi:telnet-start-garbage-filter

The following are new to all Lisp editing modes:

        NEW     C-c <        fi:previous-top-level-form
        NEW     C-c >        fi:next-top-level-form

User-visible changes (post patch) with fi:legacy-keybindings set to nil

This section details user-visible keybindings changes when the patch is downloaded and fi:legacy-keybindings has the value nil:

fi:common-lisp-mode:

        DEL     C-c A           fi:lisp-arglist
        DEL     C-c C           fi:list-who-calls
        DEL     C-c D           fi:describe-symbol
        DEL     C-c F           fi:lisp-function-documentation
        DEL     C-c M           fi:lisp-macroexpand
        DEL     C-c T           fi:toggle-trace-definition
        DEL     C-c W           fi:lisp-macroexpand-recursively
        DEL     C-c a           fi:lisp-arglist
        DEL     C-c c           fi:list-who-calls
        DEL     C-c d           fi:describe-symbol
        DEL     C-c f           fi:lisp-function-documentation
        DEL     C-c k           fi:kill-definition
        DEL     C-c l           fi:toggle-to-lisp
        DEL     C-c m           fi:lisp-macroexpand
        DEL     C-c t           fi:toggle-trace-definition
        DEL     C-c w           fi:lisp-macroexpand-recursively
        DEL     ESC A           fi:lisp-arglist
        DEL     ESC C           fi:list-who-calls
        DEL     ESC D           fi:describe-symbol
        DEL     ESC F           fi:lisp-function-documentation
        DEL     ESC M           fi:lisp-macroexpand
        DEL     ESC T           fi:toggle-trace-definition
        DEL     ESC W           fi:lisp-macroexpand-recursively

        FROM    C-c C-t         fi:trace-definer
        TO      C-c C-t         fi:toggle-trace-definition

The change of C-c C-t was deemed necessary since fi:toggle-trace-definition is more important than fi:trace-definer.

fi:inferior-common-lisp-mode and fi:lisp-listener-mode:

        DEL     C-c A           fi:lisp-arglist
        DEL     C-c C           fi:list-who-calls
        DEL     C-c D           fi:describe-symbol
        DEL     C-c F           fi:lisp-function-documentation
        DEL     C-c M           fi:lisp-macroexpand
        DEL     C-c T           fi:toggle-trace-definition
        DEL     C-c W           fi:lisp-macroexpand-recursively
        DEL     C-c a           fi:lisp-arglist
        DEL     C-c c           fi:list-who-calls
        DEL     C-c d           fi:describe-symbol
        DEL     C-c f           fi:lisp-function-documentation
        DEL     C-c k           fi:kill-definition
        DEL     C-c l           fi:toggle-to-lisp
        DEL     C-c m           fi:lisp-macroexpand
        DEL     C-c s           fi:scan-stack
        DEL     C-c t           fi:toggle-trace-definition
        DEL     C-c w           fi:lisp-macroexpand-recursively
        DEL     C-x RET         fi:inferior-lisp-input-list
        DEL     ESC A           fi:lisp-arglist
        DEL     ESC C           fi:list-who-calls
        DEL     ESC D           fi:describe-symbol
        DEL     ESC F           fi:lisp-function-documentation
        DEL     ESC M           fi:lisp-macroexpand
        DEL     ESC RET         fi:inferior-lisp-input-sexp
        DEL     ESC T           fi:toggle-trace-definition
        DEL     ESC W           fi:lisp-macroexpand-recursively

        FROM    C-c C-t         fi:trace-definer
        TO      C-c C-t         fi:toggle-trace-definition

        NEW     C-c &           fi:scan-stack

1.12.3 New keybindings

Other than the rearranged keybindings listed above, the following are completely new key bindings providing new functionality:

fi:common-lisp-mode:

        C-c *           fi:pop-definition-mark
        C-c <           fi:previous-top-level-form
        C-c >           fi:next-top-level-form
        SPC             fi:arglist-lisp-space

fi:inferior-common-lisp-mode:

        C-a             fi:subprocess-beginning-of-line
        C-c *           fi:pop-definition-mark
        SPC             fi:arglist-lisp-space

fi:lisp-listener-mode:

        C-a             fi:subprocess-beginning-of-line
        C-c *           fi:pop-definition-mark
        SPC             fi:arglist-lisp-space

C-c * is a convenient way to return to a previous context after C-c ..

fi:rlogin-mode, fi:shell-mode, fi:telnet-mode, fi:su-mode,
fi:remote-su-mode:

        C-a             fi:subprocess-beginning-of-line
        C-c C-g         fi:telnet-start-garbage-filter

For the shell-related modes, C-c C-g is a quick way to get rid of those annoying ^M's that occur on some systems.


1.12.4 Auto-arglist on SPC

The default behavior is now to retrieve and display in the minibuffer arglist information, when a connection to Lisp has already been made and the arglist information is available for the symbol before the point at the time SPC is typed. The variable which controls this feature is:

(defvar fi:arglist-on-space t
  "If non-nil, then bind SPC to a function that retrieves arglist
information and displays it according to the value of the variable
fi:auto-arglist-pop-up-style.")

The method by which the arglist is displayed is controlled by this variable:

(defvar fi:auto-arglist-pop-up-style '(minibuffer)
  "The value of this variable is used to bind
fi:pop-up-temp-window-behavior when ([fi:arglist-lisp-space]) is executed.
A value of '(split . nil) is handy for insuring that the arglist
information stays around long enough to be used.")

In Emacs 21 or later, the default behavior of the minibuffer is to grow dynamically, and this will allow even large arglists to be displayed without having a new buffer pop up. If you want more permanance to the arglist information, while you type in your program, use this in your .emacs:

(setq fi:auto-arglist-pop-up-style '(split . nil))

XEmacs does not have a dynamically resizing minibuffer, so if the information being displayed is larger than one line, it will be put into the *CL-Temp* buffer.


1.12.5 Pop-up buffer handling

Pop-up buffer handling has been improved. The value of fi:pop-up-temp-window-behavior can now be the list '(minibuffer), which allows for the minibuffer to be used for Lisp-queried information (e.g., arglist, macro expansions), as well as evaluations of user code.

The documentation for fi:pop-up-temp-window-behavior has also been improved:

(defvar fi:pop-up-temp-window-behavior '(other . t)
  "The value of this variable determines the behavior of the popup
temporary buffers used to display information which is the result of
queries of the Lisp environment.  As of version 2.4.0 of the interface,
this includes output generated by arbitrary evaluations of user-written
Lisp code, when the value of this variable is '(minibuffer).

The value is a cons of the form (style .  boolean).

The possible values for the `style' (or the car of the cons) are the symbols
minibuffer, split, other, and replace:

- `minibuffer' causes the minibuffer to always be used, regardless of the
number of lines of output.  Recent versions of Emacs have dynamically
resizing minibuffers, and this is useful in combination with these newer
versions.

- `split' causes the largest window to be split and the new window to be
minimal in size.

- `other' causes the other window to be used, splitting the screen if there is
only one window.

- `replace' causes the current window to be replaced with the help buffer.

The possible values for the `boolean' (or cdr of the cons) are `t' or
`nil'.  `t' means use the minibuffer, and if the resulting text does not
fit, use a window.  `nil' means always use a window.  A value of `nil' is
handy since messages printed in the minibuffer can easily be erased.

If the `style' is `minibuffer', then the `boolean' is ignored, since
the minibuffer is always used, regardless of the amount of output.")

1.12.6 Misc

Many thanks to Bill Clementson for many of the suggestions and helping with testing.


2.0 Starting the Emacs-Lisp interface

Starting the Emacs-Lisp interface is actually a misnomer. Assuming the interface code has been loaded into Emacs, it is available whenever Emacs is running. (Below, in Running Common Lisp, we describe how to start Lisp from within Emacs). Therefore, this section is really about ensuring that the interface is loaded into Emacs.

The simplest way to ensure that the interface is loaded is to have the proper forms in your $HOME/.emacs file (that is, the .emacs file in your home directory). See What should be in your .emacs file for information on what to put in that file.

With the proper form in the .emacs file, the interface will be loaded when Emacs starts up. Note that in the following sections, we discuss many variables that customize the Emacs-Lisp programming environment. Forms changing the default values of these variables can also be put in the .emacs file, allowing you to customize the environment to your liking. Note that these forms should be placed before (above) the two forms specified above.

While putting the specified load form in $HOME/.emacs (as described in What should be in your .emacs file) is the recommended method of loading the Emacs-Lisp interface, it is not required. If you are using Emacs and the Emacs-Lisp interface is not loaded, you can load it as follows.

For GNU Emacs users:

M-x load-file RET [Allegro directory]/eli/fi-site-init

For XEmacs users:

M-x load-file RET [Allegro directory]/xeli/fi-site-init

The [Allegro directory] is the directory where Allegro CL is installed.

Note about running Common Lisp on a different machine than Emacs

If M-x fi:common-lisp is used to start a Common Lisp process on a remote machine (i.e. a different machine than the one running Emacs), and Emacs is exited without first exiting from Common Lisp, Common Lisp may continue running on the remote machine. While there seems to be no sure-fire way to prevent this, you can load code into Emacs which prevents you from exiting Emacs while Common Lisp is running. This code is contained in the file misc/dot-emacs (misc/dot-emacs.el on Windows) in the Allegro directory. Make use of this code if you wish by placing it in your .emacs file in your home directory (misc/dot-emacs is a sample .emacs file).


2.1 Troubleshooting the Emacs-Lisp interface

This section gives some hints about what may be wrong if either the Emacs-Lisp interface does not seem to be available at all or does not seem to work as described in this document. The interface is supported by Franz Inc. (although we do not support Emacs itself), so problems with the interface can be reported to us just like bugs or problems with Allegro CL and related products. We do ask, however, that you check out the suggestions here before reporting a problem to us. The following problems are discussed in this section, each under a heading in bold type.


2.1.1 Emacs reports that a function defined in the interface is undefined

Suppose you try to invoke the command fi:common-lisp (which starts up Allegro CL within Emacs) and Emacs reports that function is undefined. A likely cause is that the Emacs-Lisp interface is not loaded. The variable fi:package-loaded is set to t when the interface is loaded. Evaluate that variable in a scratch buffer (by typing its name followed by a LINEFEED -- i.e Control-J). If the value is nil, the interface is not loaded. Check your $HOME/.emacs file and make sure the form that loads "fi-site-init" is in the file. If the value of the variable is t, there is a more serious problem which does not have an easily identifiable cause.


2.1.2 Emacs reports that it encountered an error when loading .emacs

The cause of this problem cannot be known in advance. Here we suggest how to further investigate. Exit Emacs and restart it with the -q option (which suppresses the loading of the $HOME/.emacs file). Then type the following in the scratch buffer:

(setq debug-on-error t) LF
(load "~/.emacs") LF

Note that you press LINEFEED (LF, typically Control-J) rather than RETURN (RET) after typing the forms.

If you run Emacs and Lisp on different machines, then you must be certain that the value of fi:emacs-to-lisp-transaction-directory is a directory which is accessible on both machines. Care must be taken to get the pathname just right, including the possible NFS prefix (/net/MACHINE-NAME/...).


2.1.3 Checking your setup

If you are having trouble with the Emacs-Lisp interface, we recommend that you check for trouble involving your personal .emacs and .clinit.cl files.

  1. Start up Emacs with the -q option: [shell prompt]% emacs -q This will start up Emacs without reading your .emacs file.

  2. Load the Emacs-Lisp interface by hand: M-x load-file RET [Allegro directory]/eli/fi-site-init

  3. Start up a Common Lisp image with the -qq option: M-x fi:common-lisp; answer the question: Image arguments (separate by spaces): with -qq This will start up Common Lisp without reading any .clinit.cl files.

  4. Try the Emacs-Lisp interface command that tests the interface: M-x fi:verify-emacs-support. See Previous versions of Emacs for more information about this command.


2.1.4 Other strange or unexplained behavior

The most common cause of other strange or unexplained behavior is using the Emacs-Lisp interface with a version of Emacs other than the one distributed with Allegro CL. The Emacs-Lisp interface is only supported on that specific version. While only the person who installed Allegro CL and Emacs knows for sure, a simple test is to compare the version number specific in the Release Notes with the version number stored in the Emacs image itself, accessed with the function emacs-version. To evaluate this function, enter

M-x emacs-version

to Emacs. This function returns a string specifying the version number. Note that even if that number is the same as that in the Release Notes, it may not be the exact version from the Allegro CL distribution. However, if the numbers are different, it is certainly not the same.

Also note that fi: is not a package prefix (as it would be in Common Lisp). Instead, it is just part of the symbol name so you always must type it. (We use fi: to guarantee that the names of functions defined in our interface do not conflict with other function names.)


3.0 Running Common Lisp

Interacting with Common Lisp occurs in an Emacs subprocess buffer. This interaction can even occur between Emacs and Common Lisp processes that reside on different machines. Common Lisp must be started with the function fi:common-lisp or with fi:start-interface-via-file. Although you can (using fi:start-interface-via-file) start Common Lisp in an Emacs shell and then initiate the interface, it is unusual to do so. Note that most of the Emacs-Lisp interface will not work with a Lisp image started in an Emacs shell and not connected to Lisp using fi:start-interface-via-file.

Starting with fi:common-lisp

When called for the first time in an emacs session, fi:common-lisp prompts in the minibuffer for information on how you wish to invoke Lisp (see section Functions and variables for Interacting with a CL subprocess for details on what questions are asked). Subsequent calls use the previous answers unless qualified with C-u. Once it knows what to invoke, fi:common-lisp makes a Common Lisp subprocess in a buffer named (in the default) *common-lisp*. After start-up, *common-lisp* might have contents which look similar to this:

Allegro CL 11.0
Copyright (C) 1985-2023, Franz Inc., Lafayette, CA, USA
;; Optimization settings: safety 1, space 1, speed 1,
;; debug 2. For a complete description of all compiler
;; switches given the current optimization settings
;; evaluate (EXPLAIN-COMPILER-SETTINGS).
;; Starting socket daemon and emacs-lisp interface...
USER(1):

First, what you in fact see will probably be different. In particular everything after 11.0 in the first line will likely be different (the information there specifies the exact version shipped to you); the notice in comments may be changed and anyway, we have changed the linebreaks to prevent wrapping; and the code changes faster than the documentation. However, what you see will be similar.

The user(N): is the Allegro CL prompt. The comment just before the first prompt signifies that an Allegro CL process that communicates with Emacs has started (see multiprocessing.html for a definition of process). Meanwhile, in the Emacs minibuffer, you should see

Trying to start connection...done.

That message signifies that the hidden, or backdoor, communication between Emacs and Common Lisp has been initiated. Emacs and Common Lisp will be communicating over a network connection.

The Emacs-Lisp interface is currently started with the -e Allegro Common Lisp command line option. This allows the interface to be started for images that do not behave like a standard Common Lisp image (with a read-eval-print loop). For more information, see the description of fi:start-lisp-interface-arguments in Functions and variables for Interacting with a CL subprocess below.

It is possible for the interface to fail to start up (failure will be indicated by the failure of Starting socket daemon and emacs-lisp interface... to appear in the common-lisp buffer or the failure of Trying to start connection...done to appear in the Emacs minibuffer. You can start the interface (or restart it if it dies) with the Allegro CL function new-start-emacs-lisp-interface.

Starting with fi:start-interface-via-file

The emacs function fi:start-interface-via-file allows you to connect Emacs to a running Lisp after Lisp has started. This is typically done for debugging a running but apparently broken process. fi:start-interface-via-file takes arguments host buffer connection-file, specifying the host machine, the emacs buffer name, and the file created by new-start-emacs-lisp-interface that will be used for the connection. To start the interface using this method, on the lisp side, you would do something like this:

(excl:new-start-emacs-lisp-interface :port 7666 
           :announce-to-file"~/.eli-startup")

See
new-start-emacs-lisp-interface for a discussion of the arguments. Then, sometime later on the emacs side, do this (the host is "pie"):

(fi:start-interface-via-file "pie" "*common-lisp*" "~/.eli-startup")

3.1 Key bindings in Common Lisp subprocess mode

The tables in this section have been updated and describe the new behavior with fi:legacy-keybindings having its initial value t (fewest changes) and the value nil (most changes).

Many of the key bindings in a common-lisp buffer behave much like a shell buffer does. The common-lisp buffer and a shell buffer have mode specific commands with the key prefix C-c. Both buffers have key bindings that will delete typed input (words or lines), send an EOF or interrupt, or send the input to the Allegro CL process.

The key bindings can be classified into four categories: (1) General subprocess interaction, (2) Editing, (3) Lisp environment queries, and (4) Superkeys (Superkeys are keybindings that have different effects according to whether they are entered at the end of a buffer or elsewhere in the buffer). We describe the key bindings in each category next.

General subprocess interaction

The keys/functions in this category provide the functionality that a shell buffer would have. All the special characters (C-c, C-d, C-w, C-u, etc.) are handled by these functions:

key binding
C-a fi:subprocess-beginning-of-line
C-c C-\ fi:subprocess-quit
C-c C-c fi:interrupt-listener
C-c C-d fi:subprocess-send-eof

(fi:remote-lisp-send-eof when Lisp is remote)
C-c C-j fi:toggle-to-lisp
C-c C-k fi:subprocess-kill-output
C-c C-l fi:list-input-ring
C-c C-n fi:push-input
C-c C-o fi:subprocess-send-flush
C-c C-p fi:pop-input
C-c C-r fi:re-search-backward-input
C-c C-s fi:re-search-forward-input
C-c C-u fi:subprocess-kill-input
C-c C-v fi:subprocess-show-output
C-c C-w fi:subprocess-backward-kill-word
C-c = fi:lisp-sync-current-working-directory
C-x RET fi:inferior-lisp-input-list if fi:legacy-keybindings is non-nil, no binding otherwise
ESC RET fi:inferior-lisp-input-sexp if fi:legacy-keybindings is non-nil, no binding otherwise
RET fi:inferior-lisp-newline

Table 1: General Subprocess Keybindings

Editing

The keys/functions in this category provide the functionality to edit and enter expressions that will be processed by Common Lisp:

key binding
TAB fi:lisp-indent-line
DEL backward-delete-char-untabify
; fi:lisp-semicolon (if fi:lisp-do-indentation is non-nil)
C-c ] fi:super-paren
C-c % fi:extract-list
C-c ; fi:comment-region
C-c ^ fi:center-defun
C-c C-e fi:end-of-defun
C-c C-q fi:indent-sexp
C-c C-y fi:kill-definition
ESC C-q fi:indent-sexp

Table 2: Editing Keybindings

Lisp environment query

The keys/functions in this category provide a way to obtain information from the Allegro CL environment. These functions use the hidden communication between Emacs and Lisp to simulate Lisp-machine like behavior:

key binding
C-c C-afi:lisp-arglist
C-c ifi:insert-arglist
C-c C-ffi:lisp-function-documentation
C-c TABfi:lisp-complete-symbol
C-c RETfi:lisp-macroexpand
C-c C-t fi:trace-definer if fi:legacy-keybindings is t, fi:toggle-trace-definition if fi:legacy-keybindings is nil
C-c C-yfi:kill-definition
C-c C-zfi:list-who-calls
C-c (fi:lisp-macroexpand-recursively
C-c *fi:pop-definition-mark
C-c .fi:lisp-find-definition
C-c 4 .fi:lisp-find-definition-other-window
C-c ,fi:lisp-find-next-definition
C-c ?fi:lisp-apropos
C-c SPCfi:lisp-delete-pop-up-window
C-c &fi:scan-stack
C-c Afi:lisp-arglist if fi:legacy-keybindings is non-nil, no binding otherwise
C-c Cfi:list-who-calls if fi:legacy-keybindings is non-nil, no binding otherwse
C-c Dfi:describe-symbol if fi:legacy-keybindings is non-nil, no binding otherwise
C-c Ffi:lisp-function-documentation if fi:legacy-keybindings is non-nil, no binding otherwise
C-c Kfi:kill-definition if fi:legacy-keybindings is non-nil, no binding otherwise
C-c Lfi:toggle-to-lisp if fi:legacy-keybindings is non-nil, no binding otherwise
C-c Mfi:lisp-macroexpand if fi:legacy-keybindings is non-nil, no binding otherwise
C-c Sfi:scan-stack if fi:legacy-keybindings is non-nil, no binding otherwise
C-c Tfi:toggle-trace-definition if fi:legacy-keybindings is non-nil, no binding otherwise
C-c Wfi:lisp-macroexpand-recursively if fi:legacy-keybindings is non-nil, no binding otherwise
C-c afi:lisp-arglist if fi:legacy-keybindings is non-nil, no binding otherwise
C-c cfi:list-who-calls if fi:legacy-keybindings is non-nil, no binding otherwse
C-c dfi:describe-symbol if fi:legacy-keybindings is non-nil, no binding otherwise
C-c ffi:lisp-function-documentation if fi:legacy-keybindings is non-nil, no binding otherwise
C-c kfi:kill-definition if fi:legacy-keybindings is non-nil, no binding otherwise
C-c lfi:toggle-to-lisp if fi:legacy-keybindings is non-nil, no binding otherwise
C-c mfi:lisp-macroexpand if fi:legacy-keybindings is non-nil, no binding otherwise
C-c sfi:scan-stack if fi:legacy-keybindings is non-nil, no binding otherwise
C-c tfi:toggle-trace-definition if fi:legacy-keybindings is non-nil, no binding otherwise
C-c wfi:lisp-macroexpand-recursively if fi:legacy-keybindings is non-nil, no binding otherwise

Table 3: Lisp Environment Query Keybindings

The functions in this category that read symbols also do dynamic completion of symbols present in the Allegro CL environment. The Emacs-Lisp interface has no static symbols database, so a symbol is available for completion just after it is created. See the description of fi:lisp-complete-symbol in Finding the definitions of functions below.

Superkeys

Because there is a set of process-related functions that are needed in the common-lisp buffer, these key bindings have a special meaning at the end of the buffer. That is, there are certain key sequences which have behavior determined by fi:inferior-common-lisp-mode when typed at the end of the buffer, but have their global meaning when typed anywhere else in the buffer. The key sequences and their meanings are given below, and they are only in effect when fi:subprocess-enable-superkeys is non-nil (before fi:inferior-common-lisp-mode is entered for the first time)

key binding
C-\ send "kill -QUIT" (UNIX quit) to Common Lisp
C-d send EOF to Common Lisp
C-o flush output (from "stty flush")
C-u delete the current input (from "stty kill")
C-w delete the last word (from "stty werase")
C-z suspend job (from "stty susp"), only for shell-related modes

Table 4: Superkeys

C-w, C-u, and C-o are chosen because those are the (default) keys used by stty werase, kill, and flush in Unix.

So, C-d at the end of the common-lisp buffer will send Common Lisp an end of file, and at other places in the buffer will delete the next character (unless you have rebound C-d to call another function). See the entry for fi:superkey-shadow-universal-argument for ways to control the universal argument C-u.


3.2 Typing input to Common Lisp

The Emacs Lisp function bound to RET is more than just "send the current line to the Common Lisp process". In fact, it sends only entire s-expressions, or forms, to Common Lisp. This allows editing of incomplete, multi-line expressions before Common Lisp sees them.

To accomplish the advanced input features, Emacs needs to know the form of the Common Lisp prompt. The prompt in Allegro CL is defined by the value of the variable *prompt*. This value must be a string acceptable as the second argument to format. Although the prompt can be changed at any time, it is typically set in the file $HOME/.clinit.cl. But however the prompt is changed, the Emacs user option fi:common-lisp-prompt-pattern must be changed as well -- so that the default value of *prompt* (in Common Lisp) and fi:common-lisp-prompt-pattern (in Emacs Lisp) are in agreement.

See the file misc/prompts.cl in the Allegro directory for examples of other prompts. See top-level.html for information on the prompt itself.


3.2.1 Input rings

The subprocess input ring helps to minimize typing in many different modes of the Emacs-Lisp interface. The Emacs-Lisp interface shell modes and Common Lisp modes have subprocess input rings. The subprocess input ring is similar to the Emacs kill ring, except each subprocess buffer has a separate subprocess input ring. Previously typed input can be yanked to the prompt at the end of the Common Lisp subprocess buffer. It can then be edited before sending it to Common Lisp. The selection of which input to yank can be the previous, next or selected by regular expression search through the input ring. See the Emacs-Lisp interface commands fi:list-input-ring, fi:pop-input, fi:push-input, fi:re-search-backward-input, and fi:re-search-forward-input.


3.2.2 Tracking directory changes

Top-level commands to change the directory in the Common Lisp process are watched by Emacs, so that the Emacs variable default-directory can be changed when the Common Lisp current working directory is changed. The Common Lisp top-level commands :cd, :pushd, and :popd are tracked, and when typed in the common-lisp buffer the new directory is saved in default-directory.

The Common Lisp top-level commands :dirs and :pwd do exactly what their C shell counterparts do: print the directory stack and current working directory.


3.2.3 Tracking package changes

Another Common Lisp top-level command, :package, is tracked by the Emacs-Lisp interface. When package changes are done either via the top-level command :package or the macro in-package, Emacs tracks the current package of the *common-lisp* buffer. The current package is used by many Emacs-Lisp interface functions that query the Common Lisp environment, such as fi:lisp-arglist and fi:insert-arglist.

The current package is displayed in the mode-line. So, when

:package foo

is entered in the *common-lisp* buffer, the mode-line will be updated to contain the string pkg:foo after the mode identifier. See Packages and readtables for more information.


3.2.4 Lisp Listeners

Because Allegro CL has multiprocessing (see multiprocessing.html for more information), multiple threads of control can be created--multiple user interactions, or top-levels, can be created within the same UNIX process. Within one Common Lisp process, any number of lisp listeners, as these top-levels are called, can be created.

The Emacs-Lisp interface has a function for creating a lisp listener onto an existing Common Lisp subprocess: fi:open-lisp-listener. This can be used to debug multiprocessing applications or to execute forms while Common Lisp is doing other processing. See also Lisp Listeners and multiprocessing.


3.2.5 Argument lists

When an open parenthesis and an operator name is typed, the argument list is displayed is the minibuffer if it is known (see fi:arglist-on-space and fi:auto-arglist-pop-up-style). The argument list is also displayed by fi:lisp-arglist (C-c C-a).

A new command, fi:insert-arglist, was added in a Summer, 2006 update. Its binding is C-c i and when invoked after '( ', it inserts the argument list into the code being written. The user can then edit the insertion with the desired argument values. Here are some examples:

;;  In each case, we define a function (except where we use a standard
;;  CL function), and the type '(<fun-name> C-c i'. We show 
;;  what is inserted:

cl-user(198): (defun foo (a &key (b 'bee) (c 'cee)) (list a b c1))
foo
cl-user(199): (foo a :b b :c c)

cl-user(201): (defun foo (a b &rest c) (list a b c))
foo
cl-user(202): (foo a b c...)

cl-user(202): (defun foo (a &optional b c d) (list a b c d))
foo
cl-user(203): (foo a [b] [c] [d])

cl-user(203): (find item sequence :from-end from-end :test test :test-not test-not :start start :end end :key key)

;;  Even uncommon constructions are supported. In the following definition,
;;  the designator name of the second keyword argument is the symbol C
;;  (not the keyword :C) while the argument name is C1.  Anyway, C-c i
;;  does the right thing:

cl-user(203): (defun foo (a &key (b 'bee) ((c c1) 'cee)) (list a b c1))
foo
cl-user(204): (foo a :b b 'c c)

3.3 Functions and variables for Interacting with a CL subprocess

The function fi:common-lisp starts Common Lisp from within Emacs.

Below is a fragment of code which can be placed in your .emacs file that defines a function run-common-lisp, which will start up a Lisp with default arguments. run-common-lisp is useful if the user frequently uses the same Lisp.


(setq fi:common-lisp-image-name "/usr/local/acl110/mlisp")
(setq fi:common-lisp-host "ultra")

;; This function starts up lisp with your defaults.
(defun run-common-lisp ()
  (interactive)
  (fi:common-lisp fi:common-lisp-buffer-name
                  fi:common-lisp-directory
                  fi:common-lisp-image-name
                  fi:common-lisp-image-arguments
                  fi:common-lisp-host
                  fi:common-lisp-image-file))

;;  This function uses specific values rather than variables.
;;  Either way works and one may be more suitable for you than 
;;  another (this example runs a Lisp on Windows from an Emacs
;;  running on Windows:

(defun run-ide ()
  (interactive)
  (fi:common-lisp "*common-lisp*"
          "h:/acl110/"
          "h:/acl110/allegro.exe"
          '("")
          "localhost"
          "h:/acl110/allegro.dxl"))
;; Set up a keybinding for `run-common-lisp', two possible ways
;; (keybindings for run-ide are analogous):
(progn
  (setq ctlx-3-map (make-keymap))
  (define-key ctl-x-map "3" ctlx-3-map)
  (define-key ctlx-3-map "l" 'run-common-lisp))
;; or this:
(define-key global-map "\C-xl" 'run-common-lisp)

;; Run cl each time emacs is run:
(run-common-lisp)
fi:emacs-lisp-interface-version
fi:verify-emacs-support
fi:common-lisp
fi:open-lisp-listener
fi:common-lisp-buffer-name
fi:common-lisp-directory
fi:common-lisp-image-name
fi:common-lisp-image-file
fi:common-lisp-image-arguments
fi:common-lisp-host
fi:common-lisp-prompt-pattern
fi:common-lisp-subprocess-timeout
fi:common-lisp-subprocess-wait-forever
fi:legacy-keybindings
fi:define-global-lisp-mode-bindings
fi:menu-bar-single-item
fi:compile-at-load-time
fi:toggle-to-lisp
fi:connect-to-windows
fi:start-lisp-interface-arguments
fi:use-background-streams
fi:start-lisp-interface-hook
fi:start-interface-via-file
fi:reset-lep-connection
fi:in-package-regexp
fi:default-in-package-regexp
fi:inferior-common-lisp-mode
fi:inferior-lisp-input-list
fi:inferior-lisp-input-sexp
fi:inferior-lisp-newline
fi:inferior-lisp-send-input
fi:lisp-sync-current-working-directory
fi:list-input-ring
fi:pop-input
fi:push-input
fi:re-search-backward-input
fi:re-search-forward-input
fi:remote-lisp-send-eof
fi:subprocess-backward-kill-word
fi:subprocess-beginning-of-line
fi:subprocess-input-region
fi:subprocess-interrupt
fi:subprocess-kill
fi:subprocess-kill-input
fi:subprocess-kill-output
fi:subprocess-quit
fi:subprocess-send-input
fi:subprocess-send-eof
fi:subprocess-send-flush
fi:subprocess-show-output
fi:subprocess-suspend
fi:lisp-listener-mode
fi:interrupt-listener
fi:tcp-lisp-listener-kill-process
fi:tcp-lisp-listener-send-eof
fi:emacs-to-lisp-transaction-directory
fi:default-input-ring-max
fi:display-buffer-function
fi:new-screen-for-common-lisp-buffer
fi:eval-in-lisp
fi:eval-in-lisp-asynchronous
fi:filename-frobber-hook
fi:lisp-evalserver-number-reads
fi:shell-cd-regexp
fi:shell-popd-regexp
fi:shell-pushd-regexp
fi:subprocess-continuously-show-output-in-visible-buffer
fi:subprocess-enable-superkeys
fi:user-env-vars
fi:subprocess-env-vars
fi:subprocess-max-buffer-lines
fi:superkey-shadow-universal-argument

4.0 Editing Common Lisp Programs

This section and its subsections discuss the Emacs mode for editing Common Lisp programs.

Common Lisp editing mode, fi:common-lisp-mode, is automatically entered when a Common Lisp source file is visited. The Emacs Lisp variable fi:common-lisp-file-types specifies the file types of Common Lisp source files. The following sections discuss the various aspects of fi:common-lisp-mode. Please note that bindings in this mode are changed by a patch made available in August, 2003. See Changes in the interface in Release 6.2 for details.


4.1 Indentation

Indentation of a form can be performed with C-M-q, (Hold the CONTROL and META keys while depressing the q key) when the point is on an opening parenthesis. Indentation of the current line can be performed by typing TAB.

All Common Lisp forms are indented with the generally accepted amount of indentation. At the current time, the user interface to the indentation method specification is not documented. It is, however, available for your perusal in the file fi/indent.el - -there are many examples at the end of this file.

Comments in Common Lisp begin with a semicolon (;). Comments starting with different numbers of semicolons are indented differently. The Emacs Lisp variable fi:lisp-comment-indent-specification specifies how the indentation is done. fi:lisp-comment-indent-specification is a list, where the Nth element (counting from 1) specifies how N semicolons will be indented. That is, the first element specifies how a single semicolon will be indented. The values in the list are either:

The initial value of fi:lisp-comment-indent-specification is

`(list 40 t nil 0)

which means indent one semicolon to column 40, two semicolons to the column s-expressions would indent to, three semicolons should be left alone, and four semicolons are left justified.

NOTE: if the buffer-local variable comment-column is changed, then the first element of fi:lisp-comment-indent-specification is changed to contain the value of comment-column.

Additionally, if fi:lisp-electric-semicolon is non-nil, then semicolon placement will happen automatically when semicolons are inserted into the buffer--no TAB is required to indent the current line. The value of this variable defaults to nil.

Here is an example of each type, using default values:

;;;; Foo the Bar

(in-package :foo)

(defun bar (thang)
  ;; BAR the THANG
;;;; WARNING: frobs beware
  (frob-the-frammis thang)              ; out in right margin field
;;; leave me where I lie...
  ;; but indent by right...
  )
fi:lisp-comment-indent-specification

4.2 Packages and readtables

The Common Lisp package in which a source file is defined is an important quantity which must be known to Emacs. Readtables, though less essential, are also useful when known to Emacs. Such information is used by Emacs, when communicating with Common Lisp, to insure that the operations performed in the Common Lisp environment are with respect to the correct package and expressions are read with the correct readtable.

There are two methods for telling Emacs about which package to use.

  1. The in-package macro form is parsed when a file is visited, and the argument to in-package is used as the package for that buffer.

  2. The file mode line (unfortunately named, since the name conflicts with the display mode line) also communicates information about the file to Emacs.

The file mode line can also be used to specify a readtable and the Emacs mode. A file mode line must be the first line of text in the file and has the following form:

; -*- ... -*-

where ... has the following fields:

Fields in the file mode line are separated by semicolons. The following example illustrates a file mode line: With the in-package and eval-when forms, loading this file into Emacs will result in the correct package and readtable being used by Lisp operations on the file:

;; -*- mode: fi:common-lisp-mode; package: mypack; readtable: myrt -*-
(in-package :mypack)
(eval-when (compile 
            load    ;; see note below
            eval)
  (setq *readtable* (named-readtable :myrt)))
; ... [rest of code]

Note: load is not needed in the eval-when form when no extraneous reading will happen when the compiled version of this file is loaded. load must be omitted if the named readtable does not actually exist at runtime (when, for example, you use a special readtable for developing an application but it is not included in the application when it is finished).

The file mode line is parsed by the standard Emacs Lisp function set-auto-mode, which has been modified by this interface to look for the package and readtable fields. If you change the file mode line or in-package form in a buffer, you may execute the Emacs Lisp function fi:parse-mode-line-and-package to re-parse the package. A file mode line, if supplied, overrides the value of an in-package form.

The display mode line is used to display status information about buffers (and it appears, usually in a contrasting color, at the bottom of the buffer). In particular, the package and readtable (if any) are displayed in the display mode line.

If a file contains neither a file mode line nor an in-package form, the following supplies the package:

fi:default-package
fi:package
fi:readtable

4.3 Syntactic modification of Common Lisp source code

Users of Emacs Lisp mode in standard Emacs will be familiar with the many ways to manipulate Lisp expressions. We mention three additional functions available in fi:common-lisp-mode. A full description of these functions and the keybindings defined for the functions is provided later.

fi:extract-list

Take the list on which the point resides and move it up one level. That is, delete the enclosing expression. With an optional integer prefix argument n, take the list on which the point resides and move it up n times.

fi:comment-region

Comment the region between the point and the mark. With a non-nil prefix argument, uncomment the region.

fi:super-paren

Close the current top-level form by inserting as many parentheses as are necessary.


4.4 Information sharing between Common Lisp and Emacs

Please note that bindings in this mode are changed by a patch made available in August, 2003. See Changes in the interface in Release 6.2 for details. The tables in this section have not yet been updated and describe the pre-patch behavior. In the lists below, we mark the changed bindings (indicating whether the change occurs with fi:legacy-keybindings set to its initial value t (the fewest changes) or set to nil (the most changes).

The commands that were discussed that query the Common Lisp environment, in Key bindings in Common Lisp subprocess mode, also apply to Common Lisp editing mode, with several additional commands:

key binding description
C-c C-b fi:lisp-eval-or-compile-current-buffer evaluate or compile the entire current buffer
C-c C-r fi:lisp-eval-or-compile-region evaluate or compile the region bounded by the point and mark
C-c C-s fi:lisp-eval-or-compile-last-sexp evaluate or compile the last S-expression
C-c C-x fi:lisp-eval-or-compile-defun evaluate or compile the entire current top-level form
ESC C-x fi:lisp-eval-or-compile-defun

if fi:legacy-keybindings is t, no binding otherwise

If fi:lisp-evals-always-compile is non-nil, then the above group of functions compile without a prefix argument and evaluate the source without compilation when a prefix argument is provided.

key binding description
C-c C-m fi:lisp-macroexpand Cause the form at the point to be macroexpanded.
C-c M fi:lisp-macroexpand if fi:legacy-keybindings is t, no binding otherwise
C-c m fi:lisp-macroexpand if fi:legacy-keybindings is t, no binding otherwise
ESC M fi:lisp-macroexpand if fi:legacy-keybindings is t, no binding otherwise
C-c ( fi:lisp-macroexpand-recursively Cause the form at the point to be recursively macroexpanded. If given a prefix argument, the recursive macroexpansion is done as the compiler would. The compiler simulation is approximate only and does not preserve the precise semantics of the form.
C-c W fi:lisp-macroexpand-recursively if fi:legacy-keybindings is t, no binding otherwise
C-c w fi:lisp-macroexpand-recursively if fi:legacy-keybindings is t, no binding otherwise
ESC W fi:lisp-macroexpand-recursively if fi:legacy-keybindings is t, no binding otherwise

The following table contains the remainder of the Lisp querying functions.

key(s) binding description
C-c C-a
C-c A
C-c a
ESC A
fi:lisp-arglist Show the argument Lisp for the symbol at the point. See fi:arglist-on-space and fi:auto-arglist-pop-up-style.
C-c i fi:insert-arglist insert the argument list template into a function call.
C-c ? fi:lisp-apropos Run apropos in the Lisp on a symbol read from the minibuffer and display the results.
C-c D
ESC D
C-c d
fi:describe-symbol

bound if fi:legacy-keybindings is non-nil
Run describe in the Lisp on a symbol read from the minibuffer and display the results.
C-c C-f
C-c F
C-c f
ESC F
fi:lisp-function-documentation Show the documentation for a symbol read from the minibuffer.
C-c C-z
C-c C
C-c c
ESC C
fi:lisp-who-calls Show the callers of a function, the symbol for which is read from the minibuffer.
C-c C-t fi:trace-definer Toggle tracing for the function defined by the top-level form around the cursor position. The form can be a defun, defgeneric, defmethod, define-compiler-macro, or deftype. The defmethod case is most useful, as the function spec for the particular method is extracted from the qualifiers and specializers. If tracing is already turned on, then it will be turned off. With a prefix arg, cause the debugger to be invoked via a call to break when the function is called.
C-c C-t
C-c T
C-c t
ESC T
fi:toggle-trace-definition Toggle tracing of a function, the symbol for which is read from the minibuffer. If tracing is already turned on, then it will be turned off.
C-c TAB
ESC TAB
fi:lisp-complete-symbol Dynamically comple the symbol at the point using information in the Lisp environment. This means that you may define a function or variable in Common Lisp, go into Common Lisp source buffer, and complete the name. Each time completion is done it looks up the possible completions, dynamically, and does not use a static table.

Abbreviations are also expanded. For example, in the initial `user' package, which inherits symbols from the `common-lisp' package, `m-p-d-` will expand to `most-positive-double-float`. The hyphen (`-`) is a separator that causes the sub-string before the hyphen to be matched at the beginning of words in target symbols.

C-c C-y
C-c k
fi:kill-definition Insert a form to kill, or un-define, the definition that starts at the point. The un-defining form is inserted after the form to un-define. With prefix argument then actually un-define the form in the Common Lisp environment instead of inserted the un-defining form.
C-c .
fi:lisp-find-definition Find the definition of the symbol at the point using information in the Lisp environment. With prefix argument, find the next occurance of the last definition. The current or other window is used, depending on which key is used.
C-c 4 . fi:lisp-find-definition-other-window
C-c , fi:lisp-find-next-definition Continue last definition search, started by fi:lisp-find-definition.
C-c * fi:pop-definition-mark Pop back to where the find definition was last invoked.

For more information on the group of functions for finding definitions of objects defined in the Common Lisp environment, see the documents source-file-recording.html and cross-reference.html for information on this. In short, you will need to set the Common Lisp special variables *record-source-file-info* and *record-xref-info* to non-nil values before loading any files into Common Lisp.


4.5 common-lisp-mode functions and variables

fi:common-lisp-mode
fi:center-defun
fi:beginning-of-defun       
fi:next-top-level-form      
fi:previous-top-level-form      
fi:lisp-semicolon           
fi:comment-region
fi:uncomment-region 
fi:end-of-defun
fi:extract-list
fi:indent-sexp
fi:lisp-apropos
fi:lisp-arglist
fi:insert-arglist
fi:arglist-lisp-space
fi:arglist-on-space
fi:auto-arglist-pop-up-style
fi:lisp-complete-symbol
fi:describe-symbol
fi:lisp-evals-always-compile
fi:lisp-eval-current-buffer
fi:lisp-eval-or-compile-current-buffer
fi:lisp-eval-defun
fi:lisp-compile-current-buffer
fi:lisp-compile-defun
fi:lisp-eval-or-compile-defun
fi:lisp-eval-last-sexp
fi:lisp-compile-last-sexp
fi:lisp-eval-or-compile-last-sexp
fi:lisp-eval-region
fi:lisp-compile-region
fi:lisp-eval-or-compile-region
fi:lisp-find-definition
fi:lisp-find-definition-other-window
fi:lisp-find-next-definition
fi:pop-definition-mark      
fi:lisp-function-documentation
fi:lisp-indent-line
fi:lisp-macroexpand
fi:lisp-macroexpand-recursively
fi:lisp-mode-auto-indent
fi:lisp-mode-newline
fi:log-functional-change
fi:super-paren
fi:trace-definition
fi:toggle-trace-definition
fi:trace-definer

4.6 definition-mode functions and variables

fi:definition-mode
fi:inverse-definition-mode
fi:maintain-definition-stack
fi:compare-source-files
fi:list-buffer-definitions
fi:list-undefined-functions
fi:list-unused-functions
fi:definition-mode-goto-definition
fi:definition-mode-goto-next
fi:definition-mode-goto-previous
fi:definition-mode-quit
fi:definition-mode-undo
fi:definition-mode-toggle-trace
fi:inverse-definition-mode-quit
fi:inverse-definition-who-calls

5.0 Writing and Debugging Common Lisp Programs

The Emacs-Lisp interface is a rich programming environment for the construction and debugging of Common Lisp programs. The debugging aids are classified into several categories. In Emacs:

In addition to the interface from Emacs to debugging programs, Allegro CL provides a rich set of tools to debug programs (see debugging.html). Functions in Allegro CL which are implemented with the help of the Emacs-Lisp interface are the top-level command :edit and the function common-lisp:ed - both allow the source code for a particular function to be edited. The editing operation is initiated from Emacs, but the action is performed by Allegro CL. :edit edits the function associated with the current stack frame and common-lisp:ed allow the editing of arbitrary functions or functions associated with symbols or function specs. For example, a call to lisp:ed returns a value immediately

    USER(1): (ed 'frob)

    <mp:process Metdot Session 0 @ #x90e7a6>
    USER(2): 

but causes a buffer to be created and made visible in Emacs displaying the definition of frob.

See:

fi:auto-fill
fi:check-unbalanced-parentheses-when-saving
fi:common-lisp-file-types
fi:compile-file
fi:echo-evals-from-buffer-in-listener-p
fi:fill-paragraph 
fi:find-tag-lock
fi:find-unbalanced-parenthesis
fi:indent-code-rigidly
fi:indent-methods-case-sensitive
fi:lisp-package
fi:kill-definition
fi:lisp-do-indentation
fi:lisp-electric-semicolon
fi:load-file
fi:parse-mode-line-and-package
fi:pop-to-sublisp-buffer-after-lisp-eval

5.1 Finding the definitions of functions

An important programming aid is being able to easily locate the source for functions. Sometimes the name of a function is not entirely known, so substrings or regular expressions need to be used to locate possible definitions.

Additionally, Emacs provides a tags facility, which does precisely what is described above, except it uses a static database created by the program etags. This is, obviously, of limited value since as the database becomes out of date the ability to find definitions diminishes.

The approach taken in this interface is to use the information present in the Common Lisp environment, and, if that lookup fails, to use the Emacs tags mechanism.

The information that is saved in the Common Lisp environment when files are loaded into Common Lisp uses the Source-file recording facility of Allegro CL, which is described in source-file-recording.html. Source-file information will be recorded and loaded if the values of the Common Lisp variables *record-source-file-info* and *load-source-file-info* are non-nil.

Retrieving information from the Common Lisp environment

During the course of debugging or programming, it is useful to have access to the wealth of information present in the Common Lisp environment. The arglist of a function, for example, is useful when composing a call to a particular function, but only if it is inexpensive to look it up.

The following functions are specifically available in Common Lisp editing mode because they are bound to a key sequence:

        key             action
        ---             -------
        C-c ?           LISP:APROPOS on a string or regular expression
        C-c a           print the arglist of a function 
        C-c c           list the who calls a function
        C-c d           LISP:DESCRIBE a symbol
        C-c f           print the function documentation of a symbol
        C-c m           macroexpand the form at the point
        C-c w           recursively macroexpand the form at the point
        C-c TAB         present completions of a partially named symbol
        C-c .           find the source for a function
        C-c 4 .         find the source for a function, in the other window
        C-c ,           find the next definition, when there is more than one
        C-c *           pop back to the window context of the previous match
        Table of Bindings for Retrieving information from the Common
                  Lisp environment

in addition to the above functions bound to key sequences, the following functions are available as extended commands:

        fi:edit-who-calls
                Edit all the callers of a function.

        fi:list-who-is-called-by
        fi:edit-who-is-called-by
                List or edit all the functions that are called by a
                function.

        fi:list-generic-function-methods
        fi:edit-generic-function-methods
                List or edit all the methods of a generic function.

        fi:describe-class
        fi:describe-function
                Describe a named class or function.

        fi:list-undefined-functions
                List the functions which are called but not defined.

List means to display the names in definition mode, which allows for easily finding the source associated with a definition. See the description of fi:definition-mode Edit means to find the source associated with a definition, making the additional definitions available via C-c ,.

Many of the above commands create a buffer named CL-temp to display the information they retrieve from the Lisp environment. After viewing the contents of this buffer, you may restore the arrangement of windows, as they were before the CL-temp buffer was made visible, by invoking the function fi:lisp-delete-pop-up-window. The keybinding C-c SPC will run this function.

Emacs functions and variables for retrieving CL environment information

fi:lisp-delete-pop-up-window
fi:pop-up-temp-window-behavior
fi:list-who-calls
fi:list-who-is-called-by
fi:edit-who-calls
fi:edit-who-is-called-by
fi:list-generic-function-methods
fi:edit-generic-function-methods
fi:describe-class
fi:describe-function

5.2 Modifying the state of the Common Lisp environment

In the course of programming it is often necessary to make changes in the Common Lisp environment. Being able to do this without having to actually type commands to a Common Lisp prompt can be valuable, especially when there would be a good deal of typing involved.

The following functions are specifically available in Common Lisp editing mode because they are bound to a key sequence:

        key             action
        ---             -------
        C-c C-r         evaluate the region
        C-c C-s         evaluate the last s-expression
        C-c C-b         evaluate the entire current buffer
        ESC C-x         evaluate the current top-level form
        ESC T           toggle tracing a function, optionally break on entry

       Table of Bindings to modify the Common Lisp environment

Additionally, the above commands to evaluation will compile the expressions sent to Common Lisp if a prefix argument is given to the command.

The commands to evaluate portions of Emacs buffers are useful, but require the programmer to indicate which portions of the buffer are evaluated. Sometimes the act of making changes to source code is deeper than just fixing one or two functions. The following functions, available as extended commands (M-x) help ease the demand on remembering what changes have been made or having to recompile more than is necessary, which can be time consuming in a large system:

fi:list-buffer-changed-definitions
fi:list-changed-definitions

List the definitions that have been added, deleted or modified in the current buffer or in all buffers visiting Common Lisp source code (in mode fi:common-lisp-mode). Listing the definitions creates a buffer showing one-line descriptions of the definitions, in fi:definition-mode. Each line contains a name' and type'. The current list of types are:

key(s) binding description
C-c C-a fi:lisp-arglist Show the argument Lisp for the symbol at the point. See fi:arglist-on-space and fi:auto-arglist-pop-up-style.
C-c i fi:insert-arglist insert the argument list template into a function call.
C-c A fi:lisp-arglist

bound if fi:legacy-keybindings is non-nil
C-c a
ESC A
SPC fi:arglist-lisp-space

no binding if fi:arglist-on-space is nil.
Cause the arglist to be automatically shown for symbols as you type.
C-c ? fi:lisp-apropos Run apropos in the Lisp on a symbol read from the minibuffer and display the results.
C-c D fi:describe-symbol

bound if fi:legacy-keybindings is non-nil
Run describe in the Lisp on a symbol read from the minibuffer and display the results.
C-c d
ESC D
C-c C-f fi:lisp-function-documentation Show the documentation for a symbol read from the minibuffer.
C-c F fi:lisp-function-documentation

bound if fi:legacy-keybindings is non-nil
C-c f
ESC F
C-c C-z fi:lisp-who-calls Show the callers of a function, the symbol for which is read from the minibuffer.
C-c C fi:lisp-who-calls

bound if fi:legacy-keybindings is non-nil
C-c c
ESC C
C-c C-t fi:trace-definer

if fi:legacy-keybindings is non-nil
Toggle tracing for the function defined by the top-level form around the cursor position. The form can be a defun, defgeneric, defmethod, define-compiler-macro, or deftype. The defmethod case is most useful, as the function spec for the particular method is extracted from the qualifiers and specializers. If tracing is already turned on, then it will be turned off. With a prefix arg, cause the debugger to be invoked via a call to break when the function is called.
C-c C-t fi:toggle-trace-definition

if fi:legacy-keybindings is nil
Toggle tracing of a function, the symbol for which is read from the minibuffer. If tracing is already turned on, then it will be turned off.
C-c T fi:toggle-trace-definition

bound if fi:legacy-keybindings is non-nil
C-c t
ESC T
C-c TAB

ESC TAB
fi:lisp-complete-symbol Dynamically comple the symbol at the point using information in the Lisp environment. This means that you may define a function or variable in Common Lisp, go into Common Lisp source buffer, and complete the name. Each time completion is done it looks up the possible completions, dynamically, and does not use a static table.

Abbreviations are also expanded. For example, in the initial `user' package, which inherits symbols from the `common-lisp' package, ``m-p-d-'' will expand to ``most-positive-double-float''. The hyphen (-) is a separator that causes the sub-string before the hyphen to be matched at the beginning of words in target symbols.

C-c C-y fi:kill-definition Insert a form to kill, or un-define, the definition that starts at the point. The un-defining form is inserted after the form to un-define. With prefix argument then actually un-define the form in the Common Lisp environment instead of inserted the un-defining form.
C-c k fi:kill-definition

bound if fi:legacy-keybindings is non-nil
C-c . fi:lisp-find-definition Find the definition of the symbol at the point using information in the Lisp environment. With prefix argument, find the next occurance of the last definition. The current or other window is used, depending on which key is used. No mark is set in the definition file by this command.
C-c 4 . fi:lisp-find-definition-other-window
C-c , fi:lisp-find-next-definition Continue last definition search, started by fi:lisp-find-definition.
C-c * fi:pop-definition-mark Pop back to where the find definition was last invoked.

TABLE # 12

:operator for functions, methods, generic functions and macros
:type for classes (types)
:setf-method for setf methods
:variable for constants and variables
fi:eval-buffer-changed-definitions
fi:eval-changed-definitions
fi:compile-buffer-changed-definitions
fi:compile-changed-definitions

Evaluate each of the definitions that have been added or modified in the current buffer or in all buffers visiting Common Lisp source code. C-c , finds subsequent definitions, if there is more than one. This synchronizes the definitions of the currently in-core versions of files being edited by Emacs with Common Lisp. The last two functions compile the changed definitions in the Common Lisp environment, whereas the first two load the interpreted versions of the changed definitions.

fi:copy-buffer-changed-definitions
fi:copy-changed-definitions

Copy into the kill ring the definitions that have been added or modified in the current buffer or in all buffers visiting Common Lisp source code.

All the above functions take a prefix argument, since, which defaults to the value of the variable fi:change-definitions-since-default. The value of since causes the above functions to operate on the changes:

thus allowing fine control over which types of changed definitions are used listed, evaluated, compiled or yanked.

Useful in comparing two files of similar origin is fi:compare-source-files, which lists the definitions that have been added, deleted or modified between the two file name arguments read from the minibuffer, if called interactively.

Lastly, it is sometimes useful to remove or kill definitions in the Common Lisp environment. fi:kill-definition inserts after the defining form at the point a form which, when evaluated, will kill the definition. With a prefix argument, fi:kill-definition will, instead of inserting the killing form, evaluate the kill definition form in the Common Lisp environment.

Here is the definition of fi:change-definitions-since-default:

fi:change-definitions-since-default

Functions and variables that modify the state of the Lisp environment

All of these functions act on definitions which have changed since:

The since prefix argument controls the behavior. You can specify it explicitly (by C-u since M-x [function of interest] where since is 1, 2, or 3), or accept the default, which is controlled by the variable fi:change-definitions-since-default defined above. Its initial value is last-compile-or-eval, which is equivalent to since = 1.

(fi:list-buffer-changed-definitions SINCE)

List the definitions in the current buffer which have been added,
deleted or changed.  See the documentation for the variable
fi:change-definitions-since-default for information on the behavior of
SINCE.

(fi:eval-buffer-changed-definitions SINCE)

Eval the definitions in the current buffer which have been added or
changed.  See the documentation for the variable
fi:change-definitions-since-default for information on the behavior of
SINCE.
 
(fi:eval-changed-definitions SINCE)

Eval the definitions in all buffers which have been added or
changed.  See the documentation for the variable
fi:change-definitions-since-default for information on the behavior of
SINCE.
 
(fi:compile-buffer-changed-definitions SINCE)

Compile the definitions in the current buffer which have been added or
changed.  See the documentation for the variable
fi:change-definitions-since-default for information on the behavior of
SINCE.
 
(fi:compile-changed-definitions SINCE)

Compile the definitions in all buffers which have been added or
changed.  See the documentation for the variable
fi:change-definitions-since-default for information on the behavior of
SINCE.
 
(fi:copy-buffer-changed-definitions SINCE)

Copy into the kill ring the definitions in the current buffer which have
been added or changed.  See the documentation for the variable
fi:change-definitions-since-default for information on the behavior of
SINCE.
 
(fi:copy-changed-definitions SINCE)

Copy into the kill ring the definitions in all buffers which have been
added or changed.  See the documentation for the variable
fi:change-definitions-since-default for information on the behavior of
SINCE. 

5.3 Debugging Common Lisp processes in Emacs

Without a window debugger, which presents a graphical view of the runtime stack, programmers debugging Common Lisp programs must resort to examining the stack with the debugger commands described in debugging.html. It is often the case, however, that much moving up and down the stack must be done to find the proper point of error. Scan stack mode allows a snapshot of the Common Lisp runtime stack to be taken, and for navigation through the stack to proceed in a Emacs buffer with a host of local commands to make this a painless experience.

Consider the following example, typed in the common-lisp buffer created by fi:common-lisp:

user(1): (defun foo (x) (bar x))
foo
user(2): (defun bar (x) (1+ x))
bar
user(3): (foo `foo)
Error: foo is an illegal argument to + 
[1] user(4): 

At this point, the problem can be debugged using :zoom, the offended function identified and fixed. A :zoom would look like:

[1] user(4): :zoom
    Evaluation stack:

    ->(error "~s is an illegal argument to +" foo)
      (excl::+_2op foo 1)
      (1+ foo)
      (bar foo)
      (foo foo)
    ... more older frames ...
    [1] user(5):

It is now desirable to move the current frame pointer down the stack to find the problem. The inconvenience here is that much output is generated moving around in the stack to find the frame which contains the useful information.

Scan stack mode makes the perusal of the stack much easier. At the point of error, if C-c s is typed, then the following question is asked, in the minibuffer:

    Process to debug: Initial Lisp Listener

where the Initial Lisp Listener is the default input to the query. Unless a multiprocessing application is being run, then most errors occur in the initial process created when Common Lisp is run, which is called the Initial Lisp Listener. Typing RET to this query will cause a debugger buffer to be created and displayed. The buffer will be named *debugger:XXX where XXX is the pretty form of the process name of the Allegro Common Lisp process which is being debugged. For the example above, it will have the following contents:

Debugger commands:

C-cC-c :continue
C-cC-p :pop
C-cC-r :reset
.      make frame under the point the current frame
D      disassemble the function
R      restart function (give prefix to specify different form)
a      toggle visibility of all frames (by default a subset are visible)
d      next line
e      edit source corresponding to function
g      revert stack from Lisp
h      Causes this help text to become visible
l      display the lexical variables
p      pretty print
q      switch back to "*common-lisp*" buffer
r      return a value
u      previous line

Type SPACE to hide this help summary.

Evaluation stack:

 ->(error "~s is an illegal argument to +" foo)
   (excl::+_2op foo 1)
   (1+ foo)
   (bar foo)
   (foo foo)
   (eval (foo 'foo))
   (apply #<Function top-level-read-eval-print-loop @ #x4854ce> nil)
   (excl::start-reborn-lisp)

where the first section of the buffer is help text, which can be made to disappear by typing SPC. The commands in this mode can be grouped according to functionality:

motion in the stack: d goto to the next frame, making it `current' u goto to the previous frame, making it `current' . make frame on the line with the point `current'

The `current' frame is signified by the -> indicator. All the commands below operate on the current frame, the one with the -> beside it.

exiting commands:

r: return the value that is read from the minibuffer and evaluated in the Common Lisp environment

R: restart execution, when a prefix argument is provided, restart with a new functions and arguments

C-cC-c: continue from the current error, which must be continuable, and the default restart is chosen (equivalent to ":continue 0")

C-cC-p: Abandon this error and pop out to the top level read-eval-print loop or a previous debugger loop (equivalent to ":pop")

C-cC-r: Abandon all debugger loops and reset to the top level (equivalent to ":reset")

q: quit scan stack mode

All of the "exiting" type commands leave scan stack mode and restore the window configuration to what it was when this mode was entered.

print auxiliary information: D disassemble the function associated with a frame and position the buffer with the return pc highlighted l retrieve the local, or lexical, variables associated with a frame. Local variable information is dependent on the value of the compiler switch compiler:save-local-names-switch p pprint the function and actual arguments of a frame

All the above commands display their output in a buffer named *CL-temp*.

miscellaneous: e edit the definition of the function associated with a frame h toggle the visibility of the help text, which if visible, is at the beginning of the buffer a toggle between hiding certain stack frames, which are normally not useful in debugging, and show all stack frames g revert stack the stack from the Common Lisp process from which the current stack was taken

Emacs functions for scanning the Common Lisp stack

fi:scan-stack
fi:scan-stack-mode
fi:scan-stack-mode-display-help
fi:ss-continue
fi:ss-disassemble
fi:ss-edit
fi:ss-hide-help-text
fi:ss-locals
fi:ss-next-frame
fi:ss-pop
fi:ss-pprint
fi:ss-previous-frame
fi:ss-quit
fi:ss-reset
fi:ss-restart
fi:ss-return
fi:ss-revert-stack
fi:ss-set-current
fi:ss-toggle-all
fi:ss-unhide-help-text

Debugging with gdb

gdb is a source level debugger provided by the Free Software Foundation. Its functionality is broadly similar to adb and dbx. You can call gdb on a Lisp image with the following command.

fi:gdb

5.4 Lisp Listeners and multiprocessing

During the course of debugging multi-process applications, it is often useful to be able to type to an additional listener in the same Common Lisp. That is, within one UNIX Common Lisp process it is possible to run multiple threads, each executing different processes in the Common Lisp address space. The function fi:open-lisp-listener will open a Lisp listener on an existing Common Lisp process started with fi:common-lisp.

The following Allegro CL debugging commands are also useful in debugging multi-process applications:

The scan stack mode above is also useful for multi-process applications, however a process must be quiescent for fi:scan-stack-mode to be used on it. quiescent means the process must have called error or break and be in a read-eval-print loop waiting for debugging commands. The above process related top-level commands, however, can be used to stop running processes for examination.


5.5 Miscellaneous programming aids

This section lists the miscellaneous programming and debugging aids which do not fit into the above sections:


5.6 Bug reports

Finally, we end our discussion on debugging by mentioning a function, fi:bug-report, which will allow Franz Inc. to be sent a bug report with all the right information:

fi:bug-report

6.0 Shell modes

The Emacs-Lisp interface defines many useful functions to interact with various types of shells. Below is a description of the functions and variables associated with various shell modes.

The main differences between the standard Emacs shell mode and the Franz Emacs-Lisp interface are described below:

shell mode

fi:shell
fi:shell-command-completion
fi:shell-do-completion
fi:shell-file-name-completion
fi:shell-image-arguments
fi:shell-image-name
fi:shell-mode
fi:shell-mode-bang
fi:shell-mode-use-history
fi:shell-prompt-pattern
fi:shell-sync-current-working-directory
fi:shell-token-pattern

su mode

fi:su
fi:su-initial-input
fi:su-mode
fi:su-prompt-pattern
fi:remote-root-login
fi:remote-su-mode

telnet mode

fi:telnet
fi:telnet-mode
fi:telnet-image-arguments
fi:telnet-image-name
fi:telnet-initial-input
fi:telnet-prompt-pattern
fi:telnet-start-garbage-filter

rlogin mode

fi:rlogin
fi:rlogin-new-user
fi:rlogin-mode
fi:rlogin-image-arguments
fi:rlogin-image-name
fi:rlogin-initial-input
fi:rlogin-prompt-pattern
fi:rlogin-send-eof
fi:rlogin-send-interrupt
fi:rlogin-send-quit
fi:rlogin-send-stop

7.0 Advanced miscellaneous features

This section and its subsections discuss advanced features of the Emacs-Lisp interface.

fi:define-emacs-lisp-mode
fi:emacs-lisp-mode

7.1 Emacs hooks

Some functions in Emacs will call one or more hook functions. A hook is a user settable variable whose value is a hook function. Hooks allow the user to customize features of emacs. Hooks are usually set in the .emacs file, but may be changed by other emacs functions. Many of the mode functions in the Emacs-Lisp Interface run one or more hooks. The hooks and the order they are called are listed in the table below. Note that the documentation for each mode function also lists the hook called (if any). For more information about hooks, please see the FSF Emacs and Emacs Lisp documentation.

Function Called                 Hooks run (in order)
fi:inferior-common-lisp-mode    fi:lisp-mode-hook 
                                fi:subprocess-mode-hook 
                                fi:inferior-common-lisp-mode-hook
fi:lisp-listener-mode           fi:lisp-mode-hook 
                                fi:subprocess-mode-hook
                                fi:lisp-listener-mode-hook
fi:common-lisp-mode             fi:lisp-mode-hook 
                                fi:common-lisp-mode-hook
fi:definition-mode              fi:definition-mode-hook
fi:inverse-definition-mode      fi:inverse-definition-mode-hook
fi:scan-stack-mode              fi:scan-stack-mode-hook
fi:shell-mode                   fi:subprocess-mode-hook 
                                fi:shell-mode-hook
fi:su-mode                      fi:subprocess-mode-hook 
                                fi:su-mode-hook
fi:remote-su-mode               fi:subprocess-mode-hook 
                                fi:rlogin-mode-hook
fi:telnet-mode                  fi:subprocess-mode-hook
                                fi:telnet-mode-hook
fi:rlogin-mode                  fi:subprocess-mode-hook 
                                fi:rlogin-mode-hook

Hooks are commonly used to customize the key-map of a particular mode. The Emacs code fragment below would cause the C-i keystroke to invoke the function fi:shell-do-completion. Note that C-i is also the TAB key.

(setq fi:subprocess-mode-hook
   '(lambda ()
      (interactive)
      (define-key (current-local-map) "\C-i" 
        'fi:shell-do-completion)))

7.2 The Emacs-Lisp interface and excl:dumplisp

Just about everything we have said so far in this document about the Emacs-Lisp interface has assumed that the Lisp image was created with build-lisp-image in a relatively standard fashion.

Problems starting the Emacs-Lisp interface can arise, however, when starting images created with dumplisp called with a non-nil value specified for the :ignore-command-line-arguments keyword argument.

This will cause problems because of how the Emacs-Lisp interface is started, as we describe next.

How Emacs and Lisp rendezvous

As we said in section 3 (and elsewhere), the Emacs-Lisp interface is started by invoking within Emacs the function fi:common-lisp. That function either asks you for command line arguments for Lisp or (typically after the first invocation within an Emacs session) simply takes the value of the Emacs Lisp variable fi:start-lisp-interface-arguments. Here is what happens then:

Because information is passed between Lisp and Emacs in this special way, the connection between Emacs and Lisp can only be established by running Common Lisp with fi:common-lisp. Prior to starting the connection between Lisp and Emacs, Emacs can only communicate to Lisp via the command line. Therefore, the Lisp side of the connection is started using the command line. The problem with images that ignore command-line arguments should be apparent.

Starting the interface directly with excl:new-start-emacs-lisp-interface

If, because command-line arguments are ignored, the Emacs-Lisp interface does not start up (or if it does not start up for any other reason), you can start it directly from within Lisp by calling excl:new-start-emacs-lisp-interface. We remind you again that the image must have been started with fi:common-lisp for this to work.


Copyright (c) Franz Inc. Lafayette, CA., USA. All rights reserved.

ToC DocOverview CGDoc RelNotes FAQ Index PermutedIndex
Allegro CL version 11.0