\documentstyle [12pta]{article}
\textheight 9.0in
\textwidth 6.5in
\topmargin -1.0in
\oddsidemargin -0.05in
\baselineskip .2in

\begin{document}
\vspace*{0.1 in}
\begin{center}{\large Interfacing Lisp and Emacs}\\
\vspace*{0.3in}
Dennis G. Allard and Neil M. Goldman\\
USC Information Sciences Institute\\
4676 Admiralty Way\\
Marina del Rey, CA 90292\\
(310) 822-1511
\end{center}


\begin{abstract}
We have developed a facility to connect Common Lisp to Emacs and Epoch
text editors.  We have named the facility ELI, an acronym for An Emacs
to Lisp Interface.  ELI has several layers.  At its foundation is a
service for making {\em connections} among Lisp, Emacs, and other
{\em agents} on the Internet.  Above that is a
{\em remote procedure call} protocol which
allows agents to invoke functions in other agents synchronously or
asynchronously and optionally get back a return value.  On top of
these layers, we have implemented various facilities to interface
Emacs and Lisp agents, including ones to interact with Lisp process
threads via Emacs
buffers, to display active Lisp objects in Epoch buffers, and to
display the status of Lisp threads.
The connections between Emacs and Lisp agents can be many to many.
\end{abstract}


\section{Motivation}

Our computing environment, FSD\cite{FSD1,FSD2,FSD3}, was originally
implemented on Lisp machines\cite{Symbolics} and recently ported to
Unix platforms.  We ported to both Franz Lisp and Lucid Lisp and chose
Epoch, a well known extension to Emacs, as our
editor\cite{Lucid,Allegro,Epoch}.  This means that the editor no
longer resides in Lisp address space, posing the problem of how Lisp
and the editor are to communicate.  Our solution to this problem is
the subject of this paper.

ELI, an Emacs to Lisp Interface, provides functionality which in many
ways resembles the Lisp Machine environments.  Lisp threads can have
one or more of their i/o streams attached to Emacs buffers.  For
example, one or more {\em Lisp listener} buffers can be created to
interact with Lisp threads running read-eval-print loops.  As another
example, when a thread enters the debugger, interaction with the
debugger takes place in a distinct Emacs buffer, rather than being
interleaved with i/o from other threads in a Unix shell window.  A
form of hypertext is available where objects appear in buffers
as highlighted regions of text, implemented via Epoch {\em buttons}.
The buttons contain information about the
object they display, including a handle which allows Lisp and Epoch to
coordinate on how the object is displayed and what actions can be
performed on it.  For example, its color can vary dynamically
depending on the state of the object, and a menu of actions pertaining
to the object can be obtained by clicking on the button.

ELI has some advantages over the Lisp machine editor implementation.
First, the editor and Lisp can run on different host machines anywhere
on the Internet.  Second, we have arranged for a single editor to
connect simultaneously to different Lisps running on the same or
different machines.  Third, such connections can be made or broken
dynamically to facilitate temporary connections for the purposes of
debugging or for contacting existing address space from remote sites.
Fourth, connections can be many to many.  We have cases where
several Lisp and Emacs processes work together with different services or
databases being managed by different participants resulting in a form
of distributed computation.  Finally, the connection protocol has a
layer which is more general than merely an Emacs to Lisp connection
mechanism.  The full protocol enables a dynamic form of Remote
Procedure Call from Lisp or Emacs to arbitrary other processes which
have implemented the protocol.

\section{Overview}

ELI consists of several layers of abstraction, each partly implemented in
terms of one or more of the layers below it.  
\begin{verbatim}

               Process buffers             Hypertext

                            Stream buffers

                         Remote Procedure Call

                         Remote Agents Protocol

                       Network connection protocol
\end{verbatim}

Each layer involves code at both the Emacs and Lisp ends of
a connection.  In this section, we briefly describe each layer.  The
remaining sections describe each layer more fully.

