The Emacs-Lisp Interface

ELI Version __VERSION__

$Revision: 1.1.2.4 $


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.20 (shipped with Allegro CL 4.3.2 on Windows 95/NT) to __VERSION__:

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

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

%%include examples/emacs.el
%% 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: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. 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

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
%% fi:package
%% fi:readtable

4.3. Syntactic modification of Common Lisp source code

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

fi:extract-list

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

fi:comment-region

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

fi:super-paren

Close the current top-level form by inserting as many 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
%% 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. 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.

%% 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 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 excl:*record-source-file-info* and excl:*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 (We mention these functions briefly. Their full descriptions are later):

	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 names *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:

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

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

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

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

All the above functions take a prefix argument, since, which defaults to the value of the variable fi:change-definitions-since-default, 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
%% fi:list-changed-definitions 
%% fi:eval-buffer-changed-definitions
%% fi:eval-changed-definitions
%% fi:compile-buffer-changed-definitions
%% fi:compile-changed-definitions
%% fi:copy-buffer-changed-definitions
%% fi:copy-changed-definitions

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:

:processes	list all the Common Lisp processes and their state
:arrest		stop a Common Lisp process
:focus		make a process the focus of future stack
		commands, such :zoom
:unarrest	reverse the effect of arrest and focusing on a
		process, allowing it to continue, if possible

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 which will allow Franz Inc. to be sent a bug report with all the right information:

%% fi:bug-report

6. 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. 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 install_lisp in a relatively standard fashion. install_lisp is the program that installs Allegro CL. By `a relatively standard fashion', we mean that the restart_function= command line argument to install_lisp was not specified.

Problems starting the Emacs-Lisp interface can arise, however, when starting images:

  1. created with excl:dumplisp called with a restart function specified as the value of the :restart-function keyword argument;
  2. created with excl:dumplisp called with a non-nil value specified for the :ignore-command-line-arguments keyword argument;
  3. created by install_lisp with a value specified for the restart_function= command line argument to install_lisp.

Note that cases (2) and (3) are really the same. install_lisp creates its image with excl:dumplisp. install_lisp calls excl:dumplisp with :ignore-command-line-arguments nil in all situations except when restart_function= is specified on the command line, in which case :ignore-command-line-arguments is specified to be t.

Those cases 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.

The problem with an image created with excl:dumplisp with a restart function is a bit more subtle but essentially the same. Command line arguments are processed after the restart function returns. However restart functions are (often) designed not to return (they provide the interface to an application, e.g.) Therefore, specifying a restart function prevents command line arguments from being processed.

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

If, because command-line arguments are ignored or there is a restart function, 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 excl: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