The Emacs-Lisp Interface

ELI Version 2.0.21.16.15

$Revision: 1.1.2.6 $


Table of Contents

1. Introduction to the Emacs-Lisp interface

2. Starting the Emacs-Lisp interface

2.1. Troubleshooting the Emacs-Lisp interface

3. Running Common Lisp

3.1. Key bindings in Common Lisp subprocess mode
3.2. Typing input to Common Lisp
3.3. Functions and variables for Interacting with a CL subprocess

4. Editing Common Lisp Programs

4.1. Indentation
4.2. Packages and readtables
4.3. Syntactic modification of Common Lisp source code
4.4. Information sharing between Common Lisp and Emacs
4.5. common-lisp-mode functions and variables
4.6. definition-mode functions and variables

5. Writing and Debugging Common Lisp Programs

5.1. Finding the definitions of functions
5.2. Interaction with Allegro Composer
5.3. Modifying the state of the Common Lisp environment
5.4. Debugging Common Lisp processing in Emacs
5.5. Lisp Listeners
5.6. Miscellaneous programming aids
5.7. Bug reports

6. Shell modes

7. Advanced miscellaneous features

7.1. Emacs hooks
7.2. The Emacs-Lisp interface and excl:dumplisp
7.3. Raw mode


1. 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.

Unless otherwise specified, when we say Emacs in this document, we mean Xemacs or GNU Emacs. Versions of Xemacs and GNU Emacs are distributed with Allegro CL.

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 UNIX 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. We expect that it will be documented in the future, after we have had more experience with the fundamentally new design.

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. The topics are:

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. Their address is:

    Free Software Foundation, Inc.
    675 Massachusetts Avenue
    Cambridge, MA 02139, USA
    +1 617-876-3296

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. All of the documentation available in the Info program may be printed on hardcopy, see the Texinfo section of Info. Note that printing the Emacs manual is easiest if you have TeX.

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.

$HOME

This refers to the value of the $HOME shell environment variable in the shell where Emacs is running. The value of this variable is typically the home directory of the user running Emacs.

$HOME/.emacs

This file is an initialization file which is read by Emacs when it starts up. Forms in this file customize Emacs to the user's specifications. The Emacs-Lisp interface described in this document is typically loaded by forms put in this file.

fi/xxx

Files in the fi directory implement the Emacs-Lisp interface. This directory must be accessible while Emacs is running. When the interface is installed, the fi directory is placed in a directory associated with Emacs. To find the exact path of this directory, within Emacs evaluate the variable load-path (the value will be one or more directories). If installed correctly, the fi directory will be a subdirectory of the first directory which ends in .../lisp/. If the fi directory is not a subdirectory of the first .../lisp/ directory then certain features, such as the on-line manual may not work. This pathname can be used to find the file xxx in the .../lisp/fi directory.

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 Sun keyboards, for example, the LEFT key is used for the META key. Note also that in most cases, pressing LEFT 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 (as you have noticed) 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.

ESC

This symbol stands for the ESCAPE key. It can be used alone or in conjunction with another key. If used in conjunction with another key, the ESCAPE is pressed first and the other key immediately after. ESC-v, therefore, means press ESCAPE and then press v (without pressing SHIFT, note!). Some keyboards do not have a META key. You may type META characters by using two character keystrokes starting with ESCAPE.

M-

This symbol stands for the META key (usually called something else, e.g. LEFT on Sun keyboards). The META key only has an effect when pressed simultaneously with another key (hence the - following the M). M-a means depress META and press a while META is down. M-Sh-a means depress META and SHIFT, then press a while META and SHIFT are down. Note that M-a and M-Sh-a are two distinct keystrokes. Note too that Emacs online documentation typically says M-A instead of M-Sh-a (that is, the case of the letter is important when M-<letter> appears in Emacs online documentation).

C-

This symbol stands for the CONTROL key. The CONTROL key only has an effect when pressed simultaneously with another key (hence the - following the C). C-a means depress CONTROL and press a while CONTROL is down.

RET

This symbol stands for the RETURN key, also called a carriage return. This key is not ever pressed in conjunction with another. Note that most Emacs commands are effected without a RETURN being necessary.

LF

This symbol stands for the LINE FEED key. This key is not ever pressed in conjunction with another. Note that this key is different from (and has a different effect than) the RETURN key.

DEL

This symbol stands for the DELETE key. This key is not ever pressed in conjunction with another. This key, rather than BACKSPACE deletes the character before the cursor. BACKSPACE (C-h) is the initial default help key and has no effect on typed-in text.

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

Previous versions of Emacs