Network connection protocol.  Protocol for connecting Lisp, Emacs and
other processes enabling them to send streams of bytes to each other.
This layer contains a simple API (Application Program Interface)
enabling Lisp to use TCP/IP connections via Unix sockets \cite{TAN}.

Remote Agents Protocol (RAP).  Provides {\em agent} and
{\em connection} abstractions for representing processes on a network
which communicate via network connections.  Agents and connections have
machine independent identities.  The API of this layer provides functionality
for creating connections between Lisp, Emacs, and other agents.

Remote Procedure Call (RPC).  A simple dynamic RPC mechanism \cite{TAN}.
Allows asynchrony in both procedure calling and value returning
mechanisms.  The API of this layer is useful for customizing ELI.

Stream buffers.
Functionality for dynamically connecting a Lisp stream to an Emacs
buffer, enabling a Lisp thread to do i/o via the buffer.  Lisp can
control buffer interaction modality by sending control information to
a filtering mechanism associated with the buffer.

Hypertext.  Use of Epoch buttons to display printed representations of
Lisp objects.  For example, a Lisp object can be shown as a colored
button having a distinct handle so that mousing it in Epoch can be
detected and responded to by Lisp.

Process buffers.  When a Lisp thread is spawned, the default behaviour
of ELI is to locally bind the special variable {\bf*terminal-io*} in
that process to a new stream buffer.  This enables interaction with
each Lisp thread to occur in a separate Emacs buffer while other
threads continue to execute.  Lisp listeners are implemented as
threads which simply run a function performing a read-eval-print loop.


\section{The Network connection protocol}

The Network connection protocol provides a very simple interface
to Unix sockets, enabling two processes to establish a TCP/IP
connection \cite{BSD1,TAN} with each other.  We define
here our API for this layer\footnote{We define our protocols via a
semiformal Lisp-like functional notation.}, mostly of interest to
socket programmers.  

The standard Unix client/server socket connection protocol involves
the notion of a {\em server} and a {\em client} process which
cooperate to create a {\em socket connection}.  Once created, each
process has identical capabilities for reading, writing, and closing
the connection.  {\bf serverlisten} and {\bf serveraccept} implement
the server side of our socket creation protocol.  {\bf clientconnect}
implements the client side.  We have implemented the client side in
Emacs Lisp and both sides in Common Lisp.  We omit specifying here
what happens in the case of errors.

\begin{verbatim}
Function: SERVERLISTEN(TRYPORT &optional (TRYS 10)) --> PORT
\end{verbatim}
Done once only by the server process.  {\bf tryport} and {\bf trys}
are positive integers.  Finds the first available port, an integer,
within {\bf trys} of {\bf tryport}.  Makes the port be a {\em
listening port} and returns it.  Note, our notion of listening port
replaces the standard Unix protocol use of a special mediating socket.
We felt that the mediating socket needlessly complicates the protocol.

\begin{verbatim}
Function: SERVERACCEPT(PORT) --> SOCKET
\end{verbatim}
{\em Accepts} a new connection requested by a client over {\bf port},
a listening port which was returned by {\bf serverlisten}.  Returns a
new socket which is {\em connected} to a client end socket.  This
function blocks until it succeeds or fails and will never time out.
Can only succeed if a client call to {\bf clientconnect} has occurred
or does occur.

\begin{verbatim}
Function: CLIENTCONNECT(HOSTNAME PORT) --> SOCKET
\end{verbatim}
Requests a connection over the listening port {\bf port} created by a
server on {\bf host}.  Returns a new socket {\em connected} to a
socket obtained in the server via {\bf serveraccept}.  Blocks until it
succeeds or fails and will never time out.  Can only succeed if a
server call to {\bf serveraccept} has occurred or does occur.

\begin{verbatim}
Function: SOCKET-TO-STREAM(SOCKET) --> STREAM
\end{verbatim}
Converts a socket to a stream type object in the embedding language
and returns the stream.  In many languages, such as C, sockets {\em
are} stream types.


