The Emacs-Lisp Interface

The index for the Allegro CL Documentation is in index.htm. The documentation is described in introduction.htm.

This document contains the following sections:

1.0 Introduction to the Emacs-Lisp interface
   1.1 If you are new to Emacs
   1.2 Notation conventions used in this document
   1.3 Format of this document
   1.4 Previous versions of Emacs
   1.5 Previous versions of the Emacs-Lisp interface
   1.6 What should be in your .emacs file
   1.7 Emacs Documentation
   1.8 Licensing issues and The Free Software Foundation
   1.9 Quirks of the Emacs-Lisp Interface
   1.10 Bug reports and fixes
2.0 Starting the Emacs-Lisp interface
   2.1 Troubleshooting the Emacs-Lisp interface
      2.1.1 Emacs reports that a function defined in the interface is undefined
      2.1.2 Emacs reports that it cannot find a file to load
      2.1.3 Emacs reports that it encountered an error when loading .emacs
      2.1.4 Checking your setup
      2.1.5 Other strange or unexplained behavior
3.0 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.0 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.0 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.0 Shell modes
7.0 Advanced miscellaneous features
   7.1 Emacs hooks
   7.2 The Emacs-Lisp interface and excl:dumplisp
   7.3 Raw mode

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.

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 ithe fi:. Similarly for variables (but C-h-v instead of C-h-f).

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.

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

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

1.3 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.4 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 TypeRange of Supported Versions
GNU Emacs19.34, 20.2
Xemacs19.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).

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

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. 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/acl60. Here is the correct form to place in .emacs:

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

Note: replace /usr/acl60 with the correct directory if that is not where Allegro CL was installed. (/usr/acl60 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.)

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 1.1 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. 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-2000 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.

1.9 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".

1.10 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.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 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/acl60. Here is the correct form to place in .emacs:

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

