|
Allegro CL version 11.0 |
See franz.com/emacs/ for information on obtaining Emacs (which is no longer supplied with the Allegro CL distribution). That location links to a downloadable installer for GNU Emacs on Windows and to locations from which to download Emacs for Unix platforms. Once you have Emacs installed on your machine, you need to have it load the Emacs-Lisp interface files when it starts up. You do this by putting the appropriate form in your .emacs file, as described:
On Windows, create a .emacs file or add the following to your existing .emacs file. (If you have a home directory on your Windows machine -- many people do not -- place the .emacs file there. Otherwise place the .emacs file in c:\
. [release id] is aclNNN where NNN is the version number of the release (e.g. 11.0
).
load "c:/program files/[release id]/eli/fi-site-init") (
That form assumes you installed Allegro CL in the standard location, c:/program files/acl110/. Replace that with the correct location if it is different.
On Unix/Linux/Mac OS X, create a .emacs file or add the following to your existing .emacs file. The .emacs file goes in your home directory.
load "/usr/local/acl110/eli/fi-site-init") (
That form assumes you installed Allegro CL in the standard location, /usr/local/acl110/. Replace that with the correct location if it is different.
The page at franz.com/emacs/ has additional recommendations for the .emacs file, along with a list of convenient key bindings. The rest of this document is a more complete description of the Emacs-Lisp interface.
ELI was previously incompatible with GNU Emacs on Windows which was compiled and run under Cygwin but was fixed with an update in March, 2006. For information on Cygwin, see www.cygwin.com.
An integral part of the Allegro CL programming environment is the interface between various implementations of Emacs (XEmacs or GNU Emacs) and Allegro CL, hereafter referred to as the Emacs-Lisp interface. This interface allows the editing and running of Common Lisp programs, and contains enhancements that allow a tight coupling between Emacs and Lisp, very similar to those which used to be available only on Lisp machines.
This document provides a technical description of the emacs-lisp interface. See Running Lisp as a subprocess of Emacs in startup.html for information on starting Allegro CL from emacs. Be sure that the necessary definition files are loaded so that the commands to start Allegro CL (using fi:common-lisp) are defined. See What should be in your .emacs file in this document.
Note that we do not include function definitions in this document. To see the documentation for a specific object, do C-h-f
and specify the function name (including the fi:
). Similarly for variables, but with C-h-v
instead of C-h-f
.
Unless otherwise specified, when we say Emacs in this document, we mean XEmacs or GNU Emacs.
We have tried to make the editor seem as if it is implemented in Lisp. However, such an editor would be able to manipulate objects not as text but as first-class Lisp objects and would then be able to know more about programs and be able easily to extract information from them. Emacs with the Emacs-Lisp interface cannot do all that.
Because the Emacs-Lisp interface uses Emacs, which runs as a separate OS process from Lisp, a protocol, called the Lisp-Editor protocol, was designed and implemented to make the communication of information between Emacs and Lisp easier and more natural. A strong requirement of this communication and information exchange is that the user not be aware of it--it must happen in the background. This hidden communication is accomplished by using multiprocessing (commonly called threads) in Allegro CL and process filters in Emacs. The latter is necessary because Emacs does not have multiprocessing.
The Lisp-Editor protocol is not documented in this release of Allegro CL.
This document is broken into several sections:
In the remainder of this section we discuss a number of topics related to Emacs and the Emacs-Lisp interface. The following headings describe the topics discussed. Each heading appears in large type later in this section, followed by one or more paragraphs describing the topic.
Note particularly What should be in your .emacs file. To use the Emacs-Lisp interface, you need only ensure that the correct files are loaded into your running Emacs. What should be in your .emacs file tells you what to put in your .emacs file in your home directory in order to ensure the files are loaded.
The topics are:
If you have never used Emacs before, then you should obtain an Emacs manual. A good one that describes GNU Emacs specifically but is generally applicable to all three supported versions is the GNU Emacs Manual. It is available from the Free Software Foundation (www.gnu.org/software/emacs/.
We assume in this document that you are familiar with Emacs although we do provide occasional hints for beginners.
Emacs has a few different forms of on-line help. Type Control-h (also called C-h for short) three times to find out about the on-line Emacs help facilities. To start the Emacs tutorial, type Control-h t.
The entire Emacs manual is available on-line through the Emacs Info program. Type Control-h i to start up the Info program. To run the Info tutorial, type h after starting the Info program.
See Running Lisp as a subprocess of Emacs for information on starting Allegro CL as a subprocess of Emacs (the recomemnded way to use Allegro CL when developing applications, particularly on UNIX machines).
You cannot run two different Lisp images from the same running Emacs. However, it is possible to run two Emacs's and have each connected to a different Lisp, and you may wish to do this when one Lisp image is performing some general function (such as running a server of some sort) and you wish to do some different work in a separate Lisp. On both Windows and UNIX, this can be done by starting two Emacs's and using fi:common-lisp in each Emacs to start a Lisp.
This also works (try it, particularly on Windows, if using fi:common-lisp in both Emacs processes does not work for any reason).
In Emacs 1: run fi:common-lisp, which starts Lisp 1.
Start Lisp 2, and in it evaluate (new-start-emacs-lisp-interface :port 9999 :announce-to-file "c:/tmp/eli")
.
Start Emacs 2, and evaluate the following in the scratch buffer: (fi:start-interface-via-file "localhost" "*common-lisp*" "c:/tmp/eli")
. Recall that you evaluate a form in the scratch buffer by entering Control-J at the end of the form.
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. On Windows, the "HOME" directory (not a defined concept) is c:\
, so that is where Emacs will look for a .emacs file. You can use -l eli/xxx
: files in the eli directory implement the Emacs-Lisp interface. This directory must be accessible while Emacs is running. It is typically a subdirectory of the Allegro directory. To find the exact path of this directory, within Emacs evaluate the variable load-path
(the value will be one or more directories).Now we discuss the conventions for identifying keyboard keys. The important point is that most Emacs commands are effected by entering one or more keystrokes, with each keystroke being a single key or a combination of keys pressed simultaneously. The most common keys used in combination with others are the CONTROL key, the ESCAPE key and the META key. (Most keyboards do not have a key labeled META, so another key is usually designated as the META key. On PC keyboards, for example, the ALT key is used for the META key. On Sun keyboards the LEFT key is used for the META key. Note also that in most cases, pressing the META and another key simultaneously has the same effect as pressing ESCAPE and the other key sequentially. Of the keys mentioned, only ESCAPE is pressed prior to rather than simultaneously with another key.)
Some more points about designating keys. First we say press to mean enter or depress a keyboard key. Second, CONTROL-a and CONTROL-A are the same character; whereas ESCAPE-a and ESCAPE-A are two different characters.
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 |
nil
, meaning there is no prefix argument). Each command may use the prefix argument or ignore it. One way of specifying a prefix argument is to use the C-u command followed by a numeric argument just before typing the command.function-name |
[Emacs function] |
Arguments: formal arglist |
user-option-name |
[Emacs user option] |
Initial value: value |
variable-name |
[Emacs variable] |
Initial value: value |
The Emacs-Lisp interface works with all recent versions of GNU Emacs and XEmacs. Evaluating M-x emacs-version in your Emacs will print the version number. It is possible that the interface will not work with a version that was released after the release of Allegro CL. If that occurs, please contact us for assistance.
You should use the xeli/ directory instead of the eli/ directory. elc (compiled emacs) files are not compatible between the GNU Emacs and XEmacs. The correct compiled files are in the appropriate directory.
The Emacs function fi:verify-emacs-support will determine if your Emacs has the internal code necessary for the Emacs-Lisp interface. Evaluating M-x fi:verify-emacs-support in your Emacs will print:
everything looks fine!
in the minibuffer if it finds the required support. Otherwise an error is signaled specifying the missing feature(s).
The code for the Emacs-Lisp interface needs to be loaded into Emacs when Emacs starts up. There are different directories for GNU Emacs (the eli/ directory) and XEmacs (the xeli/ directory).
The simplest way to ensure that the interface is loaded is to have the proper forms in your $HOME/.emacs file (that is, the .emacs file in your home directory). On Windows, the "HOME" directory (not a defined concept) is c:\
, so that is where Emacs will look for a .emacs file. You can use -l
The exact forms depend on where Allegro CL was installed on your system.
Assuming that Allegro CL was installed into /usr/local/acl110/
on UNIX machines, here is the correct form to place in .emacs for GNU Emacs users:
(load "/usr/local/acl110/eli/fi-site-init")
Here is the correct form to place in .emacs for XEmacs users:
(load "/usr/local/acl110/xeli/fi-site-init")
In both cases, replace the directory with the correct directory if it is not what is shown.
On Windows machines, the standard location for the Allegro CL directory is *c:\acl110* (there may be additional characters like .64 or .smp or express). Use that or whatever directory was actually used in the .emacs file on Windows machines, again using eli/ or xeli/ as you are using GNU Emacs or XEmacs.
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.
Files whose type is el may be distributed with GNU Emacs under the terms of the GNU Emacs license agreement. Files without the extension el are not covered by the GNU Emacs License agreement and use is restricted according to the Franz Inc. License Agreement.
Below is a brief list of Emacs-Lisp Interface features that have caused users trouble.
C-u may not behave in an expected manner. If a C-u is typed at the end of certain types of buffers, then the functionality invoked will be different from the standard Emacs functionality. This is because C-u can be bound as a superkey (see the information under the heading Superkeys in section 3.1). In Emacs C-u is the universal-argument. In a Unix shell C-u is often the kill character. The Emacs-Lisp Interface provides either functionality depending on where in the buffer C-u is typed. If you are at the end of a buffer and are getting the kill behavior when you want the prefix behavior, move up one line (with C-p) and try again.
The Emacs-Lisp interface keeps track of the current package of common-lisp-mode buffers. If the Emacs-Lisp interface fails to correctly determine the current package, then the interface may fail in mysterious ways. The most common failure occurs when the Emacs-Lisp interface attempts to query the Common Lisp environment. If you experience strange failures you may want to verify that the Emacs-Lisp interface has the correct package by doing the following:
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".
You can limit the interface to the local host by modifying the value of *eli-daemon-socket-hook* as shown in the description of that variable.
There are other security issues. The password chosen to protect the connection is a small number, which can be bruteforced in a few seconds and some LEP variables appear to get overwritten even on error. Please note that the ELI was engineered before threats in common use today existed. We make improvements from time to time but if you have reason to be concerned about security, ELI may not be for you.
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.
The Emacs/Lisp Interface was significantly changed in release 6.2. There have not been major changes since. In this section, we review the 6.2 changes.
There are five major areas of change, each described in its own section:
There are improved menus for Emacs and XEmacs 21 (and later). Previously in Emacs, Allegro CL-specific menu items were not mode specific. (They were mode-specific in XEmacs.) They are now mode-specific in Emacs. Previously, in both XEmacs and Emacs, there were several Allegro CL-specific menus on the menu-bar. Now, by default, there is a single Allegro CL-specific menu on the menu-bar, with sub-menus. The following variable can be used to retrieve previous functionality:
(defvar fi:menu-bar-single-item t
"If non-nil then put a single item onto the menu-bar. Otherwise, the
sub-menus in the single menu are put onto the menu-bar. This variable is
ignored in all but XEmacs and Emacs 21 and later.")
Set this variable to nil
in your .emacs file before loading "fi-site-init" if you want the previous behavior of multiple menus on the menu-bar.
For Emacs (and not XEmacs) the following additional changes have been made:
We now offer the option of complying with the major mode conventions outlined in the GNU Emacs Lisp Reference Manual, edition 2.5.
The variable fi:legacy-keybindings
controls whether you use major mode convention compliant keybindings, or not. The compliant keybindings will be in effect when fi:legacy-keybindings
is nil
. Its initial value is t
so that users downloading the patch will see only minimal behavior change.
(defvar fi:legacy-keybindings t
"If non-nil then define the global, legacy keybindings, which in some
cases are in violation of the Elisp major mode conventions outlined in the
Emacs Lisp Manual. For compatibility reasons the value of this variable is
t by default.")
More details on how keybindings relate to this variable are given below. (fi:legacy-keybindings
subsumes the actions of fi:define-global-lisp-mode-bindings
.) If you want to change the value of fi:legacy-keybindings
, it should be set in your .emacs file before loading "fi-site-init".
Our goal with the patch was to minimize incompatibilities while offering compliance.
Consider the three different version/states of ELI:
Pre-patch (version 2.3.5 or earlier), with fi:define-global-lisp-mode-bindings
unchanged from the default value.
Post-patch (version 2.4.0 or later), with fi:legacy-keybindings
unchanged from the default value (which is t
).
Post-patch, with fi:legacy-keybindings
changed to nil
.
The differences between first two and second two states are outlined under the heading User-visible changes after installing the patch just below and User-visible changes (post patch) with fi:legacy-keybindings set to nil below that.
Here are the changes to keybindings after the patch is downloaded but fi:legacy-keybindings
has its initial value t
. NEW means a new binding, DEL means a removed binding, FROM/TO denote a changed binding.
fi:common-lisp-mode:
NEW C-c C-a fi:lisp-arglist
NEW C-c i fi:insert-arglist
NEW C-c C-f fi:lisp-function-documentation
NEW C-c C-j fi:toggle-to-lisp
NEW C-c C-y fi:kill-definition
NEW C-c C-z fi:list-who-calls
NEW C-c RET fi:lisp-macroexpand
NEW C-c ( fi:lisp-macroexpand-recursively
NEW C-c * fi:pop-definition-mark
fi:inferior-common-lisp-mode:
NEW C-a fi:subprocess-beginning-of-line
NEW C-c C-f fi:lisp-function-documentation
NEW C-c C-j fi:toggle-to-lisp
NEW C-c C-z fi:list-who-calls
NEW C-c ( fi:lisp-macroexpand-recursively
NEW C-c * fi:pop-definition-mark
DEL C-c - fi:log-functional-change
FROM C-c C-a fi:subprocess-beginning-of-line
TO C-c C-a fi:lisp-arglist
FROM C-c C-y fi:pop-input
TO C-c C-y fi:kill-definition
FROM C-c RET fi:subprocess-input-region
TO C-c RET fi:lisp-macroexpand
C-a
is added in accordance with the major mode conventions: it is reasonable for a major mode to rebind a key sequence with a standard meaning, if it implements a command that does "the same job" in a way that fits the major mode better. This makes C-c C-a
obsolete and available for fi:lisp-arglist
.
fi:pop-input (C-c C-y)
was redundant (same as C-c C-p
).
fi:subprocess-input-region (C-c RET)
was obscure and little used, so C-c RET
was used for fi:lisp-macroexpand
.
fi:lisp-listener-mode:
NEW C-a fi:subprocess-beginning-of-line
NEW C-c C-f fi:lisp-function-documentation
NEW C-c C-j fi:toggle-to-lisp
NEW C-c C-z fi:list-who-calls
NEW C-c ( fi:lisp-macroexpand-recursively
NEW C-c * fi:pop-definition-mark
DEL C-c - fi:log-functional-change
FROM C-c C-a fi:subprocess-beginning-of-line
TO C-c C-a fi:lisp-arglist
FROM C-c C-y fi:pop-input
TO C-c C-y fi:kill-definition
FROM C-c RET fi:subprocess-input-region
TO C-c RET fi:lisp-macroexpand
fi:emacs-lisp-mode:
DEL C-c l fi:toggle-to-lisp
fi:rlogin-mode, fi:shell-mode, fi:su-mode, fi:remote-su-mode:
NEW C-a fi:subprocess-beginning-of-line
NEW C-c C-g fi:telnet-start-garbage-filter
NEW DEL backward-delete-char-untabify
DEL C-c C-a fi:subprocess-beginning-of-line
DEL C-c C-y fi:pop-input
fi:telnet-mode:
NEW C-a fi:subprocess-beginning-of-line
NEW C-c C-g fi:telnet-start-garbage-filter
NEW DEL backward-delete-char-untabify
DEL C-c C-a fi:subprocess-beginning-of-line
DEL C-c C-y fi:pop-input
DEL C-c m fi:telnet-start-garbage-filter
The following are new to all Lisp editing modes:
NEW C-c < fi:previous-top-level-form
NEW C-c > fi:next-top-level-form
This section details user-visible keybindings changes when the patch is downloaded and fi:legacy-keybindings
has the value nil
:
fi:common-lisp-mode:
DEL C-c A fi:lisp-arglist
DEL C-c C fi:list-who-calls
DEL C-c D fi:describe-symbol
DEL C-c F fi:lisp-function-documentation
DEL C-c M fi:lisp-macroexpand
DEL C-c T fi:toggle-trace-definition
DEL C-c W fi:lisp-macroexpand-recursively
DEL C-c a fi:lisp-arglist
DEL C-c c fi:list-who-calls
DEL C-c d fi:describe-symbol
DEL C-c f fi:lisp-function-documentation
DEL C-c k fi:kill-definition
DEL C-c l fi:toggle-to-lisp
DEL C-c m fi:lisp-macroexpand
DEL C-c t fi:toggle-trace-definition
DEL C-c w fi:lisp-macroexpand-recursively
DEL ESC A fi:lisp-arglist
DEL ESC C fi:list-who-calls
DEL ESC D fi:describe-symbol
DEL ESC F fi:lisp-function-documentation
DEL ESC M fi:lisp-macroexpand
DEL ESC T fi:toggle-trace-definition
DEL ESC W fi:lisp-macroexpand-recursively
FROM C-c C-t fi:trace-definer
TO C-c C-t fi:toggle-trace-definition
The change of C-c C-t
was deemed necessary since fi:toggle-trace-definition is more important than fi:trace-definer.
fi:inferior-common-lisp-mode and fi:lisp-listener-mode:
DEL C-c A fi:lisp-arglist
DEL C-c C fi:list-who-calls
DEL C-c D fi:describe-symbol
DEL C-c F fi:lisp-function-documentation
DEL C-c M fi:lisp-macroexpand
DEL C-c T fi:toggle-trace-definition
DEL C-c W fi:lisp-macroexpand-recursively
DEL C-c a fi:lisp-arglist
DEL C-c c fi:list-who-calls
DEL C-c d fi:describe-symbol
DEL C-c f fi:lisp-function-documentation
DEL C-c k fi:kill-definition
DEL C-c l fi:toggle-to-lisp
DEL C-c m fi:lisp-macroexpand
DEL C-c s fi:scan-stack
DEL C-c t fi:toggle-trace-definition
DEL C-c w fi:lisp-macroexpand-recursively
DEL C-x RET fi:inferior-lisp-input-list
DEL ESC A fi:lisp-arglist
DEL ESC C fi:list-who-calls
DEL ESC D fi:describe-symbol
DEL ESC F fi:lisp-function-documentation
DEL ESC M fi:lisp-macroexpand
DEL ESC RET fi:inferior-lisp-input-sexp
DEL ESC T fi:toggle-trace-definition
DEL ESC W fi:lisp-macroexpand-recursively
FROM C-c C-t fi:trace-definer
TO C-c C-t fi:toggle-trace-definition
NEW C-c & fi:scan-stack
Other than the rearranged keybindings listed above, the following are completely new key bindings providing new functionality:
fi:common-lisp-mode:
C-c * fi:pop-definition-mark
C-c < fi:previous-top-level-form
C-c > fi:next-top-level-form
SPC fi:arglist-lisp-space
fi:inferior-common-lisp-mode:
C-a fi:subprocess-beginning-of-line
C-c * fi:pop-definition-mark
SPC fi:arglist-lisp-space
fi:lisp-listener-mode:
C-a fi:subprocess-beginning-of-line
C-c * fi:pop-definition-mark
SPC fi:arglist-lisp-space
C-c *
is a convenient way to return to a previous context after C-c .
.
fi:rlogin-mode, fi:shell-mode, fi:telnet-mode, fi:su-mode,
fi:remote-su-mode:
C-a fi:subprocess-beginning-of-line
C-c C-g fi:telnet-start-garbage-filter
For the shell-related modes, C-c C-g
is a quick way to get rid of those annoying ^M
's that occur on some systems.
The default behavior is now to retrieve and display in the minibuffer arglist information, when a connection to Lisp has already been made and the arglist information is available for the symbol before the point at the time SPC is typed. The variable which controls this feature is:
(defvar fi:arglist-on-space t
"If non-nil, then bind SPC to a function that retrieves arglist
information and displays it according to the value of the variable
fi:auto-arglist-pop-up-style.")
The method by which the arglist is displayed is controlled by this variable:
(defvar fi:auto-arglist-pop-up-style '(minibuffer)
"The value of this variable is used to bind
fi:pop-up-temp-window-behavior when ([fi:arglist-lisp-space]) is executed.
A value of '(split . nil) is handy for insuring that the arglist
information stays around long enough to be used.")
In Emacs 21 or later, the default behavior of the minibuffer is to grow dynamically, and this will allow even large arglists to be displayed without having a new buffer pop up. If you want more permanance to the arglist information, while you type in your program, use this in your .emacs:
(setq fi:auto-arglist-pop-up-style '(split . nil))
XEmacs does not have a dynamically resizing minibuffer, so if the information being displayed is larger than one line, it will be put into the *CL-Temp*
buffer.
Pop-up buffer handling has been improved. The value of fi:pop-up-temp-window-behavior
can now be the list '(minibuffer)
, which allows for the minibuffer to be used for Lisp-queried information (e.g., arglist, macro expansions), as well as evaluations of user code.
The documentation for fi:pop-up-temp-window-behavior
has also been improved:
(defvar fi:pop-up-temp-window-behavior '(other . t)
"The value of this variable determines the behavior of the popup
temporary buffers used to display information which is the result of
queries of the Lisp environment. As of version 2.4.0 of the interface,
this includes output generated by arbitrary evaluations of user-written
Lisp code, when the value of this variable is '(minibuffer).
The value is a cons of the form (style . boolean).
The possible values for the `style' (or the car of the cons) are the symbols
minibuffer, split, other, and replace:
- `minibuffer' causes the minibuffer to always be used, regardless of the
number of lines of output. Recent versions of Emacs have dynamically
resizing minibuffers, and this is useful in combination with these newer
versions.
- `split' causes the largest window to be split and the new window to be
minimal in size.
- `other' causes the other window to be used, splitting the screen if there is
only one window.
- `replace' causes the current window to be replaced with the help buffer.
The possible values for the `boolean' (or cdr of the cons) are `t' or
`nil'. `t' means use the minibuffer, and if the resulting text does not
fit, use a window. `nil' means always use a window. A value of `nil' is
handy since messages printed in the minibuffer can easily be erased.
If the `style' is `minibuffer', then the `boolean' is ignored, since
the minibuffer is always used, regardless of the amount of output.")
Many thanks to Bill Clementson for many of the suggestions and helping with testing.
Starting the Emacs-Lisp interface is actually a misnomer. Assuming the interface code has been loaded into Emacs, it is available whenever Emacs is running. (Below, in Running Common Lisp, we describe how to start Lisp from within Emacs). Therefore, this section is really about ensuring that the interface is loaded into Emacs.
The simplest way to ensure that the interface is loaded is to have the proper forms in your $HOME/.emacs file (that is, the .emacs file in your home directory). See What should be in your .emacs file for information on what to put in that file.
With the proper form in the .emacs file, the interface will be loaded when Emacs starts up. Note that in the following sections, we discuss many variables that customize the Emacs-Lisp programming environment. Forms changing the default values of these variables can also be put in the .emacs file, allowing you to customize the environment to your liking. Note that these forms should be placed before (above) the two forms specified above.
While putting the specified load form in $HOME/.emacs (as described in What should be in your .emacs file) is the recommended method of loading the Emacs-Lisp interface, it is not required. If you are using Emacs and the Emacs-Lisp interface is not loaded, you can load it as follows.
For GNU Emacs users:
M-x load-file RET [Allegro directory]/eli/fi-site-init
For XEmacs users:
M-x load-file RET [Allegro directory]/xeli/fi-site-init
The [Allegro directory] is the directory where Allegro CL is installed.
If M-x fi:common-lisp is used to start a Common Lisp process on a remote machine (i.e. a different machine than the one running Emacs), and Emacs is exited without first exiting from Common Lisp, Common Lisp may continue running on the remote machine. While there seems to be no sure-fire way to prevent this, you can load code into Emacs which prevents you from exiting Emacs while Common Lisp is running. This code is contained in the file misc/dot-emacs (misc/dot-emacs.el on Windows) in the Allegro directory. Make use of this code if you wish by placing it in your .emacs file in your home directory (misc/dot-emacs is a sample .emacs file).
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 -- i.e Control-J
). If the value is nil, the interface is not loaded. Check your $HOME/.emacs file and make sure the form that loads "fi-site-init" is in the file. If the value of the variable is t, there is a more serious problem which does not have an easily identifiable cause.
The cause of this problem cannot be known in advance. Here we suggest how to further investigate. Exit Emacs and restart it with the -q option (which suppresses the loading of the $HOME/.emacs file). Then type the following in the scratch buffer:
(setq debug-on-error t) LF
(load "~/.emacs") LF
Note that you press LINEFEED (LF, typically Control-J) rather than RETURN (RET) after typing the forms.
If you run Emacs and Lisp on different machines, then you must be certain that the value of fi:emacs-to-lisp-transaction-directory is a directory which is accessible on both machines. Care must be taken to get the pathname just right, including the possible NFS prefix (/net/MACHINE-NAME/...).
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.
Start up Emacs with the -q option: [shell prompt]% emacs -q
This will start up Emacs without reading your .emacs file.
Load the Emacs-Lisp interface by hand: M-x load-file RET [Allegro directory]/eli/fi-site-init
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.
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.
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.)
Interacting with Common Lisp occurs in an Emacs subprocess buffer. This interaction can even occur between Emacs and Common Lisp processes that reside on different machines. Common Lisp must be started with the function fi:common-lisp or with fi:start-interface-via-file. Although you can (using fi:start-interface-via-file) start Common Lisp in an Emacs shell and then initiate the interface, it is unusual to do so. Note that most of the Emacs-Lisp interface will not work with a Lisp image started in an Emacs shell and not connected to Lisp using fi:start-interface-via-file.
When called for the first time in an emacs session, fi:common-lisp prompts in the minibuffer for information on how you wish to invoke Lisp (see section Functions and variables for Interacting with a CL subprocess for details on what questions are asked). Subsequent calls use the previous answers unless qualified with C-u
. Once it knows what to invoke, fi:common-lisp makes a Common Lisp subprocess in a buffer named (in the default) *common-lisp*
. After start-up, *common-lisp*
might have contents which look similar to this:
Allegro CL 11.0
Copyright (C) Franz Inc., Lafayette, CA, USA
;; Optimization settings: safety 1, space 1, speed 1,
;; debug 2. For a complete description of all compiler
;; switches given the current optimization settings
;; evaluate (EXPLAIN-COMPILER-SETTINGS).
;; Starting socket daemon and emacs-lisp interface...
USER(1):
First, what you in fact see will probably be different. In particular everything after 11.0
in the first line will likely be different (the information there specifies the exact version shipped to you); the notice in comments may be changed and anyway, we have changed the linebreaks to prevent wrapping; and the code changes faster than the documentation. However, what you see will be similar.
The user(N): is the Allegro CL prompt. The comment just before the first prompt signifies that an Allegro CL process that communicates with Emacs has started (see multiprocessing.html for a definition of process). Meanwhile, in the Emacs minibuffer, you should see
Trying to start connection...done.
That message signifies that the hidden, or backdoor, communication between Emacs and Common Lisp has been initiated. Emacs and Common Lisp will be communicating over a network connection.
The Emacs-Lisp interface is currently started with the -e Allegro Common Lisp command line option. This allows the interface to be started for images that do not behave like a standard Common Lisp image (with a read-eval-print loop). For more information, see the description of fi:start-lisp-interface-arguments in Functions and variables for Interacting with a CL subprocess below.
It is possible for the interface to fail to start up (failure will be indicated by the failure of Starting socket daemon and emacs-lisp interface...
to appear in the common-lisp buffer or the failure of Trying to start connection...done
to appear in the Emacs minibuffer. You can start the interface (or restart it if it dies) with the Allegro CL function new-start-emacs-lisp-interface.
The emacs function fi:start-interface-via-file allows you to connect Emacs to a running Lisp after Lisp has started. This is typically done for debugging a running but apparently broken process. fi:start-interface-via-file takes arguments host buffer connection-file, specifying the host machine, the emacs buffer name, and the file created by new-start-emacs-lisp-interface that will be used for the connection. To start the interface using this method, on the lisp side, you would do something like this:
(excl:new-start-emacs-lisp-interface :port 7666
:announce-to-file"~/.eli-startup")
See
new-start-emacs-lisp-interface for a discussion of the arguments. Then, sometime later on the emacs side, do this (the host is "pie"):
(fi:start-interface-via-file "pie" "*common-lisp*" "~/.eli-startup")
The tables in this section have been updated and describe the new behavior with fi:legacy-keybindings
having its initial value t
(fewest changes) and the value nil
(most changes).
Many of the key bindings in a common-lisp buffer behave much like a shell buffer does. The common-lisp buffer and a shell buffer have mode specific commands with the key prefix C-c. Both buffers have key bindings that will delete typed input (words or lines), send an EOF or interrupt, or send the input to the Allegro CL process.
The key bindings can be classified into four categories: (1) General subprocess interaction, (2) Editing, (3) Lisp environment queries, and (4) Superkeys (Superkeys are keybindings that have different effects according to whether they are entered at the end of a buffer or elsewhere in the buffer). We describe the key bindings in each category next.
The keys/functions in this category provide the functionality that a shell buffer would have. All the special characters (C-c, C-d, C-w, C-u, etc.) are handled by these functions:
key | binding |
---|---|
C-a | fi:subprocess-beginning-of-line |
C-c C-\ | fi:subprocess-quit |
C-c C-c | fi:interrupt-listener |
C-c C-d | fi:subprocess-send-eof (fi:remote-lisp-send-eof when Lisp is remote) |
C-c C-j | fi:toggle-to-lisp |
C-c C-k | fi:subprocess-kill-output |
C-c C-l | fi:list-input-ring |
C-c C-n | fi:push-input |
C-c C-o | fi:subprocess-send-flush |
C-c C-p | fi:pop-input |
C-c C-r | fi:re-search-backward-input |
C-c C-s | fi:re-search-forward-input |
C-c C-u | fi:subprocess-kill-input |
C-c C-v | fi:subprocess-show-output |
C-c C-w | fi:subprocess-backward-kill-word |
C-c = | fi:lisp-sync-current-working-directory |
C-x RET | fi:inferior-lisp-input-list if
|
ESC RET | fi:inferior-lisp-input-sexp if
|
RET | fi:inferior-lisp-newline |
Table 1: General Subprocess Keybindings
The keys/functions in this category provide the functionality to edit and enter expressions that will be processed by Common Lisp:
key | binding |
---|---|
TAB | fi:lisp-indent-line |
DEL | backward-delete-char-untabify |
; | fi:lisp-semicolon (if fi:lisp-do-indentation is non-nil) |
C-c ] | fi:super-paren |
C-c % | fi:extract-list |
C-c ; | fi:comment-region |
C-c ^ | fi:center-defun |
C-c C-e | fi:end-of-defun |
C-c C-q | fi:indent-sexp |
C-c C-y | fi:kill-definition |
ESC C-q | fi:indent-sexp |
Table 2: Editing Keybindings
The keys/functions in this category provide a way to obtain information from the Allegro CL environment. These functions use the hidden communication between Emacs and Lisp to simulate Lisp-machine like behavior:
key | binding |
---|---|
C-c C-a | fi:lisp-arglist |
C-c i | fi:insert-arglist |
C-c C-f | fi:lisp-function-documentation |
C-c TAB | fi:lisp-complete-symbol |
C-c RET | fi:lisp-macroexpand |
C-c C-t | fi:trace-definer if
fi:legacy-keybindings is t ,
fi:toggle-trace-definition if
fi:legacy-keybindings is nil |
C-c C-y | fi:kill-definition |
C-c C-z | fi:list-who-calls |
C-c ( | fi:lisp-macroexpand-recursively |
C-c * | fi:pop-definition-mark |
C-c . | fi:lisp-find-definition |
C-c 4 . | fi:lisp-find-definition-other-window |
C-c , | fi:lisp-find-next-definition |
C-c ? | fi:lisp-apropos |
C-c SPC | fi:lisp-delete-pop-up-window |
C-c & | fi:scan-stack |
C-c A | fi:lisp-arglist if
fi:legacy-keybindings is non-nil,
no binding otherwise |
C-c C | fi:list-who-calls if
fi:legacy-keybindings is non-nil,
no binding otherwse |
C-c D | fi:describe-symbol if
fi:legacy-keybindings is non-nil,
no binding otherwise |
C-c F | fi:lisp-function-documentation if
fi:legacy-keybindings is non-nil,
no binding otherwise |
C-c K | fi:kill-definition if
fi:legacy-keybindings is non-nil,
no binding otherwise |
C-c L | fi:toggle-to-lisp if
fi:legacy-keybindings is non-nil,
no binding otherwise |
C-c M | fi:lisp-macroexpand if
fi:legacy-keybindings is non-nil,
no binding otherwise |
C-c S | fi:scan-stack if
fi:legacy-keybindings is non-nil,
no binding otherwise |
C-c T | fi:toggle-trace-definition if
fi:legacy-keybindings is non-nil,
no binding otherwise |
C-c W | fi:lisp-macroexpand-recursively if
fi:legacy-keybindings is non-nil,
no binding otherwise |
C-c a | fi:lisp-arglist if
fi:legacy-keybindings is non-nil,
no binding otherwise |
C-c c | fi:list-who-calls if
fi:legacy-keybindings is non-nil,
no binding otherwse |
C-c d | fi:describe-symbol if
fi:legacy-keybindings is non-nil,
no binding otherwise |
C-c f | fi:lisp-function-documentation if
fi:legacy-keybindings is non-nil,
no binding otherwise |
C-c k | fi:kill-definition if
fi:legacy-keybindings is non-nil,
no binding otherwise |
C-c l | fi:toggle-to-lisp if
fi:legacy-keybindings is non-nil,
no binding otherwise |
C-c m | fi:lisp-macroexpand if
fi:legacy-keybindings is non-nil,
no binding otherwise |
C-c s | fi:scan-stack if
fi:legacy-keybindings is non-nil,
no binding otherwise |
C-c t | fi:toggle-trace-definition if
fi:legacy-keybindings is non-nil,
no binding otherwise |
C-c w | fi:lisp-macroexpand-recursively if
fi:legacy-keybindings is non-nil,
no binding otherwise |
Table 3: Lisp Environment Query Keybindings
The functions in this category that read symbols also do dynamic completion of symbols present in the Allegro CL environment. The Emacs-Lisp interface has no static symbols database, so a symbol is available for completion just after it is created. See the description of fi:lisp-complete-symbol in Finding the definitions of functions below.
Because there is a set of process-related functions that are needed in the common-lisp buffer, these key bindings have a special meaning at the end of the buffer. That is, there are certain key sequences which have behavior determined by fi:inferior-common-lisp-mode when typed at the end of the buffer, but have their global meaning when typed anywhere else in the buffer. The key sequences and their meanings are given below, and they are only in effect when fi:subprocess-enable-superkeys is non-nil (before fi:inferior-common-lisp-mode is entered for the first time)
key | binding |
---|---|
C-\ | send "kill -QUIT" (UNIX quit) to Common Lisp |
C-d | send EOF to Common Lisp |
C-o | flush output (from "stty flush") |
C-u | delete the current input (from "stty kill") |
C-w | delete the last word (from "stty werase") |
C-z | suspend job (from "stty susp"), only for shell-related modes |
Table 4: Superkeys
C-w
, C-u
, and C-o
are chosen because those are the (default) keys used by stty werase, kill, and flush in Unix.
So, C-d at the end of the common-lisp buffer will send Common Lisp an end of file, and at other places in the buffer will delete the next character (unless you have rebound C-d to call another function). See the entry for fi:superkey-shadow-universal-argument
for ways to control the universal argument C-u.
The Emacs Lisp function bound to RET is more than just "send the current line to the Common Lisp process". In fact, it sends only entire s-expressions, or forms, to Common Lisp. This allows editing of incomplete, multi-line expressions before Common Lisp sees them.
To accomplish the advanced input features, Emacs needs to know the form of the Common Lisp prompt. The prompt in Allegro CL is defined by the value of the variable *prompt*. This value must be a string acceptable as the second argument to format. Although the prompt can be changed at any time, it is typically set in the file $HOME/.clinit.cl
. But however the prompt is changed, the Emacs user option fi:common-lisp-prompt-pattern
must be changed as well -- so that the default value of *prompt* (in Common Lisp) and fi:common-lisp-prompt-pattern
(in Emacs Lisp) are in agreement.
See the file misc/prompts.cl in the Allegro directory for examples of other prompts. See top-level.html for information on the prompt itself.
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 and fi:insert-arglist.
The current package is displayed in the mode-line. So, when
:package foo
is entered in the *common-lisp*
buffer, the mode-line will be updated to contain the string pkg:foo after the mode identifier. See Packages and readtables for more information.
Because Allegro CL has multiprocessing (see multiprocessing.html for more information), multiple threads of control can be created--multiple user interactions, or top-levels, can be created within the same UNIX process. Within one Common Lisp process, any number of lisp listeners, as these top-levels are called, can be created.
The Emacs-Lisp interface has a function for creating a lisp listener onto an existing Common Lisp subprocess: fi:open-lisp-listener. This can be used to debug multiprocessing applications or to execute forms while Common Lisp is doing other processing. See also Lisp Listeners and multiprocessing.
When an open parenthesis and an operator name is typed, the argument list is displayed is the minibuffer if it is known (see fi:arglist-on-space and fi:auto-arglist-pop-up-style). The argument list is also displayed by fi:lisp-arglist (C-c C-a).
A new command, fi:insert-arglist, was added in a Summer, 2006 update. Its binding is C-c i and when invoked after '(
;; In each case, we define a function (except where we use a standard
;; CL function), and the type '(<fun-name> C-c i'. We show
;; what is inserted:
cl-user(198): (defun foo (a &key (b 'bee) (c 'cee)) (list a b c1))
foo
cl-user(199): (foo a :b b :c c)
cl-user(201): (defun foo (a b &rest c) (list a b c))
foo
cl-user(202): (foo a b c...)
cl-user(202): (defun foo (a &optional b c d) (list a b c d))
foo
cl-user(203): (foo a [b] [c] [d])
cl-user(203): (find item sequence :from-end from-end :test test :test-not test-not :start start :end end :key key)
;; Even uncommon constructions are supported. In the following definition,
;; the designator name of the second keyword argument is the symbol C
;; (not the keyword :C) while the argument name is C1. Anyway, C-c i
;; does the right thing:
cl-user(203): (defun foo (a &key (b 'bee) ((c c1) 'cee)) (list a b c1))
foo
cl-user(204): (foo a :b b 'c c)
The function fi:common-lisp starts Common Lisp from within Emacs.
Below is a fragment of code which can be placed in your .emacs file that defines a function run-common-lisp, which will start up a Lisp with default arguments. run-common-lisp is useful if the user frequently uses the same Lisp.
(setq fi:common-lisp-image-name "/usr/local/acl110/mlisp")
(setq fi:common-lisp-host "ultra")
;; This function starts up lisp with your defaults.
(defun run-common-lisp ()
(interactive)
(fi:common-lisp fi:common-lisp-buffer-name
fi:common-lisp-directory
fi:common-lisp-image-name
fi:common-lisp-image-arguments
fi:common-lisp-host
fi:common-lisp-image-file))
;; This function uses specific values rather than variables.
;; Either way works and one may be more suitable for you than
;; another (this example runs a Lisp on Windows from an Emacs
;; running on Windows:
(defun run-ide ()
(interactive)
(fi:common-lisp "*common-lisp*"
"h:/acl110/"
"h:/acl110/allegro.exe"
'("")
"localhost"
"h:/acl110/allegro.dxl"))
;; Set up a keybinding for `run-common-lisp', two possible ways
;; (keybindings for run-ide are analogous):
(progn
(setq ctlx-3-map (make-keymap))
(define-key ctl-x-map "3" ctlx-3-map)
(define-key ctlx-3-map "l" 'run-common-lisp))
;; or this:
(define-key global-map "\C-xl" 'run-common-lisp)
;; Run cl each time emacs is run:
(run-common-lisp)
fi:emacs-lisp-interface-version
fi:verify-emacs-support
fi:common-lisp
fi:open-lisp-listener
fi:common-lisp-buffer-name
fi:common-lisp-directory
fi:common-lisp-image-name
fi:common-lisp-image-file
fi:common-lisp-image-arguments
fi:common-lisp-host
fi:common-lisp-prompt-pattern
fi:common-lisp-subprocess-timeout
fi:common-lisp-subprocess-wait-forever
fi:legacy-keybindings
fi:define-global-lisp-mode-bindings
fi:menu-bar-single-item
fi:compile-at-load-time
fi:toggle-to-lisp
fi:connect-to-windows
fi:start-lisp-interface-arguments
fi:use-background-streams
fi:start-lisp-interface-hook
fi:start-interface-via-file
fi:reset-lep-connection
fi:in-package-regexp
fi:default-in-package-regexp
fi:inferior-common-lisp-mode
fi:inferior-lisp-input-list
fi:inferior-lisp-input-sexp
fi:inferior-lisp-newline
fi:inferior-lisp-send-input
fi:lisp-sync-current-working-directory
fi:list-input-ring
fi:pop-input
fi:push-input
fi:re-search-backward-input
fi:re-search-forward-input
fi:remote-lisp-send-eof
fi:subprocess-backward-kill-word
fi:subprocess-beginning-of-line
fi:subprocess-input-region
fi:subprocess-interrupt
fi:subprocess-kill
fi:subprocess-kill-input
fi:subprocess-kill-output
fi:subprocess-quit
fi:subprocess-send-input
fi:subprocess-send-eof
fi:subprocess-send-flush
fi:subprocess-show-output
fi:subprocess-suspend
fi:lisp-listener-mode
fi:interrupt-listener
fi:tcp-lisp-listener-kill-process
fi:tcp-lisp-listener-send-eof
fi:emacs-to-lisp-transaction-directory
fi:default-input-ring-max
fi:display-buffer-function
fi:new-screen-for-common-lisp-buffer
fi:eval-in-lisp
fi:eval-in-lisp-asynchronous
fi:filename-frobber-hook
fi:lisp-evalserver-number-reads
fi:shell-cd-regexp
fi:shell-popd-regexp
fi:shell-pushd-regexp
fi:subprocess-continuously-show-output-in-visible-buffer
fi:subprocess-enable-superkeys
fi:user-env-vars
fi:subprocess-env-vars
fi:subprocess-max-buffer-lines
fi:superkey-shadow-universal-argument
This section and its subsections discuss the Emacs mode for editing Common Lisp programs.
Common Lisp editing mode, fi:common-lisp-mode, is automatically entered when a Common Lisp source file is visited. The Emacs Lisp variable fi:common-lisp-file-types specifies the file types of Common Lisp source files. The following sections discuss the various aspects of fi:common-lisp-mode. Please note that bindings in this mode are changed by a patch made available in August, 2003. See Changes in the interface in Release 6.2 for details.
Indentation of a form can be performed with C-M-q, (Hold the CONTROL and META keys while depressing the q key) when the point is on an opening parenthesis. Indentation of the current line can be performed by typing TAB.
All Common Lisp forms are indented with the generally accepted amount of indentation. At the current time, the user interface to the indentation method specification is not documented. It is, however, available for your perusal in the file fi/indent.el - -there are many examples at the end of this file.
Comments in Common Lisp begin with a semicolon (;). Comments starting with different numbers of semicolons are indented differently. The Emacs Lisp variable fi:lisp-comment-indent-specification
specifies how the indentation is done. fi:lisp-comment-indent-specification
is a list, where the Nth element (counting from 1) specifies how N semicolons will be indented. That is, the first element specifies how a single semicolon will be indented. The values in the list are either:
The initial value of fi:lisp-comment-indent-specification is
`(list 40 t nil 0)
which means indent one semicolon to column 40, two semicolons to the column s-expressions would indent to, three semicolons should be left alone, and four semicolons are left justified.
NOTE: if the buffer-local variable comment-column is changed, then the first element of fi:lisp-comment-indent-specification
is changed to contain the value of comment-column.
Additionally, if fi:lisp-electric-semicolon
is non-nil
, then semicolon placement will happen automatically when semicolons are inserted into the buffer--no TAB is required to indent the current line. The value of this variable defaults to nil
.
Here is an example of each type, using default values:
;;;; Foo the Bar
(in-package :foo)
(defun bar (thang)
;; BAR the THANG
;;;; WARNING: frobs beware
(frob-the-frammis thang) ; out in right margin field
;;; leave me where I lie...
;; but indent by right...
)
fi:lisp-comment-indent-specification
The Common Lisp package in which a source file is defined is an important quantity which must be known to Emacs. Readtables, though less essential, are also useful when known to Emacs. Such information is used by Emacs, when communicating with Common Lisp, to insure that the operations performed in the Common Lisp environment are with respect to the correct package and expressions are read with the correct readtable.
There are two methods for telling Emacs about which package to use.
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.
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:
mode: mode-name: 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.
package: name: 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).
readtable: namename is the name of the readtable for this buffer. See the description of excl:named-readtable in named-readtable for information on creating and using named readtables.
Fields in the file mode line are separated by semicolons. The following example illustrates a file mode line: With the in-package and eval-when forms, loading this file into Emacs will result in the correct package and readtable being used by Lisp operations on the file:
;; -*- mode: fi:common-lisp-mode; package: mypack; readtable: myrt -*-
(in-package :mypack)
(eval-when (compile
load ;; see note below
eval)
(setq *readtable* (named-readtable :myrt)))
; ... [rest of code]
Note: load is not needed in the eval-when form when no extraneous reading will happen when the compiled version of this file is loaded. load must be omitted if the named readtable does not actually exist at runtime (when, for example, you use a special readtable for developing an application but it is not included in the application when it is finished).
The file mode line is parsed by the standard Emacs Lisp function set-auto-mode, which has been modified by this interface to look for the package and readtable fields. If you change the file mode line or in-package form in a buffer, you may execute the Emacs Lisp function fi:parse-mode-line-and-package to re-parse the package. A file mode line, if supplied, overrides the value of an in-package form.
The display mode line is used to display status information about buffers (and it appears, usually in a contrasting color, at the bottom of the buffer). In particular, the package and readtable (if any) are displayed in the display mode line.
If a file contains neither a file mode line nor an in-package form, the following supplies the package:
fi:default-package
fi:package
fi:readtable
Users of Emacs Lisp mode in standard Emacs will be familiar with the many ways to manipulate Lisp expressions. We mention three additional functions available in fi:common-lisp-mode. A full description of these functions and the keybindings defined for the functions is provided later.
fi:extract-list
Take the list on which the point resides and move it up one level. That is, delete the enclosing expression. With an optional integer prefix argument n, take the list on which the point resides and move it up n times.
fi:comment-region
Comment the region between the point and the mark. With a non-nil prefix argument, uncomment the region.
fi:super-paren
Close the current top-level form by inserting as many parentheses as are necessary.
Please note that bindings in this mode are changed by a patch made available in August, 2003. See Changes in the interface in Release 6.2 for details. The tables in this section have not yet been updated and describe the pre-patch behavior. In the lists below, we mark the changed bindings (indicating whether the change occurs with fi:legacy-keybindings
set to its initial value t (the fewest changes) or set to nil (the most changes).
The commands that were discussed that query the Common Lisp environment, in Key bindings in Common Lisp subprocess mode, also apply to Common Lisp editing mode, with several additional commands:
key | binding | description |
---|---|---|
C-c C-b | fi:lisp-eval-or-compile-current-buffer | evaluate or compile the entire current buffer |
C-c C-r | fi:lisp-eval-or-compile-region | evaluate or compile the region bounded by the point and mark |
C-c C-s | fi:lisp-eval-or-compile-last-sexp | evaluate or compile the last S-expression |
C-c C-x | fi:lisp-eval-or-compile-defun | evaluate or compile the entire current top-level form |
ESC C-x | fi:lisp-eval-or-compile-defun if fi:legacy-keybindings is t, no binding otherwise |
If fi:lisp-evals-always-compile
is non-nil, then the above group of functions compile without a prefix argument and evaluate the source without compilation when a prefix argument is provided.
key | binding | description |
---|---|---|
C-c C-m | fi:lisp-macroexpand | Cause the form at the point to be macroexpanded. |
C-c M | fi:lisp-macroexpand
if fi:legacy-keybindings is t,
no binding otherwise
|
|
C-c m | fi:lisp-macroexpand
if fi:legacy-keybindings is t,
no binding otherwise
|
|
ESC M | fi:lisp-macroexpand
if fi:legacy-keybindings is t,
no binding otherwise
|
|
C-c ( | fi:lisp-macroexpand-recursively | Cause the form at the point to be recursively macroexpanded. If given a prefix argument, the recursive macroexpansion is done as the compiler would. The compiler simulation is approximate only and does not preserve the precise semantics of the form. |
C-c W | fi:lisp-macroexpand-recursively
if fi:legacy-keybindings is t,
no binding otherwise
|
|
C-c w | fi:lisp-macroexpand-recursively
if fi:legacy-keybindings is t,
no binding otherwise
|
|
ESC W | fi:lisp-macroexpand-recursively
if fi:legacy-keybindings is t,
no binding otherwise
|
The following table contains the remainder of the Lisp querying functions.
key(s) | binding | description |
---|---|---|
C-c C-a C-c A C-c a ESC A |
fi:lisp-arglist | Show the argument Lisp for the symbol at the point. See fi:arglist-on-space and fi:auto-arglist-pop-up-style. |
C-c i | fi:insert-arglist | insert the argument list template into a function call. |
C-c ? | fi:lisp-apropos | Run apropos in the Lisp on a symbol read from the minibuffer and display the results. |
C-c D ESC D C-c d |
fi:describe-symbol bound if fi:legacy-keybindings is non-nil |
Run describe in the Lisp on a symbol read from the minibuffer and display the results. |
C-c C-f C-c F C-c f ESC F |
fi:lisp-function-documentation | Show the documentation for a symbol read from the minibuffer. |
C-c C-z C-c C C-c c ESC C |
fi:lisp-who-calls | Show the callers of a function, the symbol for which is read from the minibuffer. |
C-c C-t | fi:trace-definer | Toggle tracing for the function defined by the top-level form around the cursor position. The form can be a defun, defgeneric, defmethod, define-compiler-macro, or deftype. The defmethod case is most useful, as the function spec for the particular method is extracted from the qualifiers and specializers. If tracing is already turned on, then it will be turned off. With a prefix arg, cause the debugger to be invoked via a call to break when the function is called. |
C-c C-t C-c T C-c t ESC T |
fi:toggle-trace-definition | Toggle tracing of a function, the symbol for which is read from the minibuffer. If tracing is already turned on, then it will be turned off. |
C-c TAB ESC TAB |
fi:lisp-complete-symbol |
Dynamically comple the symbol at the point using information in the
Lisp environment. This means that you may define a function or
variable in Common Lisp, go into Common Lisp source buffer, and
complete the name. Each time completion is done it looks up the
possible completions, dynamically, and does not use a static
table. Abbreviations are also expanded. For example, in the initial `user' package, which inherits symbols from the `common-lisp' package, `m-p-d-` will expand to `most-positive-double-float`. The hyphen (`-`) is a separator that causes the sub-string before the hyphen to be matched at the beginning of words in target symbols. |
C-c C-y C-c k |
fi:kill-definition | Insert a form to kill, or un-define, the definition that starts at the point. The un-defining form is inserted after the form to un-define. With prefix argument then actually un-define the form in the Common Lisp environment instead of inserted the un-defining form. |
C-c . |
fi:lisp-find-definition | Find the definition of the symbol at the point using information in the Lisp environment. With prefix argument, find the next occurance of the last definition. The current or other window is used, depending on which key is used. |
C-c 4 . | fi:lisp-find-definition-other-window | |
C-c , | fi:lisp-find-next-definition | Continue last definition search, started by fi:lisp-find-definition. |
C-c * | fi:pop-definition-mark | Pop back to where the find definition was last invoked. |
For more information on the group of functions for finding definitions of objects defined in the Common Lisp environment, see the documents source-file-recording.html and cross-reference.html for information on this. In short, you will need to set the Common Lisp special variables *record-source-file-info* and *record-xref-info* to non-nil
values before loading any files into Common Lisp.
fi:common-lisp-mode
fi:center-defun
fi:beginning-of-defun
fi:next-top-level-form
fi:previous-top-level-form
fi:lisp-semicolon
fi:comment-region
fi:uncomment-region
fi:end-of-defun
fi:extract-list
fi:indent-sexp
fi:lisp-apropos
fi:lisp-arglist
fi:insert-arglist
fi:arglist-lisp-space
fi:arglist-on-space
fi:auto-arglist-pop-up-style
fi:lisp-complete-symbol
fi:describe-symbol
fi:lisp-evals-always-compile
fi:lisp-eval-current-buffer
fi:lisp-eval-or-compile-current-buffer
fi:lisp-eval-defun
fi:lisp-compile-current-buffer
fi:lisp-compile-defun
fi:lisp-eval-or-compile-defun
fi:lisp-eval-last-sexp
fi:lisp-compile-last-sexp
fi:lisp-eval-or-compile-last-sexp
fi:lisp-eval-region
fi:lisp-compile-region
fi:lisp-eval-or-compile-region
fi:lisp-find-definition
fi:lisp-find-definition-other-window
fi:lisp-find-next-definition
fi:pop-definition-mark
fi:lisp-function-documentation
fi:lisp-indent-line
fi:lisp-macroexpand
fi:lisp-macroexpand-recursively
fi:lisp-mode-auto-indent
fi:lisp-mode-newline
fi:log-functional-change
fi:super-paren
fi:trace-definition
fi:toggle-trace-definition
fi:trace-definer
fi:definition-mode
fi:inverse-definition-mode
fi:maintain-definition-stack
fi:compare-source-files
fi:list-buffer-definitions
fi:list-undefined-functions
fi:list-unused-functions
fi:definition-mode-goto-definition
fi:definition-mode-goto-next
fi:definition-mode-goto-previous
fi:definition-mode-quit
fi:definition-mode-undo
fi:definition-mode-toggle-trace
fi:inverse-definition-mode-quit
fi:inverse-definition-who-calls
The Emacs-Lisp interface is a rich programming environment for the construction and debugging of Common Lisp programs. The debugging aids are classified into several categories. In Emacs:
In addition to the interface from Emacs to debugging programs, Allegro CL provides a rich set of tools to debug programs (see debugging.html). Functions in Allegro CL which are implemented with the help of the Emacs-Lisp interface are the top-level command :edit and the function common-lisp:ed - both allow the source code for a particular function to be edited. The editing operation is initiated from Emacs, but the action is performed by Allegro CL. :edit edits the function associated with the current stack frame and common-lisp:ed allow the editing of arbitrary functions or functions associated with symbols or function specs. For example, a call to lisp:ed returns a value immediately
USER(1): (ed 'frob)
<mp:process Metdot Session 0 @ #x90e7a6>
USER(2):
but causes a buffer to be created and made visible in Emacs displaying the definition of frob.
See:
fi:auto-fill
fi:check-unbalanced-parentheses-when-saving
fi:common-lisp-file-types
fi:compile-file
fi:echo-evals-from-buffer-in-listener-p
fi:fill-paragraph
fi:find-tag-lock
fi:find-unbalanced-parenthesis
fi:indent-code-rigidly
fi:indent-methods-case-sensitive
fi:lisp-package
fi:kill-definition
fi:lisp-do-indentation
fi:lisp-electric-semicolon
fi:load-file
fi:parse-mode-line-and-package
fi:pop-to-sublisp-buffer-after-lisp-eval
An important programming aid is being able to easily locate the source for functions. Sometimes the name of a function is not entirely known, so substrings or regular expressions need to be used to locate possible definitions.
Additionally, Emacs provides a tags facility, which does precisely what is described above, except it uses a static database created by the program etags. This is, obviously, of limited value since as the database becomes out of date the ability to find definitions diminishes.
The approach taken in this interface is to use the information present in the Common Lisp environment, and, if that lookup fails, to use the Emacs tags mechanism.
The information that is saved in the Common Lisp environment when files are loaded into Common Lisp uses the Source-file recording facility of Allegro CL, which is described in source-file-recording.html. Source-file information will be recorded and loaded if the values of the Common Lisp variables *record-source-file-info* and *load-source-file-info* are non-nil.
During the course of debugging or programming, it is useful to have access to the wealth of information present in the Common Lisp environment. The arglist of a function, for example, is useful when composing a call to a particular function, but only if it is inexpensive to look it up.
The following functions are specifically available in Common Lisp editing mode because they are bound to a key sequence:
key action
--- -------
C-c ? LISP:APROPOS on a string or regular expression
C-c a print the arglist of a function
C-c c list the who calls a function
C-c d LISP:DESCRIBE a symbol
C-c f print the function documentation of a symbol
C-c m macroexpand the form at the point
C-c w recursively macroexpand the form at the point
C-c TAB present completions of a partially named symbol
C-c . find the source for a function
C-c 4 . find the source for a function, in the other window
C-c , find the next definition, when there is more than one
C-c * pop back to the window context of the previous match
Table of Bindings for Retrieving information from the Common
Lisp environment
in addition to the above functions bound to key sequences, the following functions are available as extended commands:
fi:edit-who-calls
Edit all the callers of a function.
fi:list-who-is-called-by
fi:edit-who-is-called-by
List or edit all the functions that are called by a
function.
fi:list-generic-function-methods
fi:edit-generic-function-methods
List or edit all the methods of a generic function.
fi:describe-class
fi:describe-function
Describe a named class or function.
fi:list-undefined-functions
List the functions which are called but not defined.
List
means to display the names in definition mode, which allows for easily finding the source associated with a definition. See the description of fi:definition-mode Edit
means to find the source associated with a definition, making the additional definitions available via C-c ,
.
Many of the above commands create a buffer named CL-temp to display the information they retrieve from the Lisp environment. After viewing the contents of this buffer, you may restore the arrangement of windows, as they were before the CL-temp buffer was made visible, by invoking the function fi:lisp-delete-pop-up-window. The keybinding C-c SPC will run this function.
fi:lisp-delete-pop-up-window
fi:pop-up-temp-window-behavior
fi:list-who-calls
fi:list-who-is-called-by
fi:edit-who-calls
fi:edit-who-is-called-by
fi:list-generic-function-methods
fi:edit-generic-function-methods
fi:describe-class
fi:describe-function
In the course of programming it is often necessary to make changes in the Common Lisp environment. Being able to do this without having to actually type commands to a Common Lisp prompt can be valuable, especially when there would be a good deal of typing involved.
The following functions are specifically available in Common Lisp editing mode because they are bound to a key sequence:
key action
--- -------
C-c C-r evaluate the region
C-c C-s evaluate the last s-expression
C-c C-b evaluate the entire current buffer
ESC C-x evaluate the current top-level form
ESC T toggle tracing a function, optionally break on entry
Table of Bindings to modify the Common Lisp environment
Additionally, the above commands to evaluation will compile the expressions sent to Common Lisp if a prefix argument is given to the command.
The commands to evaluate portions of Emacs buffers are useful, but require the programmer to indicate which portions of the buffer are evaluated. Sometimes the act of making changes to source code is deeper than just fixing one or two functions. The following functions, available as extended commands (M-x) help ease the demand on remembering what changes have been made or having to recompile more than is necessary, which can be time consuming in a large system:
fi:list-buffer-changed-definitions
fi:list-changed-definitions
List the definitions that have been added, deleted or modified in the current buffer or in all buffers visiting Common Lisp source code (in mode fi:common-lisp-mode). Listing the definitions creates a buffer showing one-line descriptions of the definitions, in fi:definition-mode. Each line contains a
name' and
type'. The current list of types are:
key(s) | binding | description |
---|---|---|
C-c C-a | fi:lisp-arglist | Show the argument Lisp for the symbol at the point. See fi:arglist-on-space and fi:auto-arglist-pop-up-style. |
C-c i | fi:insert-arglist | insert the argument list template into a function call. |
C-c A | fi:lisp-arglist bound if fi:legacy-keybindings is non-nil |
|
C-c a | ||
ESC A | ||
SPC | fi:arglist-lisp-space no binding if fi:arglist-on-space is nil. |
Cause the arglist to be automatically shown for symbols as you type. |
C-c ? | fi:lisp-apropos | Run apropos in the Lisp on a symbol read from the minibuffer and display the results. |
C-c D | fi:describe-symbol bound if fi:legacy-keybindings is non-nil |
Run describe in the Lisp on a symbol read from the minibuffer and display the results. |
C-c d | ||
ESC D | ||
C-c C-f | fi:lisp-function-documentation | Show the documentation for a symbol read from the minibuffer. |
C-c F | fi:lisp-function-documentation bound if fi:legacy-keybindings is non-nil |
|
C-c f | ||
ESC F | ||
C-c C-z | fi:lisp-who-calls | Show the callers of a function, the symbol for which is read from the minibuffer. |
C-c C | fi:lisp-who-calls bound if fi:legacy-keybindings is non-nil |
|
C-c c | ||
ESC C | ||
C-c C-t | fi:trace-definer if fi:legacy-keybindings is non-nil |
Toggle tracing for the function defined by the top-level form around the cursor position. The form can be a defun, defgeneric, defmethod, define-compiler-macro, or deftype. The defmethod case is most useful, as the function spec for the particular method is extracted from the qualifiers and specializers. If tracing is already turned on, then it will be turned off. With a prefix arg, cause the debugger to be invoked via a call to break when the function is called. |
C-c C-t | fi:toggle-trace-definition if fi:legacy-keybindings is nil |
Toggle tracing of a function, the symbol for which is read from the minibuffer. If tracing is already turned on, then it will be turned off. |
C-c T | fi:toggle-trace-definition bound if fi:legacy-keybindings is non-nil |
|
C-c t | ||
ESC T | ||
C-c TAB
ESC TAB | fi:lisp-complete-symbol | Dynamically comple the symbol at the
point using information in the Lisp environment. This means that you may define a function or variable in
Common Lisp, go into Common Lisp source buffer, and complete the name. Each time completion is done it looks up the possible
completions, dynamically, and does not use a static table.
Abbreviations are also expanded. For example, in the initial `user' package, which inherits symbols from the `common-lisp' package, ``m-p-d-'' will expand to ``most-positive-double-float''. The hyphen (-) is a separator that causes the sub-string before the hyphen to be matched at the beginning of words in target symbols. |
C-c C-y | fi:kill-definition | Insert a form to kill, or un-define, the definition that starts at the point. The un-defining form is inserted after the form to un-define. With prefix argument then actually un-define the form in the Common Lisp environment instead of inserted the un-defining form. |
C-c k | fi:kill-definition
bound if fi:legacy-keybindings is non- nil |
|
C-c . | fi:lisp-find-definition | Find the definition of the symbol at the point using information in the Lisp environment. With prefix argument, find the next occurance of the last definition. The current or other window is used, depending on which key is used. No mark is set in the definition file by this command. |
C-c 4 . | fi:lisp-find-definition-other-window | |
C-c , | fi:lisp-find-next-definition | Continue last definition search, started by fi:lisp-find-definition. |
C-c * | fi:pop-definition-mark | Pop back to where the find definition was last invoked. |
TABLE # 12
:operator |
for functions, methods, generic functions and macros |
:type |
for classes (types) |
:setf-method |
for setf methods |
:variable |
for constants and variables |
fi:eval-buffer-changed-definitions
fi:eval-changed-definitions
fi:compile-buffer-changed-definitions
fi:compile-changed-definitions
Evaluate each of the definitions that have been added or modified in the current buffer or in all buffers visiting Common Lisp source code. C-c , finds subsequent definitions, if there is more than one. This synchronizes the definitions of the currently in-core versions of files being edited by Emacs with Common Lisp. The last two functions compile the changed definitions in the Common Lisp environment, whereas the first two load the interpreted versions of the changed definitions.
fi:copy-buffer-changed-definitions
fi:copy-changed-definitions
Copy into the kill ring the definitions that have been added or modified in the current buffer or in all buffers visiting Common Lisp source code.
All the above functions take a prefix argument, since, which defaults to the value of the variable fi:change-definitions-since-default. The value of since causes the above functions to operate on the changes:
thus allowing fine control over which types of changed definitions are used listed, evaluated, compiled or yanked.
Useful in comparing two files of similar origin is fi:compare-source-files, which lists the definitions that have been added, deleted or modified between the two file name arguments read from the minibuffer, if called interactively.
Lastly, it is sometimes useful to remove or kill definitions in the Common Lisp environment. fi:kill-definition inserts after the defining form at the point a form which, when evaluated, will kill the definition. With a prefix argument, fi:kill-definition will, instead of inserting the killing form, evaluate the kill definition form in the Common Lisp environment.
Here is the definition of fi:change-definitions-since-default:
fi:change-definitions-since-default
All of these functions act on definitions which have changed since:
The since prefix argument controls the behavior. You can specify it explicitly (by C-u since M-x [function of interest]
where since is 1, 2, or 3), or accept the default, which is controlled by the variable fi:change-definitions-since-default
defined above. Its initial value is last-compile-or-eval
, which is equivalent to since = 1.
(fi:list-buffer-changed-definitions SINCE) List the definitions in the current buffer which have been added, deleted or changed. See the documentation for the variable fi:change-definitions-since-default for information on the behavior of SINCE. (fi:eval-buffer-changed-definitions SINCE) Eval the definitions in the current buffer which have been added or changed. See the documentation for the variable fi:change-definitions-since-default for information on the behavior of SINCE. (fi:eval-changed-definitions SINCE) Eval the definitions in all buffers which have been added or changed. See the documentation for the variable fi:change-definitions-since-default for information on the behavior of SINCE. (fi:compile-buffer-changed-definitions SINCE) Compile the definitions in the current buffer which have been added or changed. See the documentation for the variable fi:change-definitions-since-default for information on the behavior of SINCE. (fi:compile-changed-definitions SINCE) Compile the definitions in all buffers which have been added or changed. See the documentation for the variable fi:change-definitions-since-default for information on the behavior of SINCE. (fi:copy-buffer-changed-definitions SINCE) Copy into the kill ring the definitions in the current buffer which have been added or changed. See the documentation for the variable fi:change-definitions-since-default for information on the behavior of SINCE. (fi:copy-changed-definitions SINCE) Copy into the kill ring the definitions in all buffers which have been added or changed. See the documentation for the variable fi:change-definitions-since-default for information on the behavior of SINCE.
Without a window debugger, which presents a graphical view of the runtime stack, programmers debugging Common Lisp programs must resort to examining the stack with the debugger commands described in debugging.html. It is often the case, however, that much moving up and down the stack must be done to find the proper point of error. Scan stack mode allows a snapshot of the Common Lisp runtime stack to be taken, and for navigation through the stack to proceed in a Emacs buffer with a host of local commands to make this a painless experience.
Consider the following example, typed in the common-lisp buffer created by fi:common-lisp:
user(1): (defun foo (x) (bar x))
foo
user(2): (defun bar (x) (1+ x))
bar
user(3): (foo `foo)
Error: foo is an illegal argument to +
[1] user(4):
At this point, the problem can be debugged using :zoom, the offended function identified and fixed. A :zoom would look like:
[1] user(4): :zoom
Evaluation stack:
->(error "~s is an illegal argument to +" foo)
(excl::+_2op foo 1)
(1+ foo)
(bar foo)
(foo foo)
... more older frames ...
[1] user(5):
It is now desirable to move the current frame pointer down the stack to find the problem. The inconvenience here is that much output is generated moving around in the stack to find the frame which contains the useful information.
Scan stack mode makes the perusal of the stack much easier. At the point of error, if C-c s is typed, then the following question is asked, in the minibuffer:
Process to debug: Initial Lisp Listener
where the Initial Lisp Listener is the default input to the query. Unless a multiprocessing application is being run, then most errors occur in the initial process created when Common Lisp is run, which is called the Initial Lisp Listener. Typing RET to this query will cause a debugger buffer to be created and displayed. The buffer will be named *debugger:XXX where XXX is the pretty form of the process name of the Allegro Common Lisp process which is being debugged. For the example above, it will have the following contents:
Debugger commands:
C-cC-c :continue
C-cC-p :pop
C-cC-r :reset
. make frame under the point the current frame
D disassemble the function
R restart function (give prefix to specify different form)
a toggle visibility of all frames (by default a subset are visible)
d next line
e edit source corresponding to function
g revert stack from Lisp
h Causes this help text to become visible
l display the lexical variables
p pretty print
q switch back to "*common-lisp*" buffer
r return a value
u previous line
Type SPACE to hide this help summary.
Evaluation stack:
->(error "~s is an illegal argument to +" foo)
(excl::+_2op foo 1)
(1+ foo)
(bar foo)
(foo foo)
(eval (foo 'foo))
(apply #<Function top-level-read-eval-print-loop @ #x4854ce> nil)
(excl::start-reborn-lisp)
where the first section of the buffer is help text, which can be made to disappear by typing SPC. The commands in this mode can be grouped according to functionality:
|
|
|
|
|
|
|
fi:scan-stack
fi:scan-stack-mode
fi:scan-stack-mode-display-help
fi:ss-continue
fi:ss-disassemble
fi:ss-edit
fi:ss-hide-help-text
fi:ss-locals
fi:ss-next-frame
fi:ss-pop
fi:ss-pprint
fi:ss-previous-frame
fi:ss-quit
fi:ss-reset
fi:ss-restart
fi:ss-return
fi:ss-revert-stack
fi:ss-set-current
fi:ss-toggle-all
fi:ss-unhide-help-text
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
During the course of debugging multi-process applications, it is often useful to be able to type to an additional listener in the same Common Lisp. That is, within one UNIX Common Lisp process it is possible to run multiple threads, each executing different processes in the Common Lisp address space. The function fi:open-lisp-listener will open a Lisp listener on an existing Common Lisp process started with fi:common-lisp.
The following Allegro CL debugging commands are also useful in debugging multi-process applications:
The scan stack mode above is also useful for multi-process applications, however a process must be quiescent for fi:scan-stack-mode to be used on it. quiescent means the process must have called error or break and be in a read-eval-print loop waiting for debugging commands. The above process related top-level commands, however, can be used to stop running processes for examination.
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, fi:bug-report
, which will allow Franz Inc. to be sent a bug report with all the right information:
fi:bug-report
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:subprocess-enable-superkeys
. fi:superkey-shadow-universal-argument
controls how C-u behaves.fi:su-initial-input
, fi:telnet-initial-input
and fi:rlogin-initial-input
.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-new-user
fi:rlogin-mode
fi:rlogin-image-arguments
fi:rlogin-image-name
fi:rlogin-initial-input
fi:rlogin-prompt-pattern
fi:rlogin-send-eof
fi:rlogin-send-interrupt
fi:rlogin-send-quit
fi:rlogin-send-stop
This section and its subsections discuss advanced features of the Emacs-Lisp interface.
fi:define-emacs-lisp-mode
fi:emacs-lisp-mode
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 build-lisp-image in a relatively standard fashion.
Problems starting the Emacs-Lisp interface can arise, however, when starting images created with dumplisp called with a non-nil value specified for the :ignore-command-line-arguments keyword argument.
This will cause problems because of how the Emacs-Lisp interface is started, as we describe next.
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:
fi:common-lisp invokes a Common Lisp subprocess with the arguments -e (excl:new-start-emacs-lisp-interface :background-streams t)
followed by whatever other command-line arguments there are.
the buffer in which Common Lisp is run, common-lisp by default, has an Emacs Lisp filter that looks for strings of the form ^A<...>^A, that is something surrounded by ^A's.
when Common Lisp starts up, it evaluates the argument following the -e (actually it reads from the command line argument string and then evaluates).
the process filter sees the ^A<...>^A and extracts the following information from what appears in <...>:
the above information is used to setup the interface and establish a connection between Lisp and Emacs.
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.
If, because command-line arguments are ignored, the Emacs-Lisp interface does not start up (or if it does not start up for any other reason), you can start it directly from within Lisp by calling excl:new-start-emacs-lisp-interface. We remind you again that the image must have been started with fi:common-lisp for this to work.
Copyright (c) Franz Inc. Lafayette, CA., USA. All rights reserved.
|
Allegro CL version 11.0 |