\section{The Remote Agents Protocol (RAP)}

The RAP layer makes explicit the concept of {\em agent} and {\em
connection} and keeps track of the set of connections between agents.
In this section, we {\em drastically} summarize the essentials of RAP.

\subsection{What is an agent?}

An agent is a process which communicates over a
network with other processes.  It is possible that one agent may
wish to make one or more connections with another agent.
Examples of agents are editor servers and the applications they
communicate with, window servers, database servers, etc.  
Historically, the term {\em server} probably arises from an agent
performing a service, and the term {\em client} from an agent using the
service.  In many distributed applications the roles are often
symmetric.  Hence, we use the term {\em agent} to connote such
symmetry.

The raison d'etre for agents is distributed computation.
The natural justification for a process being an agent is that the
process provides a locus of functionality which is conveniently
encapsulated and interfaced to other agents via network
communication channels.  Pairwise peer to peer communication between
agents is a predominant topology and the only one thus far
supported by RAP.

Since an agent may have several threads which communicate
independently of one another with another agent or agents, we require
that an agent can make connections with one or more other agents and
be able to make more than one connection with each of them.  To
facilitate graceful closing of connections and recovery of broken
connections, we require a connection to have a persistent identifier
known to the agents at each end.  To allow an agent to exist across
machine reboots or relocate itself to a different machine, we require
that an agent have a unique persistent identifier.

\subsection{Agent representations}

An agent maintains a model of other agents with which it communicates
by maintaining a representation of the all agents to which a
connection has been made.  The represenation records an agent's id,
host machine, optional connection server port, the set of connections
which have been made to that agent, and user defined data.

\subsection{Creating agents and connections}

RAP defines a notion of a {\em connection dialog}.  There is a server
agent and a client agent involved in setting up a connection.  The
server must run a connection server thread.  Key functions of the RAP
protocol suite are the following.

\begin{verbatim}
Server Function: CONNECTION-SERVER(PASSWORD) --> HOST and PORT and THREAD
Server Function: NEWCLIENT(CID) --> UNDEFINED
Client Function: NEWSERVER(HOST PORT PASSWORD SN) --> CID
\end{verbatim}
{\bf connection-server} runs a connection server thread which accepts
requests for network connections from other agents on a port and
returns the host, port, and thread.

On the client side, a user defined wrapper calls {\bf newserver} to contact the
connection server and conduct a connection dialog with {\bf
newclient}, which is automatically invoked by the protocol mechanism
on the server side.  {\bf sn} is a {\em service number} which identifies a
user defined {\em service function}, called by {\bf newclient}.  {\bf
newclient} passes {\bf cid}, an integer {\em connection identifier}, to the
service function.  {\bf cid} is also returned by {\bf newserver}.  The
service function and the client wrapper complete the dialog.  The
protocol specifies that each agent will send its {\em agent id} to the
other.  The result of a successful dialog is that each agent creates
a represention of the other, an initial connection between the
agents is registered, and additional user defined processing may occur.

Other functions exist in RAP for creating further connections between
existing agents, for closing connections, and for getting rid of
agent representations.  The protocol has been designed to support cleanly
recovering from broken connections and, ultimately, to allow an agent
to relocate to a different machine.


\section{Remote Procedure Call}

Remote Procedure Call protocols are widely accepted as a
convenient level for accomplishing communication between processes over
a network channel\cite{TAN}.  We have built an RPC which runs over
a RAP connection, enabling one agent to execute a remote procedure
in another agent and get back a return value.  RPC has proved
very useful in ELI for communications between Lisp and Emacs.  In this
section, the term RPC will refer to our RPC protocol.