Note: replace /usr/acl60 with the correct directory if that is not where Allegro CL was installed. (/usr/acl60 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/acl60/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.

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

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

2.1.4 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/acl60/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 1.4 Previous versions of Emacs for more information about this command.

2.1.5 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. 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 0.0 [SPARC; R1] (7/15/00 00:00)
Copyright (C) 1985-2000, 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 `6.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 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 3.3 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 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:

keybinding
RETfi:inferior-lisp-newline
C-c C-\fi:subprocess-quit
C-c C-dfi:subprocess-send-eof
(fi:remote-lisp-send-eof when Lisp is remote)
C-c C-cfi:subprocess-interrupt
C-c =fi:lisp-sync-current-working-directory
C-c C-wfi:subprocess-backward-kill-word
C-c C-vfi:subprocess-show-output
C-c C-ufi:subprocess-kill-input
C-c C-ofi:subprocess-send-flush
C-c RETfi:subprocess-input-region
C-c C-kfi:subprocess-kill-output
C-c C-afi: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:

keybinding
DELbackward-delete-char-untabify
TABfi:lisp-indent-line
C-c ]fi:super-paren
C-c C-efi:end-of-defun
C-c ;fi:comment-region
C-c ^fi:center-defun
C-c %fi:extract-list
C-c C-yfi:pop-input
C-c C-sfi:re-search-forward-input
C-c C-rfi:re-search-backward-input
C-c C-pfi:pop-input
C-c C-nfi:push-input
C-c C-lfi:list-input-ring
C-x RETfi:inferior-lisp-input-list
ESC C-qfi:indent-sexp
ESC RETfi: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:

keybinding
C-c ?fi:lisp-apropos
C-c sfi: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 SPCfi:lisp-delete-pop-up-window
C-c wfi:lisp-macroexpand-recursively
C-c tfi:toggle-trace-definition
C-c mfi:lisp-macroexpand
C-c ffi:lisp-function-documentation
C-c dfi:describe-symbol
C-c cfi:list-who-calls
C-c afi:lisp-arglist
C-c TABfi: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 5.1 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)

keybinding
C-\send "kill -QUIT" (UNIX quit) to Common Lisp
C-wdelete the last word (from "stty werase")
C-udelete the current input (from "stty kill")
C-oflush output (from "stty flush")
C-dsend EOF to Common Lisp
C-agoto 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 *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.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

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

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: eli.htm,v 1.10.2.27 2000/10/27 20:06:07 dm 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-6.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
fi:toggle-to-lisp                    fi:common-lisp-mode-map
fi:define-global-lisp-mode-bindings
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:connect-to-windows
fi:start-lisp-interface-arguments
fi:use-background-streams
fi:start-lisp-interface-hook
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-common-lisp-mode-map
fi:inferior-lisp-input-sexp          fi:inferior-common-lisp-mode-map
fi:inferior-lisp-newline             fi:inferior-common-lisp-mode-map
fi:lisp-sync-current-working-directory fi:inferior-common-lisp-mode-map
fi:list-input-ring                   fi:inferior-common-lisp-mode-map
fi:pop-input                         fi:inferior-common-lisp-mode-map
fi:push-input                        fi:inferior-common-lisp-mode-map
fi:re-search-backward-input          fi:inferior-common-lisp-mode-map
fi:re-search-forward-input           fi:inferior-common-lisp-mode-map
fi:remote-lisp-send-eof              fi:inferior-common-lisp-mode-map
fi:subprocess-backward-kill-word     fi:inferior-common-lisp-mode-map
fi:subprocess-beginning-of-line      fi:inferior-common-lisp-mode-map
fi:subprocess-input-region           fi:inferior-common-lisp-mode-map
fi:subprocess-interrupt              fi:inferior-common-lisp-mode-map
fi:subprocess-kill                   fi:inferior-common-lisp-mode-map
fi:subprocess-kill-input             fi:inferior-common-lisp-mode-map
fi:subprocess-kill-output            fi:inferior-common-lisp-mode-map
fi:subprocess-quit                   fi:inferior-common-lisp-mode-map
fi:subprocess-send-eof               fi:inferior-common-lisp-mode-map
fi:subprocess-send-flush             fi:inferior-common-lisp-mode-map
fi:subprocess-show-output            fi:inferior-common-lisp-mode-map
fi:subprocess-suspend                fi:inferior-common-lisp-mode-map

fi:lisp-listener-mode
fi:interrupt-listener                        fi:lisp-listener-mode-map
fi:tcp-lisp-listener-kill-process            fi:lisp-listener-mode-map
fi:tcp-lisp-listener-send-eof                fi:lisp-listener-mode-map

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:subprocess-env-vars
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.

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

See 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 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 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:

See fi:default-package, fi:package, and 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 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 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
                     and cross-reference.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
fi:center-defun                      fi:common-lisp-mode-map
fi:comment-region                    fi:common-lisp-mode-map
fi:uncomment-region 
fi:end-of-defun                      fi:common-lisp-mode-map
fi:extract-list                      fi:common-lisp-mode-map
fi:indent-sexp                       fi:common-lisp-mode-map
fi:lisp-apropos                      fi:common-lisp-mode-map
fi:lisp-arglist                      fi:common-lisp-mode-map
fi:lisp-complete-symbol              fi:common-lisp-mode-map
fi:describe-symbol                   fi:common-lisp-mode-map
fi:lisp-evals-always-compile
fi:lisp-eval-current-buffer          fi:common-lisp-mode-map
fi:lisp-eval-or-compile-current-buffer fi:common-lisp-mode-map
fi:lisp-eval-defun                   fi:common-lisp-mode-map
fi:lisp-compile-current-buffer       fi:common-lisp-mode-map
fi:lisp-compile-defun                fi:common-lisp-mode-map
fi:lisp-eval-or-compile-defun        fi:common-lisp-mode-map
fi:lisp-eval-last-sexp               fi:common-lisp-mode-map
fi:lisp-compile-last-sexp            fi:common-lisp-mode-map
fi:lisp-eval-or-compile-last-sexp    fi:common-lisp-mode-map
fi:lisp-eval-region                  fi:common-lisp-mode-map
fi:lisp-compile-region               fi:common-lisp-mode-map
fi:lisp-eval-or-compile-region       fi:common-lisp-mode-map
fi:lisp-find-definition              fi:common-lisp-mode-map
fi:lisp-find-definition-other-window fi:common-lisp-mode-map
fi:lisp-find-next-definition         fi:common-lisp-mode-map
fi:lisp-function-documentation       fi:common-lisp-mode-map
fi:lisp-indent-line                  fi:common-lisp-mode-map
fi:lisp-macroexpand                  fi:common-lisp-mode-map
fi:lisp-macroexpand-recursively      fi:common-lisp-mode-map
fi:lisp-mode-auto-indent
fi:lisp-mode-newline                 fi:common-lisp-mode-map
fi:log-functional-change             fi:common-lisp-mode-map
fi:super-paren                       fi:common-lisp-mode-map
fi:trace-definition
fi:toggle-trace-definition           fi:common-lisp-mode-map

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-map
fi:definition-mode-goto-next         fi:definition-mode-map
fi:definition-mode-goto-previous     fi:definition-mode-map
fi:definition-mode-quit              fi:definition-mode-map
fi:definition-mode-undo              fi:definition-mode-map
fi:definition-mode-toggle-trace      fi:definition-mode-map
fi:inverse-definition-mode-quit      fi:inverse-definition-mode-map
fi:inverse-definition-who-calls      fi:inverse-definition-mode-map

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.htm). 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: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.htm. 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
        Table 10: 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:common-lisp-mode-map
fi:pop-up-temp-window-behavior
fi:list-who-calls                    fi:common-lisp-mode-map
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 Interaction with Allegro Composer

The following Emacs functions allow interaction with the various components of Allegro Composer. To use them, Allegro Composer must be running. Note that these Emacs functions are formally defined later.

fi:inspect-class
fi:inspect-function
fi:inspect-value

Inspect a named class, function or arbitrary value. These functions work in conjunction with Allegro Composer to create an inspector window containing the indicated object.

fi:show-calls-to
fi:show-calls-from

Show graphs of calls to/from a specific function. The Allegro Grapher is used to display a graph with the indicated information.

fi:show-subclasses
fi:show-superclasses

Show graphs of the subclasses/superclasses of a class. The Allegro Grapher is used to display a graph with the indicated information.

Emacs functions and variables that interact with Allegro Composer

fi:inspect-class 
fi:inspect-function
fi:inspect-value
fi:show-calls-to
fi:show-calls-from
fi:show-subclasses
fi:show-superclasses

5.3 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 11: 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:

:operatorfor functions, methods, generic functions and macros
:typefor classes (types)
:setf-methodfor setf methods
:variablefor 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, defined just below. 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.4 Debugging Common Lisp processing 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.htm. 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:

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:scan-stack-mode-map
fi:ss-disassemble                 fi:scan-stack-mode-map
fi:ss-edit                        fi:scan-stack-mode-map
fi:ss-hide-help-text              fi:scan-stack-mode-map
fi:ss-locals                      fi:scan-stack-mode-map
fi:ss-next-frame 
fi:ss-pop                         fi:scan-stack-mode-map
fi:ss-pprint                      fi:scan-stack-mode-map
fi:ss-previous-frame 
fi:ss-quit                        fi:scan-stack-mode-map
fi:ss-reset                       fi:scan-stack-mode-map
fi:ss-restart                     fi:scan-stack-mode-map
fi:ss-return                      fi:scan-stack-mode-map
fi:ss-revert-stack                fi:scan-stack-mode-map
fi:ss-toggle-all                  fi:scan-stack-mode-map
fi:ss-unhide-help-text            fi:scan-stack-mode-map

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.5 Lisp Listeners

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.6 Miscellaneous programming aids

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

5.7 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:

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-mode
fi:rlogin-image-arguments
fi:rlogin-image-name
fi:rlogin-initial-input
fi:rlogin-prompt-pattern
fi:rlogin-send-eof                   fi:rlogin-mode-map
fi:rlogin-send-interrupt             fi:rlogin-mode-map
fi:rlogin-send-quit                  fi:rlogin-mode-map
fi:rlogin-send-stop                  fi:rlogin-mode-map

7.0 Advanced miscellaneous features

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

fi:define-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: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:start-emacs-lisp-interface. We remind you again that the image must have been started with fi:common-lisp for this to work.

7.3 Raw mode

Usually Common Lisp allows input editing of expressions as they are typed in. Borrowing a term from Unix, we call this the cooked mode. A Common Lisp program may need to read characters as they are typed in, without newlines. We call this raw mode. Usually, the Emacs-Lisp interface expects Common Lisp to be in cooked mode. To use the Emacs-Lisp interface with a Common Lisp that is in raw mode, we provide the Lisp function get-terminal-characteristics and Emacs Lisp variables and functions.

Security and raw mode

To use a remote Common Lisp in raw mode with a local Emacs-Lisp interface, one must use the Unix on command. The on command requires that the rexd daemon be turned on in /etc/inetd.conf. The rexd daemon is a known potential security hole.

Note that it is possible to use a local Common Lisp in raw mode and a local Emacs-Lisp interface without using on. That situation does not pose a security problem.

An example use:

(defun raw-read-char (&optional (stream *standard-input*) &rest args)
  ;;  If this function is loaded into a Common Lisp started 
  ;;  under Emacs and via M-x fi:common-lisp, then the 
  ;;  before method on SET-TERMINAL-CHARACTERISTICS will set
  ;;  commands to Emacs that will change the values of 
  ;;  fi:raw-mode and fi:raw-mode-echo appropriately. This 
  ;;  means that the READ-CHAR below will read one character 
  ;;  and *not* require a terminating newline character for 
  ;;  READ-CHAR to return, as is normally needed when not in 
  ;;  RAW or CBREAK mode (see ioctl(2) in the UNIX manual).
  (excl:set-terminal-characteristics stream :input-processing :cbreak)
  ;;  We use HANDLER-CASE instead of UNWIND-PROTECT here 
  ;;  because being in CBREAK mode and going into the debugger 
  ;;  would not be very friendly.
  (prog1
     (handler-case
      (apply #'read-char stream args)
      (error (c)
	(format *terminal-io* 
	  "error doing read-char from ~s: ~a"
	  stream c)))
	   (excl:set-terminal-characteristics stream :input-processing
	   :cooked)))

The following two variables deal with raw mode. The first tells you if you are in raw mode. The second controls the echo behavior in raw mode.

fi:raw-mode
fi:raw-mode-echo

Copyright (c) 1998-2000, Franz Inc. Berkeley, CA., USA. All rights reserved. Created 2000.10.5.