The Emacs-Lisp interface has been tested and does work with the following versions of Emacs. No changes to these versions is required. Note that in each case, we list the range of versions with which the interface is known to work. The interface will not work and is not supported with earlier versions. In each case, the interface was tested with the latest version available. 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 with after this manual was printed. If that occurs, please contact us for assistance.

Emacs Type Range of Supported Versions
GNU Emacs 19.34, 20.2
Xemacs 19.16, 20.3 (with and without Mule support)

Table 1: Supported versions of Emacs

GNU Emacs 20.2 is supported with the following caveat: eli works, but a bug in the handling of `load-file-name' prevents loading the interface the normal way, by just loading "fi-site-init.el". You must put the directory which contains fi-site-init.el in your `load-path'. See examples/emacs.el for an example of how to do this. The bug should be fixed in GNU Emacs 20.3, when it comes out.

XEmacs users only:

You must recompile the .el files because of incompatibilities between GNU Emacs and XEmacs.  You can do this by:

% cd <Allegro directory>/eli
% make clean
% make emacs=xemacs xemacs=xemacs

You will need GNU Make to execute the above command, and you should substitute the real name of your XEmacs for xemacs.

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).

Previous versions of the Emacs-Lisp interface

Previous versions of the Emacs-Lisp interface have been distributed with Allegro CL and also via anonymous FTP. The version at the time this document was written was 2.0.21 and this document describes this version only. Versions before 2.0 contain substantially less functionality.

Versions of this interface prior to 2.0 worked (for the most part, at least) on a variety of implementations of Common Lisp. This latest version is much more specific to Allegro CL and uses internal features of Allegro CL which are not available in other Lisp implementations. Therefore, many features in version 2.0 and later of the Emacs-Lisp interface will not work on implementations other than Allegro Common Lisp. The Emacs variable fi:emacs-lisp-interface-version contains the version information.

What should be in your .emacs file

The code for the Emacs-Lisp interface needs to be loaded into Emacs when Emacs starts up. 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). The exact forms depend on where Allegro CL was installed on your system (since starting with Allegro CL 4.3, the Emacs-Lisp interface code is not merged into the standard Emacs library). Assuming that Allegro CL was installed into /usr/acl50. Here is the correct form to place in .emacs:

(load "/usr/acl50/eli/fi-site-init")

Note: replace /usr/acl50 with the correct directory if that is not where Allegro CL was installed. (/usr/acl50 is the suggested directory in the Installation Guide but any directory may have been used. Your system administrator -- or whoever installed Allegro CL -- should be able to provide this information.)

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.

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. However, the text of the on-line Common Lisp Manual pages are Copyright (C) Franz Inc.

This Copyright message applies to the clman pages:

All files are Copyright (C) 1988-1998 by Franz Inc. Users may copy these files to computers for their own use. These files may not be distributed in printed form without the express prior written approval of Franz Inc. These files may not be included as part of any other software package without the express prior written approval of Franz Inc. All other rights reserved.

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 copyright notice above.

Quirks of the Emacs-Lisp Interface

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

Evaluate the following expression while in a Common Lisp buffer:

M-x eval-expression RET fi:package

The string returned should make sense as a package. A legitimate sample return value is "mypackage".

Recent changes to the Emacs-Lisp Interface

Changes from version 2.0.21.16 (shipped with Allegro CL 4.3.2 on Windows 95/NT) to 2.0.21.16.15:

Changes from version 2.0.20 (shipped with Allegro CL 4.3.2 on Windows 95/NT) to 2.0.21.16:

Changes from version 2.0.19 (shipped with Allegro CL 4.3 and 4.3.1) to 2.0.20 (shipped with Allegro CL 4.3.2), all to support using eli on Windows:

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.


2. 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 Section 3 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). The exact forms depend on where Allegro CL was installed on your system (since starting with Allegro CL 4.3, the Emacs-Lisp interface code is not merged into the standard Emacs library). Assuming that Allegro CL was installed into /usr/acl50. Here is the correct form to place in .emacs:

(load "/usr/acl50/eli/fi-site-init")