To use RPC, two agents cooperate to set up a special kind of RAP
connection, dubbed an RPC connection.  The RPC
connection is symmetric with respect to the agents.  Either agent
may invoke (i.e., call) a remote procedure on the other.  The calling
agent is dubbed the client and the called agent is dubbed the server
for the duration of an invocation.  The client side of an RPC
invocation consists of an operation identifier and arguments to the
operation, much as a function call in a programming language.  The
client may either block, waiting for a return result (synchronous RPC)
or not (asynchronous RPC).  In the asynchronous case, the client may
optionally specify that a result should or should not be sent back by
the server.  If an answer is expected, provision is made to provide a
{\em response handler (callback?) function} to process the
answer in a separate process
thread if and when it comes back.  Reponses to asynchronous RPCs may
come back in an order different from the order of invocation.  There
is provision in the protocol for a special type of error response.

The protocol is simple but powerful, providing
a more dynamic form of RPC than typical RPC protocols for
Unix, allowing late binding of operators and runtime definitions of
remote operator signatures.
\subsection{Creating an RPC connection}

An RPC connection can be made by any two agents running RAP, where at
least one of the agents has established a connection server.  A
client/server distinction exists only for purposes of creating an RPC
connection.  Once, created, both agents have symmetrical status.

\begin{verbatim}
RAP Service Function: RPC-ACCEPT(CID) --> UNDEFINED
RAP Client Wrapper Function: RPC-CONNECT(AGENT SN) --> CID
\end{verbatim}

This sets up an RPC connection which can only be legitimately accessed 
by functions in the RPC suite.  {\bf sn} is similar to a RAP
level service number, identifying a user defined function which is
invoked by {\bf rpc-accept} to customize the server side of the new
connection.  The user defined wrapper which invokes {\bf rpc-connect}
is responsible for customizing the client side.  We have been drastic
in our summary of both RAP and RPC due to lack of space.  We have
omitted, among other things, a discussion of how user defined service
functions are associated with service numbers.

\subsection{Example of RPC usage}

We do not specify our RPC protocol here due to lack of
space and because we have currently only implemented a subset of it.
The full protocol enables dynamically declaring type signatures for remote
operators and binding local names to remote operators.  We have not
implemented those features.  In our current implementation, the client
agent (either Lisp or Emacs) sends the name of a function local to the
other agent and a list of arguments, which are restricted to be
integers, strings, or {\em cons} structures whose leaves are integers or
strings.  The other agent evaluates the function on those arguments
and optionally returns a value.  There can be asynchrony at either the
calling site or the returning site, or both.

We will illustrate the protocol with an example, stated in Lisp syntax,
quite similar to the actual RPC syntax in ELI.
Assume lisp agent, L, and Epoch agent, E, have created an RPC connection
and that E has a function
{\bf foo}, which takes
two string arguments, a buffer name and a prompt string.  {\bf foo}
creates a popup Epoch window, displays the prompt string in that window,
and reads a response from the user in the minibuffer, returning
the response as a string value.  We desire
that L be able to remotely invoke {\bf foo}.  L may synchronously
invoke {\bf foo} as follows.

\begin{verbatim}
(RPC-SYNCH E "foo" "Say something.")
\end{verbatim}
This causes E to evaluate ({\bf foo} "Say something.").  Suppose the
user responds by entering "Hello" into the minibuffer.  Then
the string "Hello" is returned in L by the {\bf rpc-synch} call.
L may invoke invoke {\bf foo} asynchronously, as follows.

\begin{verbatim}
(RPC-ASYNCH E H "foo" "Say something.")
\end{verbatim}
where H is a response handler function.  This call causes the same events to
transpire in E as before.  But in L, the function {\bf rpc-asynch} returns
a {\em query handle}, without waiting for the response from E to come
back.  If and when a value does come back, H is invoked in a separate
thread to deal with the value.  The query handle can be used by L to
preemptively remove H and inform E that a response is no longer
desired.  We do not detail here the protocols for defining a handler
or for preemptively removing one.

