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.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
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:
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 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.
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.
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.
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.
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.
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.
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).
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.
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.
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.
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.
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.
|Arguments: formal arglist|
|Arguments: formal arglist|
|user-option-name||[Emacs user option]|
|Initial value: value|
|Initial value: value|
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.
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 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.
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:
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.)
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.
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.
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".
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:
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.
`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:
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
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).
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.
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.
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).
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/...).
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.
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
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.)
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.
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.
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:
(fi:remote-lisp-send-eof when Lisp is remote)
Table 2: General Subprocess Keybindings
The keys/functions in this category provide the functionality to edit and enter expressions that will be processed by Common Lisp:
Table 3: Editing Keybindings
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:
|C-c 4 .||fi:lisp-find-definition-other-window|
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.
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)
|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.
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.
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.
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.
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
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.
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.
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.)
%% 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
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.
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
(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... )
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.
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:
mode-name is the name of the function that will enter the mode for this file. It overrides the mode chosen based on the file name's type (suffix). This is a feature available in standard Emacs.
name is the name of the package for the file. For compatibility with Lisp machines, name can be a list--everything but the first element is ignored, which should be the name of the package. This value overrides the package specified by an in-package form (if there is one).
name is the name of the readtable for this buffer. See the description of excl:named-readtable in named-readtable.htm for information on creating and using named readtables.
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
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.
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.
Comment the region between the point and the mark. With a non-nil prefix argument, uncomment the region.
Close the current top-level form by inserting as many parenthesis as are necessary.
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.
%% 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
%% 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
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
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.
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.
%% 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
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.
Show graphs of calls to/from a specific function. The Allegro Grapher is used to display a graph with the indicated information.
Show graphs of the subclasses/superclasses of a class. The Allegro Grapher is used to display a graph with the indicated information.
%% fi:inspect-class %% fi:inspect-function %% fi:inspect-value %% fi:show-calls-to %% fi:show-calls-from %% fi:show-subclasses %% fi:show-superclasses
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:
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.
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:
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
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 +  user(4):
At this point, the problem can be debugged using :zoom, the offended function identified and fixed. A :zoom would look like:
 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 ...  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.
->(error "~s is an illegal argument to +" foo) (excl::+_2op foo 1) (1+ foo) (bar foo) (foo foo) (eval (foo 'foo)) (apply #<Function top-level-read-eval-print-loop @ #x4854ce> nil) (excl::start-reborn-lisp)
where the first section of the buffer is help text, which can be made to disappear by typing SPC. The commands in this mode can be grouped according to functionality:
|motion in the stack:
d goto to the next frame, making it `current' u goto to the previous frame, making it `current' . make frame on the line with the point `current'
The `current' frame is signified by the "->" indicator. All the commands below operate on the current frame, the one with the "->" beside it.
r return a value, read from the minibuffer and evaluated in the Common Lisp environment R restart execution, with a prefix argument with a new functions and arguments C-cC-c continue from the current error, which must be continuable, and the default restart is chosen (equivalent to ":continue 0") C-cC-p Abandon this error and pop out to the top level read-eval-print loop or a previous debugger loop (equivalent to ":pop") C-cC-r Abandon all debugger loops and reset to the top level (equivalent to ":reset") q quit scan stack mode
All of the "exiting" type commands leave scan stack mode and restore the window configuration to what is was when this mode was entered.
|print auxiliary information:
D disassemble the function associated with a frame and position the buffer with the return pc highlighted l retrieve the local, or lexical, variables associated with a frame. Local variable information is dependent of the value of the compiler switch compiler:save-local-names-switch p pprint the function and actual arguments of a frame
All the above commands display their output in a buffer named *CL-temp*.
e edit the definition of the function associated with a frame h toggle the visibility of the help text, which if visible, is at the beginning of the buffer a toggle between hiding certain stack frames, which are normally not useful in debugging, and show all stack frames g revert stack the stack from the Common Lisp process from which the current stack was taken
%% 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
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.
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.
This section lists the miscellaneous programming and debugging aids which do not fit into the above sections:
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:
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:
%% 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
%% fi:su %% fi:su-initial-input %% fi:su-mode %% fi:su-prompt-pattern %% fi:remote-root-login %% fi:remote-su-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
%% 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
This section and its subsections discuss advanced features of the Emacs-Lisp interface.
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)))
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:
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.
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.
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.
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.
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