[Openmcl-devel] ccl's swank-listener thingie
mevins at mac.com
Tue Jun 9 18:08:26 PDT 2009
In recent trunk revisions of Clozure CL, the IDE includes a relatively
unobtrusive new feature: it is possible to start a "swank-listener",
either on launch, or by clicking a "Start now" button in the
Preferences window. This is a new and experimental feature of the IDE.
It has existed just long enough now without causing plagues, fires,
and other disasters, that I'm now willing to describe its intended use.
The code is young, and there are a jillion ways it can go wrong. Don't
be surprised if it sneaks out with your Significant Other and sells
your car for money to buy weapons of mass destruction.
Anyhow, the intended use is:
1. Start the swank listener
2. Request a swank connection to a running CCL IDE
3. Shazam! SLIME is connected and working
Okay, so what? What's different from what SLIME has always done?
The main difference is that the CCL IDE in this case did not have
SLIME's swank server loaded when we asked for a connection. Instead,
the swank-listener code loads swank on demand and then completes the
Okay, why would we want to do that?
Well, we could build swank into the CCL IDE, of course. But the swank
protocol changes from time to time, and we were concerned that it
would be a pain for people if they had to use some particular special
version of SLIME just to interact with the CCL IDE.
Also, sometimes when you're building a Cocoa app in Lisp, you want to
be disciplined about what things you build into it, for reasons of
debugging sanity, or security, or whatever. So it seemed like it might
be useful to provide a way, during app development, to get a SLIME
connection to a Cocoa app that wouldn't normally have swank built into
So swank-listener is a means of asking a running CCL IDE for a SLIME/
swank connection, even when it doesn't have swank built into it.
So how does one use it?
I. Needed parts
There are two pieces that make this thing work (assuming it does work):
An Emacs Lisp file that handles the Emacs side of things.
A Common-Lisp file that handles the CCL side of things
II. How to use them
1. Modify your emacs startup so that swank-ccl-ide.el is loaded after
2. Start up the CCL IDE, and make sure the swank-listener is running.
When the swank listener is running, the value of gui::*ccl-swank-
listener-active-p* should be T, and the value of gui::*active-gui-
swank-listener-port* should be the port it's actually listening on.
The Preferences window for the CCL IDE has, in the General tab, a
couple of controls for the swank listener. Check the checkbox to make
the swank listener run the next time the IDE is launched. Type in a
port number (if you want to use something different from the default
4884). If you want to start the swank listener at once, click the
"Start now" button. The "Start now" button does not affect the
preference setting, by the way.
3. Make Emacs evaluate (request-ccl-load-swank). You can eval it in a
buffer, or bind it to a key, or whatever you wish.
If things are set up right, there will be a brief delay as the CCL IDE
compiles and loads the swank code, and then you should have a live
SLIME connection to the running CCL IDE. (When the swank code is
already compiled, connecting is very quick).
If you don't change any of the defaults, and if nothing else is using
the default ports, then the connection should work. If you change the
port that the swank-listener listens on, then you'll also need to
change the value of *ccl-swank-listener-port* in the elisp file. If
you want to change the port used for the SLIME/swank connection, pass
it as an argument to the request function. For example, if you want
the SLIME/swank connection to use port 5001, then call the emacs-lisp
request function like this:
(request-ccl-load-swank nil nil 5001)
Nil arguments cause the request to use the default values for those
III. What they do
When it starts up, the swank listener creates a thread that waits for
a connection on the swank-listener port (by default, 4884). If such a
connection occurs, the swank-listener tries to read a line of text
from it. If it gets a line of text, it assumes that it will be the
string "[emacs-ccl-swank-request]" followed by a port number, a colon,
and a filesystem path. The swank listener splits the port number and
path from the message. It looks to see if the path names an existing
file; if so, it loads that file and then attempts to load swank and
create a swank server on the supplied port number. If that all
succeeds, then the swank listener writes a message back to the
connected client, telling it the port number that swank is listening on.
On the Emacs side, calling (request-ccl-load-swank) opens a client
connection on localhost, on the *ccl-swank-listener-port*, and
attempts to write a line of text containing "[emacs-ccl-swank-
request]" followed by the port number and pathname specified in the
parameters to request-ccl-load-swank. By default, the port number is
the value of the SLIME variable slime-port, and the pathname is the
value returned by (swank-loader-path) (which is just the value of the
SLIME variable slime-path, with the string "swank-loader.lisp"
In other words, the emacs code tells CCL that it wants CCL to load the
swank code from the SLIME version that is currently loaded in Emacs,
and use it to start a swank server.
CCL either succeeds, and writes back to Emacs a message saying so, or
it fails, and writes back a message that says it failed, and its best
understanding of why it failed (which Emacs then displays as a
If CCL says it succeeded, then Emacs believes it, and tries to open a
normal SLIME connection on the port CCL told it. If all went well,
then a normal SLIME/swank session ensues.
There are a zillion ways for this to go wrong, and I'm pretty sure I
have not found and guarded against them all. If you decide to play
with this facility, and you find hideous bugs, feel free to report
them, and I'll do my best to fix the most hideous ones.
More information about the Openmcl-devel