It is not necessarily the case that the value of {\bf foo} be the
return value of the rpc call.  In particular, the computation of the
return value may be done asynchronously with respect to the return
from {\bf foo}.  For example, {\bf foo} could put the prompt into a
queue which is consumed later by a different Emacs process and the
answer from the user returned at that time by that other process.
Such asynchronously sent responses from the server side are possible
for either synchronous or asynchronous client side rpc calls.  The
client side syntax is not affected but the server side definition of
{\bf foo} would be.  We will not detail this aspect of the protocol
here.

If a null value is given as the response handler, this means that no
value is to be returned.  Here is an example, where L tells E to
simply display a message in the minibuffer.

\begin{verbatim}
(RPC-ASYNCH E NIL "message" "Hello there.")
\end{verbatim}

\subsection{RPC Error handling}

The RPC protocol provides a simple error handling scheme.
An error to a synchronous RPC call looks much like a normal
error in a function call.  The server side of the protocol
implementation gathers as much error message together as is practical
from the server environment and packs it into a string for subsequent
use by the error handler in the client.  For synchronous RPC, instead
of {\bf rpc-synch} returning, an error is signalled and the gathered string
is delivered as an error indication in the debugger.  For asynchronous
RPC, the string is passed in to a user defined handler.

The problem is that there is no protocol defined way to continue a
remote computation which has signalled an error.  An idea for the
future would be to declare possible error types of a remote operator.
More generally, just as we intend to go with an XDR or other scheme
for type signatures on remote operators, we imagine it would be
straightforward to develop a minimal set of common error types valid
across machines.  In essence, we would use RPC to impose an error
handling scheme.  This would enable extending the protocol to react to
remote errors and attempt to handle those errors and continue the
remote computation.  So far, this is only speculation on our part.


\section{Stream Buffers}

The previous sections describe interagent communication facilities
which are largely application independent.  The remaining sections
explain how we have used these facilities to provide a remote editor
interface to Lisp.

Stream buffers enable a Lisp stream to do i/o through an Emacs
buffer.  The i/o goes over a RAP connection which appears at the Lisp
end as a Lisp stream and at the Emacs end as an Emacs buffer and an
associated Emacs process filter.

There are different interaction modalities possible with a
stream buffer, depending on what it is being used for.  A buffer
might be used to display immutable text, to issue a prompt and read
in a single line, to edit a block of text and update a database, etc.
Consequently, we provide for an Emacs buffer being in different
states and a way for a cooperating agent to control those states via
communication with an Emacs lisp process filter, which we call a {\em
stream filter}.

A stream filter is an Emacs Lisp function which filters output
to a buffer.  The filter intervenes between agent output to the
buffer and what actually gets displayed in the buffer.  The sending agent
interjects control information into the stream which controls the
filter in order to display buttons, switch buffer modes, change text
color, etc.  ELI comes with some canned filters and the programmer
can extend these or define new ones.

ELI defines new Emacs buffer modes for achieving specific styles of
interaction between an agent and a stream buffer.  Modes affect
keyboard bindings and what and when characters are transmitted from
Emacs to the agent.  There are modes for causing it to transmit
a character or a line at a time, causing it to
transmit only when the user explicitly enters a specific command to
do so, etc.  An agent can control what modes a stream
buffer is in by interleaving instructions in the text stream it
transmits to the stream buffer.


\subsection{Creating stream buffers}

Lisp drives the creation of stream buffers.

\begin{verbatim}
Lisp function: NEW-STREAM-BUFFER(AGENT BUFNAME INITIALIZER &rest INITARGS)
                                --> STREAM
\end{verbatim}
{\bf agent} must be an Emacs agent.  {\bf agent} sets up a buffer named
{\bf bufname} and creates a connection to that buffer.  A stream
perfoming i/o via that buffer is returned.
A buffer handle for the
buffer is also established in {\bf agent}.  The
Lisp stream is associated with the buffer handle to facilitate
eventual closing of the stream or destruction of the buffer.