Note: replace /usr/acl50 with the correct directory if that is not where Allegro CL was installed. (/usr/acl50 is the suggested directory in the Installation Guide but any directory may have been used. Your system administrator -- or whoever installed Allegro CL -- should be able to provide this information.

These forms cause the interface to 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 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.

M-x load-file RET /usr/acl50/eli/fi-site-init

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 home/misc/dot-emacs. The home/ directory is read off the distribution tape (and it typically the Lisp library directory). Make use of this code if you wish by placing it in your .emacs file in your home directory (home/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.

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). 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.

Emacs reports that it cannot find a file to load

The files needed by the Emacs-Lisp interface reside in the fi subdirectory of one of the Emacs Lisp library directories. If you evaluate the Emacs variable load-path, a list of directories will be printed. The fi directory should be a subdirectory of the first directory in the list whose last element is /lisp/. Check to see if that directory does have an fi subdirectory. If it does not, the Emacs-Lisp interface was not installed correctly. See the Installation Guide for information on how to install the interface. If the fi subdirectory is there, perhaps it is not accessible on the machine where Emacs is running (usually because of a problem with NFS).

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) 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/...).

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 /usr/acl50/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.

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. 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. You cannot start Common Lisp in an Emacs shell and then initiate the interface. Most of the Emacs-Lisp interface will not work with a Lisp image started in an Emacs shell.

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 3.3 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 5.0 [SPARC; R1] (7/15/98 00:00)
Copyright (C) 1985-1998, Franz Inc., Berkeley, 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 `5.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.htm 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 an 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 section 3.3 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 is dies) with the Allegro CL function excl:start-emacs-lisp-interface.


3.1. Key bindings in Common Lisp subprocess mode

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
RET fi:inferior-lisp-newline
C-c C-\ fi:subprocess-quit
C-c C-d fi:subprocess-send-eof
(fi:remote-lisp-send-eof when Lisp is remote)
C-c C-c fi:subprocess-interrupt
C-c = fi:lisp-sync-current-working-directory
C-c C-w fi:subprocess-backward-kill-word
C-c C-v fi:subprocess-show-output
C-c C-u fi:subprocess-kill-input
C-c C-o fi:subprocess-send-flush
C-c RET fi:subprocess-input-region
C-c C-k fi:subprocess-kill-output
C-c C-a fi:subprocess-beginning-of-line

Table 2: 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
DEL backward-delete-char-untabify
TAB fi:lisp-indent-line
C-c ] fi:super-paren
C-c C-e fi:end-of-defun
C-c ; fi:comment-region
C-c ^ fi:center-defun
C-c % fi:extract-list
C-c C-y fi:pop-input
C-c C-s fi:re-search-forward-input
C-c C-r fi:re-search-backward-input
C-c C-p fi:pop-input
C-c C-n fi:push-input
C-c C-l fi:list-input-ring
C-x RET fi:inferior-lisp-input-list
ESC C-q fi:indent-sexp
ESC RET fi:inferior-lisp-input-sexp

Table 3: 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 ? fi:lisp-apropos
C-c s fi:scan-stack
C-c . fi:lisp-find-definition
C-c 4 . fi:lisp-find-definition-other-window
C-c , fi:lisp-find-next-definition
C-c SPC fi:lisp-delete-pop-up-window
C-c w fi:lisp-macroexpand-recursively
C-c t fi:toggle-trace-definition
C-c m fi:lisp-macroexpand
C-c f fi:lisp-function-documentation
C-c d fi:describe-symbol
C-c c fi:list-who-calls
C-c a fi:lisp-arglist
C-c TAB fi:lisp-complete-symbol

Table 4: 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 section 5.1 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-w delete the last word (from "stty werase")
C-u delete the current input (from "stty kill")
C-o flush output (from "stty flush")
C-d send EOF to Common Lisp
C-a goto the beginning of the line, ignore the Common Lisp prompt

Table 5: Superkeys

C-v, 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 top-level:*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 top-level:*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.htm for information on the prompt itself.

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.

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.

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.

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 4.2 Packages and readtables for more information.

Lisp Listeners

Because Allegro CL has multiprocessing (see multiprocessing.htm 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.


3.3. Functions and variables for Interacting with a CL subprocess

fi:common-lisp [Emacs command]
Arguments: &optional buffer-name directory executable-image-name image-args host image-file


Below is an example .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.  (This is eli/examples/emacs.el.)

    ;; A sample ~/.emacs file.
    ;;
    ;; $Id: emacs.el,v 1.6.20.1 1998/07/16 16:47:45 layer Exp $
    
    (defvar *eli-directory*)
    (setq *eli-directory* (expand-file-name "~/cl-ultra/src/eli/"))
    
    (when (and (not (string-match "xemacs" emacs-version))
    	   (= emacs-major-version 20)
    	   (>= emacs-minor-version 2))
      (setq load-path (cons *eli-directory* load-path)))
    
    (load (format "%sfi-site-init" *eli-directory*))
    
    (setq fi:common-lisp-image-name "/usr/local/cl-5.0")
    (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))
    
    ;; Set up a keybinding for `run-common-lisp', two possible ways:
    (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:open-lisp-listener [Emacs command]
Arguments: &optional buffer-number buffer-name setup-function
fi:toggle-to-lisp [Emacs command]
Arguments: nil
fi:define-global-lisp-mode-bindings [Emacs variable]
Initial value: t
fi:common-lisp-buffer-name [Emacs variable]
Initial value: "*common-lisp*"
fi:common-lisp-directory [Emacs variable]
Initial value: nil
fi:common-lisp-image-name [Emacs variable]
Initial value: "lisp"
fi:common-lisp-image-file [Emacs variable]
Initial value: nil
fi:common-lisp-image-arguments [Emacs variable]
Initial value: nil
fi:common-lisp-host [Emacs variable]
Initial value: "localhost"
fi:common-lisp-prompt-pattern [Emacs variable]
Initial value: "^\\(\\[[0-9]+i?c?\\] \\|\\[step\\] \\)?\\(>[-A-Za-z]* ?[0-9]*?>\\|[-A-Za-z0-9]+([0-9]+):\\) "
fi:common-lisp-subprocess-timeout [Emacs variable]
Initial value: 30
fi:common-lisp-subprocess-wait-forever [Emacs variable]
Initial value: nil
fi:connect-to-windows [Emacs variable]
Initial value: (windows-nt ms-windows ms-dos win386)
fi:start-lisp-interface-arguments [Emacs variable]
Initial value: (lambda (use-background-streams &optional lisp-image-name) (let ((args (list "-e" (format "(excl:start-emacs-lisp-interface %s)" use-background-streams)))) (when lisp-image-name (when (string-match "^~" lisp-image-name) (setq lisp-image-name (expand-file-name lisp-image-name))) (setq args (append (list "-I" lisp-image-name) args))) args))
fi:use-background-streams [Emacs variable]
Initial value: t
fi:start-lisp-interface-hook [Emacs variable]
Initial value: (fi::auto-ensure-lep-connection fi:show-run-status)
fi:reset-lep-connection [Emacs command]
Arguments: nil
fi:in-package-regexp [Emacs variable]
Initial value: nil
fi:default-in-package-regexp [Emacs variable]
Initial value: "(in-package\\>\\|:pa\\>\\|:pac\\>\\|:pack\\>\\|:packa\\>\\|:packag\\>\\|:package\\>"

fi:inferior-common-lisp-mode [Emacs command]
Arguments: &optional mode-hook &rest mode-hook-args
fi:inferior-lisp-input-list [Emacs command]
Arguments: &optional arg
fi:inferior-lisp-input-sexp [Emacs command]
Arguments: &optional arg
fi:inferior-lisp-newline [Emacs command]
Arguments: nil
fi:lisp-sync-current-working-directory [Emacs command]
Arguments: nil
fi:list-input-ring [Emacs command]
Arguments: arg &optional reflect
fi:pop-input [Emacs command]
Arguments: &optional arg
fi:push-input [Emacs command]
Arguments: &optional arg
fi:re-search-backward-input [Emacs command]
Arguments: arg regexp
fi:re-search-forward-input [Emacs command]
Arguments: arg regexp
fi:remote-lisp-send-eof [Emacs command]
Arguments: nil
fi:subprocess-backward-kill-word [Emacs command]
Arguments: arg
fi:subprocess-beginning-of-line [Emacs command]
Arguments: arg
fi:subprocess-input-region [Emacs command]
Arguments: start end
fi:subprocess-interrupt [Emacs command]
Arguments: nil
fi:subprocess-kill [Emacs command]
Arguments: nil
fi:subprocess-kill-input [Emacs command]
Arguments: nil
fi:subprocess-kill-output [Emacs command]
Arguments: nil
fi:subprocess-quit [Emacs command]
Arguments: nil
fi:subprocess-send-eof [Emacs command]
Arguments: nil
fi:subprocess-send-flush [Emacs command]
Arguments: nil
fi:subprocess-show-output [Emacs command]
Arguments: nil
fi:subprocess-suspend [Emacs command]
Arguments: nil

fi:lisp-listener-mode [Emacs command]
Arguments: &optional mode-hook
fi:interrupt-listener [Emacs command]
Arguments: select
fi:tcp-lisp-listener-kill-process [Emacs command]
Arguments: nil
fi:tcp-lisp-listener-send-eof [Emacs command]
Arguments: nil

fi:emacs-to-lisp-transaction-directory [Emacs variable]
Initial value: "c:/tmp"
fi:default-input-ring-max [Emacs variable]
Initial value: 50
fi:display-buffer-function [Emacs variable]
Initial value: fi::switch-to-buffer-new-screen
fi:new-screen-for-common-lisp-buffer [Emacs variable]
Initial value: nil
fi:eval-in-lisp [Emacs function]
Arguments: string &rest args
fi:eval-in-lisp-asynchronous [Emacs function]
Arguments: string &rest args
fi:filename-frobber-hook [Emacs variable]
Initial value: fi::discombobulate-automounter-lint
fi:lisp-evalserver-number-reads [Emacs variable]
Initial value: 200
fi:shell-cd-regexp [Emacs variable]
Initial value: ":?cd"
fi:shell-popd-regexp [Emacs variable]
Initial value: ":?popd"
fi:shell-pushd-regexp [Emacs variable]
Initial value: ":?pushd"
fi:subprocess-continuously-show-output-in-visible-buffer [Emacs variable]
Initial value: t
fi:subprocess-enable-superkeys [Emacs variable]
Initial value: nil
fi:subprocess-env-vars [Emacs variable]
Initial value: (("EMACS" . "t") ("TERM" . "emacs") ("DISPLAY" or (getenv "DISPLAY") (format "%s:0.0" (system-name))) ("TERMCAP" format "emacs:co#%d:tc=unknown:" (frame-width)))
fi:superkey-shadow-universal-argument [Emacs variable]
Initial value: t



4. 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.


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. For some of the special forms and macros new to Common Lisp (due to the ANSI X3J13 committee), the indentation is not as standardized as it is for older forms. 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 [Emacs variable]
Initial value: (40 t nil 0)



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 readable.

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 illustrate 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 is 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 [Emacs variable]
Initial value: "user"
fi:package [Emacs variable]
Initial value: nil
fi:readtable [Emacs variable]
Initial value: nil



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 parenthesis as are necessary.


4.4. Information sharing between Common Lisp and Emacs

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

      key		binding
      ---		-------
      C-c C-r		fi:lisp-eval-or-compile-region
      C-c C-s		fi:lisp-eval-or-compile-last-sexp
      C-c C-b		fi:lisp-eval-or-compile-current-buffer
      ESC C-x		fi:lisp-eval-or-compile-defun
		  The above group of functions cause the
		  region, last s-expression, the entire buffer
		  or the current top-level form to be
		  evaluated in the Common Lisp environment.
		  With a prefix argument, the source is
		  compiled.
      C-c m		fi:lisp-macroexpand
      C-c w		fi:lisp-macroexpand-recursively
		  The above two functions cause the form at the point
		  to be macroexpanded, recursively so with the second
		  function.
      C-c t		fi:toggle-trace-definition
		  Toggle tracing a function in the Common Lisp
		  environment.  If it is currently being traced, then
		  tracing will be turned off, or if is not being
		  traced, then tracing will be turned on for this one
		  function.  With a prefix argument, entry to this
		  function will cause entry into the debugger (trace
		  on break).
      C-c ?		fi:lisp-apropos
      C-c f		fi:lisp-function-documentation
      C-c d		fi:describe-symbol
      C-c c		fi:list-who-calls
      C-c a		fi:lisp-arglist
		  The above group of functions read a function name
		  from the minibuffer, using the symbol at the point,
		  if there is one, as the default answer, and execute
		  `apropos', find the documentation on the function,
		  describe the function, find the callers of the
		  function, or the arglist for the function, in the
		  Common Lisp environment.  The information is printed
		  in the minibuffer if it will fix, otherwise a buffer
		  is popped up that displays the information.
      C-c TAB		fi:lisp-complete-symbol
		  Dynamically complete the symbol at the point in the
		  Common 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 substring
		  before the hyphen to be matched at the beginning of
		  words in target symbols. 
      C-c .		fi:lisp-find-definition
      C-c 4 .		fi:lisp-find-definition-other-window
      C-c ,		fi:lisp-find-next-definition
		  The above group of functions are used for finding
		  definitions of objects defined in the Common Lisp
		  environment.   See the documents
                     source_file_recording.htm
                     xref.htm
                  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 [Emacs command]
Arguments: &optional mode-hook
fi:center-defun [Emacs command]
Arguments: nil
fi:comment-region [Emacs command]
Arguments: &optional start end uncomment
fi:uncomment-region [Emacs command]
Arguments: start end
fi:end-of-defun [Emacs command]
Arguments: nil
fi:extract-list [Emacs command]
Arguments: arg
fi:indent-sexp [Emacs command]
Arguments: nil
fi:lisp-apropos [Emacs command]
Arguments: string &optional regexp
fi:lisp-arglist [Emacs command]
Arguments: string
fi:lisp-complete-symbol [Emacs command]
Arguments: nil
fi:describe-symbol [Emacs command]
Arguments: fspec