{\bf initializer} is a string which names an Emacs Lisp function responsible
for initializing the stream buffer.  In Emacs, buffers have not only textual
content but a certain amount of state, e.g., a name, a mode, and
a collection of {\em buffer variable} bindings.  {\bf initializer} and
{\bf initargs} allow controlling that initial state.

\subsection{Stream filters}

The initializer function in Emacs which sets up the connection must
associate an Emacs Lisp filter function \cite{Emacs} with the new
stream buffer.  We have defined an Emacs Lisp function,
{\bf display-string}, which is useful as the heart of a such a filter.  It
permits the stream of characters being sent to the stream buffer to
contain {\em escape sequences} that are not simply copied into the buffer,
but cause the editor to take some useful action, such as changing the
buffer's mode or highlighting text for the end user's edification.

Rather than attempt to integrate all useful escape commands into a
single interpreter of the text stream, {\bf display-string} is implemented
as an extensible interpreter of that stream.  The implementation
defines an interface consisting of a recursively callable finite state
machine, having a distinguished predefined initial state.
An escape sequence can either cause the machine to change state or cause
a {\em utility function} to be invoked which has side effects, such
as modifying the stream buffer.
The user can define new states, new escape sequences, and new
utility functions.


\section{Hypertext}

When an interactive application prints information to the user
in a textual interace, e.g. a stream buffer, it may want to highlight
certain portions of the text either to focus the user's attention
or to actually encode information by the mode of highlighting chosen.
Epoch permits arbitrary contiguous regions of text in a buffer to
be mapped in any colors supported by the display hardware.  
Lisp applications make use of this capability by prefixing the
text with a control character sequence and color indicator and terminating
the sequence with another control character sequence.  The stream buffer's
filter interprets the control sequences to construct a highlighted region.
The text can itself contain other control commands for the
stream buffer, including further highlighting commands, so that nested
highlighted regions can be created.

For efficiency, the highlighting colors are transmitted as integer
references to logical color names.  The correspondence between integers and
logical colors is, in our applications, established by RPC calls between 
Lisp and Epoch at application startup.  The mapping between logical colors
and X-window color names is mediated by the X resource database, so that
application users can choose their own color schemes.

One capability that was present in windows of Symbolics Lisp machines
that we missed when we began developing code on Unix platforms was the
ability to {\em mouse} the printed representation of objects for
various purposes.  This is not only of interest in Lisp software
development, but can enhance user interfaces that are primarily text
oriented.  As an easy enhancement to the highlighting protocol, the
control sequence for a highlighted region was given an
{\em object handle}.  When a Lisp application wants to write such a {\em
hypertext object} into a stream buffer, it assigns a handle to the
object.  Epoch records this handle with the highlighted region.  When
the user clicks the mouse on the highlighted region, an asynchronous
RPC is sent to Lisp, including the object handle, the mouse button,
and the stream buffer handle as parameters.  We use this facility for
providing pop-up menus and for using previously printed objects as
expressions in interactive input of Lisp commands.



\section{Process Buffers}

The default behaviour in ELI is that whenever a process is spawned,
{\bf *terminal-io*} in that process is bound to a freshly created
stream buffer.  This is only a default behavior, and can be overridden
in specific cases.  The other standard stream variables are bound to
synonym streams for this new stream. The buffer is named the same as
the process.

Buffers that serve as i/o streams for asynchronously running
processes, like Lisp, have two concerns that other buffers do not.
First, where should output from the process to the buffer be inserted?
Second, when and what text from the buffer should be transmitted to
the process?  The answer to the first question is determined by the
filter function for the buffer.  The answer to the second is
determined by the mode of the buffer, since the mode can change which
key or keys will be bound to Emacs Lisp functions that transmit text
back to Lisp.

In order to define these characteristics, each stream buffer
keeps track of the point of last output (the location of the last
character transmitted into the buffer from the process).

For a stream buffer that is used for a user to do input to an agent
thread, no single mode may be ideal for the entire duration of the
thread.  So we transmit escape sequences in the output to these
buffers which are mode changing commands interpreted by their stream
filters.  We have defined the following communication modes for
use by such filters.  It is easy to define new ones.

{\bf Explicit} mode provides a distinct keystroke (currently,
{\em meta-return}) for transmitting all text between point of last
output and end-of-buffer.  No text is transmitted by any of the
standard Emacs editing commands.  This is the default mode for a new
process buffer.

{\bf Char} mode makes every keystroke transmit a character.  The
character is {\em not} inserted into the buffer on transmission.  It
is up to the Lisp process to echo the character if it wants the user
to see it.

{\bf Response} mode is like {\bf explicit} mode except that special
markers, which can be repositionned by the Lisp process, delimit what
characters gets transmitted.

{\bf Line} mode is like {\bf explicit} mode except
that {\em return}, as well as
{\em meta-return} causes transmission.  In other words, this is for
line at a time input.

{\bf Listener} mode binds {\em return} as a transmit key,
conditionalized to transmit if point is at the end of buffer, modulo
trailing whitespace, and follows a well formed Lisp expression.  The
Lisp expression is transmitted.  We have effectively dealt with type
ahead issues in listeners such that if the user types while output
is appearing, what the user types is kept together at the bottom of
the buffer.

\subsection{Lisp listeners}
We implement Lisp listeners by spawning a process which runs a
read-eval-print loop and setting its stream buffer to {\bf listener}
mode.  There is a {\em focussed listener}.  In any buffer of any mode,
including nonstream buffers,
the binding of {\em meta-return}, unless otherwise specified
by the mode, is always to copy whatever Lisp expression lies before
point to the end of the focussed listener and simulate entering a
return there.


\subsection{The Process Notification buffer}

As part of the user interface to stream buffers, there is a dedicated
buffer called the {\em active streams buffer}, which is not itself
a stream buffer.
Each time output becomes available in one of the buffers,
a green Epoch button containing the name of the buffer is placed in the
active streams buffer.  Clicking on the button containing the buffer
named B causes B to be made current in an Emacs window.

When a Lisp thread terminates which has a buffer assigned as the
interface to the standard streams, Lisp closes the stream and forgets
its association between the stream and the {\em buffer handle}.  It
also notifies Emacs that the connection may be dropped.  In Emacs we
look in the active streams buffer to see if there is a button for the
buffer.  If there isn't one, we assume the user has seen all output in
that buffer, so we kill the buffer.  The purpose of this is to avoid
the buildup of large numbers of buffers over time.  However, the
content of the buffer is not lost.  It is appended to a dedicated
buffer called the {\em transcript buffer}.  The appended contents is
preceded by the line
\begin{verbatim}
     ====== <process name> ======
\end{verbatim}
so you can see in this buffer the i/o transcript of each process that has
completed.
The content of this buffer is ordered by time of process completion.
Since the execution of some of these processes may have interleaved in
time, you cannot infer the overall temporal order of i/o from this
buffer.

If there is a button for the buffer in the active streams buffer, the
buffer is not killed, since the user may not have seen some output
available there.  Instead, an Epoch button is added at the end of the
buffer which says:
\begin{verbatim}
  Click here to free this buffer.
\end{verbatim}
The user must click on this button to kill the buffer.  Doing so also
performs the copy to the transcript buffer.  The button for the
terminated process in the active streams buffer turns into a ghost
like grey color.

Futher color coding is used to indicate the state of processes via
their buttons in the active streams buffer.  The default for a process
requesting input is red.

\section{Other tools implemented in ELI}
We easily implemented functionality to display an argument list by
appending it to the end of a dedicated buffer, *arglists* and
temporarily displaying it in the minibuffer.  We have extensive
experience using ELI to interface FSD to Epoch for displaying and
editing database objects, including source text of program objects.
In one experiment, we interfaced FSD to an E-L artifacts server,
implemented in Epoch \cite{E-L}.

\begin{small}
\bibliographystyle{plain}
\bibliography{tex}
\end{small}
\end{document}
