wiki:HemlockUser/InteractingWithLisp

Version 1 (modified by rme, 6 years ago) (diff)

--

9 Interacting With Lisp

Lisp encourages highly interactive programming environments by requiring decisions about object type and function definition to be postponed until run time. Hemlock supports interactive programming in Lisp by providing incremental redefinition and environment examination commands. Hemlock also uses Unix TCP sockets to support multiple Lisp processes, each of which may be on any machine.

9.1 Eval Servers

Hemlock runs in the editor process and interacts with other Lisp processes called eval servers. A user's Lisp program normally runs in an eval server process. The separation between editor and eval server has several advantages:

  • The editor is protected from any bad things which may happen while debugging a Lisp program.
  • Editing may occur while running a Lisp program.
  • The eval server may be on a different machine, removing the load from the editing machine.
  • Multiple eval servers allow the use of several distinct Lisp environments.

Instead of providing an interface to a single Lisp environment, Hemlock coordinates multiple Lisp environments.

9.1.1 The Current Eval Server

Although Hemlock can be connected to several eval servers simultaneously, one eval server is designated as the current eval server. This is the eval server used to handle evaluation and compilation requests. Eval servers are referred to by name so that there is a convenient way to discriminate between servers when the editor is connected to more than one. The current eval server is normally globally specified, but it may also be shadowed locally in specific buffers.

Set Eval Server [Command]

Set Buffer Eval Server [Command]

Current Eval Server [Command]

Set Eval Server prompts for the name of an eval server and makes it the the current eval server. Set Buffer Eval Server is the same except that is sets the eval server for the current buffer only. Current Eval Server displays the name of the current eval server in the echo area, taking any buffer eval server into consideration. See also Set Compile Server.

9.1.2 Slaves

For now, all eval servers are slaves. A slave is a Lisp process that uses a typescript (see page 9.2) to run its top-level read-eval-print loop in a Hemlock buffer. We refer to the buffer that a slave uses for I/O as its interactive or slave buffer. The name of the interactive buffer is the same as the eval server's name.

Hemlock creates a background buffer for each eval server. The background buffer's name is Background name, where name is the name of the eval server. Slaves direct compiler warning output to the background buffer to avoid cluttering up the interactive buffer.

Hemlock locally sets Current Eval Server in interactive and background buffers to their associated slave. When in a slave or background buffer, eval server requests will go to the associated slave, regardless of the global value of Current Eval Server.

Select Slave (bound to C-M-c) [Command]

This command changes the current buffer to the current eval server's interactive buffer. If the current eval server is not a slave, then it beeps. If there is no current eval server, then this creates a slave (see section 9.1.3). If a prefix argument is supplied, then this creates a new slave regardless of whether there is a current eval server. This command is the standard way to create a slave.

The slave buffer is a typescript (see page 9.2) the slave uses for its top-level read-eval-print loop.

Select Background (bound to C-M-C) [Command]

This command changes the current buffer to the current eval server's background buffer. If there is no current eval server, then it beeps.

9.1.3 Slave Creation and Destruction

When Hemlock first starts up, there is no current eval server. If there is no a current eval server, commands that need to use the current eval server will create a slave as the current eval server.

If an eval server's Lisp process terminates, then we say the eval server is dead. Hemlock displays a message in the echo area, interactive, and background buffers whenever an eval server dies. If the user deletes an interactive or background buffer, the associated eval server effectively becomes impotent, but Hemlock does not try to kill the process. If a command attempts to use a dead eval server, then the command will beep and display a message.

Confirm Slave Creation (initial value t) [Variable]

If this variable is true, then Hemlock always prompts the user for confirmation before creating a slave.

Ask About Old Servers (initial value t) [Variable]

If this variable is true, and some slave already exists, Hemlock prompts the user for the name of an existing server when there is no current server, instead of creating a new one.

Editor Server Name [Command]

This command echos the editor server's name, the machine and port of the editor, which is suitable for use with the Lisp processes -slave switch. See section 9.10.

Accept Slave Connections [Command]

This command cause Hemlock to accept slave connections, and it displays the editor server's name, which is suitable for use with the Lisp processes -slave switch. See section 9.10. Supplying an argument causes this command to inhibit slave connections.

Slave Utility (initial value "/usr/misc/.lisp/bin/lisp") [Variable]

Slave Utility Switches (initial value ) [Variable]

A slave is started by running the program Slave Utility Name with arguments specified by the list of strings Slave Utility Switches. This is useful primarily when running customized Lisp systems. For example, setting Slave Utility Switches to ("-core" "my.core") will cause "/usr/hqb/my.core" to be used instead of the default core image.

The -slave switch and the editor name are always supplied as arguments, and should remain unspecified in Slave Utility Switches.

Kill Slave [Command]

Kill Slave and Buffers [Command]

Kill Slave prompts for a slave name, aborts any operations in the slave, tells the slave to quit, and shuts down the connection to the specified eval server. This makes no attempt to assure the eval server actually dies.

Kill Slave and Buffers is the same as Kill Slave, but it also deletes the interactive and background buffers.

9.1.4 Eval Server Operations

Hemlock handles requests for compilation or evaluation by queuing an operation on the current eval server. Any number of operations may be queued, but each eval server can only service one operation at a time. Information about the progress of operations is displayed in the echo area.

Abort Operations (bound to C-c a) [Command]

This command aborts all operations on the current eval server, either queued or in progress. Any operations already in the Aborted state will be flushed.

List Operations (bound to C-c l) [Command]

This command lists all operations which have not yet completed. Along with a description of the operation, the state and eval server is displayed. The following states are used:

Unsent
The operation is in local queue in the editor, and hasn't been sent yet.
Pending
The operation has been sent, but has not yet started execution.
Running
The operation is currently being processed.
Aborted
The operation has been aborted, but the eval server has not yet indicated termination.

9.2 Typescripts

Both slave buffers and background buffers are typescripts. The typescript protocol allows other processes to do stream-oriented interaction in a Hemlock buffer similar to that of a terminal. When there is a typescript in a buffer, the Typescript minor mode is present. Some of the commands described in this section are also used by Eval mode (page 9.9.2.)

Typescripts are simple to use. Hemlock inserts output from the process into the buffer. To give the process input, use normal editing to insert the input at the end of the buffer, and then type Return to confirm sending the input to the process.

Confirm Typescript Input [Command]

Unwedge Interactive Input Confirm (initial value t) [Variable]

This command sends text that has been inserted at the end of the current buffer to the process reading on the buffer's typescript. Before sending the text, Hemlock moves the point to the end of the buffer and inserts a newline.

Input may be edited as much as is desired before it is confirmed; the result of editing input after it has been confirmed is unpredictable. For this reason, it is desirable to postpone confirming of input until it is actually complete. The Indent New Line command is often useful for inserting newlines without confirming the input.

If the process reading on the buffer's typescript is not waiting for input, then the text is queued instead of being sent immediately. Any number of inputs may be typed ahead in this fashion. Hemlock makes sure that the inputs and outputs get interleaved correctly so that when all input has been read, the buffer looks the same as it would have if the input had not been typed ahead.

If the buffer's point is before the start of the input area, then various actions can occur. When set, Unwedge Interactive Input Confirm causes Hemlock to ask the user if it should fix the input buffer which typically results in ignoring any current input and refreshing the input area at the end of the buffer. This also has the effect of throwing the slave Lisp to top level, which aborts any pending operations or queued input. This is the only way to be sure the user is cleanly set up again after messing up the input region. When this is nil, Hemlock simply beeps and tells the user in the Echo Area that the input area is invalid.

Kill Interactive Input [Command]

This command kills any input that would have been confirmed by Return.

Next Interactive Input [Command]

Previous Interactive Input [Command]

Search Previous Interactive Input [Command]

Interactive History Length (initial value 10) [Variable]

Minimum Interactive Input Length (initial value 2) [Variable]

Hemlock maintains a history of interactive inputs. Next Interactive Input and Previous Interactive Input step forward and backward in the history, inserting the current entry in the buffer. The prefix argument is used as a repeat count.

Search Previous Interactive Input searches backward through the interactive history using the current input as a search string. Consecutive invocations repeat the previous search.

Interactive History Length determines the number of entries with which Hemlock creates the buffer-specific histories. Hemlock only adds an input region to the history if its number of characters exceeds Minimum Interactive Input Length.

Reenter Interactive Input [Command]

This copies to the end of the buffer the form to the left of the buffer's point. When the current region is active, this copies it instead. This is sometimes easier to use to get a previous input that is either so far back that it has fallen off the history or is visible and more readily yanked than gotten with successive invocations of the history commands.

Interactive Beginning of Line [Command]

This command is identical to Beginning of Line unless there is no prefix argument and the point is on the same line as the start of the current input; then it moves to the beginning of the input. This is useful since it skips over any prompt which may be present.

Input Wait Alarm (initial value :loud-message) [Variable]

Slave GC Alarm (initial value :message) [Variable]

Input Wait Alarm determines what action to take when a slave Lisp goes into an input wait on a typescript that isn't currently displayed in any window. Slave GC Alarm determines what action to take when a slave notifies that it is GC'ing.

The following are legal values:

:loud-message
Beep and display a message in the echo area indicating which buffer is waiting for input.
:message
Display a message, but don't beep.
nil
Don't do anything.

Typescript Slave BREAK (bound to Typescript: H-b) [Command]

Typescript Slave to Top Level (bound to Typescript: H-g) [Command]

Typescript Slave Status (bound to Typescript: H-s) [Command]

Some typescripts have associated information which these commands access allowing Hemlock to control the process which uses the typescript.

Typescript Slave BREAK puts the current process in a break loop so that you can be debug it. This is similar in effect to an interrupt signal (C or \ in the editor process).

Typescript Slave to Top Level causes the current process to throw to the top-level read-eval-print loop. This is similar in effect to a quit signal (\).

Typescript Slave Status causes the current process to print status information on error-output: ; Used 0:06:03, 3851 faults. In: SYSTEM:SERVE-EVENT The message displays the process run-time, the total number of page faults and the name of the currently running function. This command is useful for determining whether the slave is in an infinite loop, waiting for input, or whatever.

9.3 The Current Package

The current package is the package which Lisp interaction commands use. The current package is specified on a per-buffer basis, and defaults to "USER". If the current package does not exist in the eval server, then it is created. If evaluation is being done in the editor process and the current package doesn't exist, then the value of *package* is used. The current package is displayed in the modeline (see section 3.3.) Normally the package for each file is specified using the Package file option (see page 3.3.3.)

When in a slave buffer, the current package is controlled by the value of package in that Lisp process. Modeline display of the current package is inhibited in this case.

Set Buffer Package [Command]

This command prompts for the name of a package to make the local package in the current buffer. If the current buffer is a slave, background, or eval buffer, then this sets the current package in the associated eval server or editor Lisp. When in an interactive buffer, do not use in-package; use this command instead.

9.4 Compiling and Evaluating Lisp Code

These commands can greatly speed up the edit/debug cycle since they enable incremental reevaluation or recompilation of changed code, avoiding the need to compile and load an entire file.

Evaluate Expression (bound to M-Escape) [Command]

This command prompts for an expression and prints the result of its evaluation in the echo area. If an error happens during evaluation, the evaluation is simply aborted, instead of going into the debugger. This command doesn't return until the evaluation is complete.

Evaluate Defun (bound to C-x C-e) [Command]

Evaluate Region [Command]

Evaluate Buffer [Command]

These commands evaluate text out of the current buffer, reading the current defun, the region and the entire buffer, respectively. The result of the evaluation of each form is displayed in the echo area. If the region is active, then Evaluate Defun evaluates the current region, just like Evaluate Region.

Macroexpand Expression (bound to C-M) [Command]

This command shows the macroexpansion of the next expression in the null environment in a pop-up window. With an argument, it uses macroexpand instead of macroexpand-1.

Re-evaluate Defvar [Command]

This command is similar to Evaluate Defun. It is used for force the re-evaluation of a defvar init form. If the current top-level form is a defvar, then it does a makunbound on the variable, and evaluates the form.

Compile Defun (bound to C-x C-c) [Command] Compile Region [Command]

These commands compile the text in the current defun and the region, respectively. If the region is active, then Compile Defun compiles the current region, just like Compile Region.

Load File [Command] Load Pathname Defaults (initial value nil) [Variable]

This command prompts for a file and loads it into the current eval server using load. Load Pathname Defaults contains the default pathname for this command. This variable is set to the file loaded; if it is nil, then there is no default. This command also uses the Remote Compile File variable.

9.5 Compiling Files

These commands are used to compile source (".lisp") files, producing binary (".fasl") output files. Note that unlike the other compiling and evalating commands, this does not have the effect of placing the definitions in the environment; to do so, the binary file must be loaded.

Compile Buffer File (bound to C-x c) [Command]

Compile Buffer File Confirm (initial value t) [Variable]

This command asks for confirmation, then saves the current buffer (when modified) and compiles the associated file. The confirmation prompt indicates intent to save and compile or just compile. If the buffer wasn't modified, and a comparison of the write dates for the source and corresponding binary (".fasl") file suggests that recompilation is unnecessary, the confirmation also indicates this. A prefix argument overrides this test and forces recompilation. Since there is a complete log of output in the background buffer, the creation of the normal error output (".err") file is inhibited.

Setting Compile Buffer File Confirm to nil inhibits confirmation, except when the binary is up to date and a prefix argument is not supplied.

Compile File [Command]

This command prompts for a file and compiles that file, providing a convenient way to compile a file that isn't in any buffer. Unlike Compile Buffer File, this command doesn't do any consistency checks such as checking whether the source is in a modified buffer or the binary is up to date.

Compile Group [Command]

List Compile Group [Command]

Compile Group does a Save All Files and then compiles every ".lisp" file for which the corresponding ".fasl" file is older or nonexistent. The files are compiled in the order in which they appear in the group definition. A prefix argument forces compilation of all ".lisp" files.

List Compile Group lists any files that would be compiled by Compile Group. All Modified files are saved before checking to generate a consistent list.

Set Compile Server [Command]

Set Buffer Compile Server [Command]

Current Compile Server [Command]

These commands are analogous to Set Eval Server, Set Buffer Eval Server and Current Eval Server, but they determine the eval server used for file compilation requests. If the user specifies a compile server, then the file compilation commands send compilation requests to that server instead of the current eval server.

Having a separate compile server makes it easy to do compilations in the background while continuing to interact with your eval server and editor. The compile server can also run on a remote machine relieving your active development machine of the compilation effort.

Next Compiler Error (bound to H-n) [Command]

Previous Compiler Error (bound to H-p) [Command]

These commands provides a convenient way to inspect compiler errors. First it splits the current window if there is only one window present. Hemlock positions the current point in the first window at the erroneous source code for the next (or previous) error. Then in the second window, it displays the error beginning at the top of the window. Given an argument, this command skips that many errors.

Flush Compiler Error Information [Command]

This command relieves the current eval server of all infomation about errors encountered while compiling. This is convenient if you have been compiling a lot, but you were ignoring errors and warnings. You don't want to step through all the old errors, so you can use this command immediately before compiling a file whose errors you intend to edit.

Remote Compile File (initial value nil) [Variable]

When true, this variable causes file compilations to be done using the RFS remote file system mechanism by prepending "/../host" to the file being compiled. This allows the compile server to be run on a different machine, but requires that the source be world readable. If false, commands use source filenames directly. Do NOT use this to compile files in AFS.

9.6 Querying the Environment

These commands are useful for obtaining various random information from the Lisp environment.

Describe Function Call (bound to C-M-A) [Command]

Describe Symbol (bound to C-M-S) [Command]

Describe Function Call uses the current eval server to describe the symbol found at the head of the currently enclosing list, displaying the output in a pop-up window. Describe Symbol is the same except that it describes the symbol at or before the point. These commands are primarily useful for finding the documentation for functions and variables. If there is no currently valid eval server, then this command uses the editor Lisp's environment instead of trying to spawn a slave.

9.7 Editing Definitions

The Lisp compiler annotates each compiled function object with the source file that the function was originally defined from. The definition editing commands use this information to locate and edit the source for functions defined in the environment.

Edit Definition [Command]

Goto Definition (bound to C-M-F) [Command]

Edit Command Definition [Command]

Edit Definition prompts for the name of a function, and then uses the current eval server to find out in which file the function is defined. If something other than defun or defmacro defined the function, then this simply reads in the file, without trying to find its definition point within the file. If the function is uncompiled, then this looks for it in the current buffer. If there is no currently valid eval server, then this command uses the editor Lisp's environment instead of trying to spawn a slave.

Goto Definition edits the definition of the symbol at the beginning of the current list.

Edit Command Definition edits the definition of a Hemlock command. By default, this command does a keyword prompt for the command name (as in an extended command). If a prefix argument is specified, then instead prompt for a key and edit the definition of the command bound to that key.

Add Definition Directory Translation [Command]

Delete Definition Directory Translation [Command]

The defining file is recorded as an absolute pathname. The definition editing commands have a directory translation mechanism that allow the sources to be found when they are not in the location where compilation was originally done. Add Definition Directory Translation prompts for two directory namestrings and causes the first to be mapped to the second. Longer (more specific) directory specifications are matched before shorter (more general) ones.

Delete Definition Directory Translation prompts for a directory namestring and deletes it from the directory translation table.

Editor Definition Info (initial value nil) [Variable]

When this variable is true, the editor Lisp is used to determine definition editing information, otherwise the current eval server is used. This variable is true in Eval and Editor modes.

9.8 Debugging

These commands manipulate the slave when it is in the debugger and provide source editing based on the debugger's current frame. These all affect the Current Eval Server.

9.8.1 Changing Frames

Debug Down (bound to C-M-H-d) [Command]

This command moves down one debugger frame.

Debug Up (bound to C-M-H-u) [Command]

This command moves up one debugger frame.

Debug Top (bound to C-M-H-t) [Command]

This command moves to the top of the debugging stack.

Debug Bottom (bound to C-M-H-b) [Command]

This command moves to the bottom of the debugging stack.

Debug Frame (bound to C-M-H-f) [Command]

This command moves to the absolute debugger frame number indicated by the prefix argument.

9.8.2 Getting out of the Debugger

Debug Quit (bound to C-M-H-q) [Command]

This command throws to top level out of the debugger in the Current Eval Server.

Debug Go (bound to C-M-H-g) [Command]

This command tries the continue restart in the Current Eval Server.

Debug Abort (bound to C-M-H-a) [Command]

This command executes the ABORT restart in the Current Eval Server.

Debug Restart (bound to C-M-H-r) [Command]

This command executes the restart indicated by the prefix argument in the Current Eval Server. The debugger enumerates the restart cases upon entering it.

9.8.3 Getting Information

Debug Help (bound to C-M-H-h) [Command]

This command in prints the debugger's help text.

Debug Error (bound to C-M-H-e) [Command]

This command prints the error condition and restart cases displayed upon entering the debugger.

Debug Backtrace (bound to C-M-H-B) [Command]

This command executes the debugger's backtrace command.

Debug Print (bound to C-M-H-p) [Command]

This command prints the debugger's current frame in the same fashion as the frame motion commands.

Debug Verbose Print (bound to C-M-H-P) [Command]

This command prints the debugger's current frame without elipsis.

Debug Source (bound to C-M-H-s) [Command]

This command prints the source form for the debugger's current frame.

Debug Verbose Source [Command]

This command prints the source form for the debugger's current frame with surrounding forms for context.

Debug List Locals (bound to C-M-H-l) [Command]

This prints the local variables for the debugger's current frame.

9.8.4 Editing Sources

Debug Edit Source (bound to C-M-H-S) [Command]

This command attempts to place you at the source location of the debugger's current frame. Not all debugger frames represent function's that were compiled with the appropriate debug-info policy. This beeps with a message if it is unsuccessful.

9.8.5 Miscellaneous

Debug Flush Errors (bound to C-M-H-F) [Command]

This command toggles whether the debugger ignores errors or recursively enters itself.

9.9 Manipulating the Editor Process

When developing Hemlock customizations, it is useful to be able to manipulate the editor Lisp environment from Hemlock.

Editor Describe (bound to Home t, C-_ t) [Command]

This command prompts for an expression, and then evaluates and describes it in the editor process.

Room [Command]

Call the room function in the editor process, displaying information about allocated storage in a pop-up window.

Editor Load File [Command]

This command is analogous to Load File, but loads the file into the editor process.

9.9.1 Editor Mode

When Editor mode is on, alternate versions of the Lisp interaction commands are bound in place of the eval server based commands. These commands manipulate the editor process instead of the current eval server. Turning on editor mode in a buffer allows incremental development of code within the running editor.

Editor Mode [Command]

This command turns on Editor minor mode in the current buffer. If it is already on, it is turned off. Editor mode may also be turned on using the Mode file option (see page 3.3.3.)

Editor Compile Defun [Command]

Editor Compile Region [Command]

Editor Evaluate Buffer [Command]

Editor Evaluate Defun [Command]

Editor Evaluate Region [Command]

Editor Macroexpand Expression (bound to Editor: C-M) [Command]

Editor Re-evaluate Defvar [Command]

Editor Describe Function Call [Command]

Editor Describe Symbol [Command]

These commands are similar to the standard commands, but modify or examine the Lisp process that Hemlock is running in. Terminal I/O is done on the initial window for the editor's Lisp process. Output is directed to a pop-up window or the editor's window instead of to the background buffer.

Editor Compile Buffer File [Command]

Editor Compile File [Command]

Editor Compile Group [Command]

In addition to compiling in the editor process, these commands differ from the eval server versions in that they direct output to the the Compiler Warnings buffer.

Editor Evaluate Expression [Command]

This command prompts for an expression and evaluates it in the editor process. The results of the evaluation are displayed in the echo area.

9.9.2 Eval Mode

Eval mode is a minor mode that simulates a read eval print loop running within the editor process. Since Lisp program development is usually done in a separate eval server process (see page 9.1), Eval mode is used primarily for debugging code that must run in the editor process. Eval mode shares some commands with Typescript mode: see section 9.2.

Eval mode doesn't completely support terminal I/O: it binds standard-output to a stream that inserts into the buffer and standard-input to a stream that signals an error for all operations. Hemlock cannot correctly support the interactive evaluation of forms that read from the Eval interactive buffer.

Select Eval Buffer [Command]

This command changes to the Eval buffer, creating one if it doesn't already exist. The Eval buffer is created with Lisp as the major mode and Eval and Editor as minor modes.

Confirm Eval Input [Command]

This command evaluates all the forms between the end of the last output and the end of the buffer, inserting the results of their evaluation in the buffer. This beeps if the form is incomplete. Use Linefeed to insert line breaks in the middle of a form.

This command uses Unwedge Interactive Input Confirm in the same way Confirm Interactive Input does.

Abort Eval Input [Command]

This command moves the the end of the buffer and prompts, ignoring any input already typed in.

9.9.3 Error Handling

When an error happens inside of Hemlock, Hemlock will trap the error and display the error message in the echo area, possibly along with the "Internal error:" prefix. If you want to debug the error, type ?. This causes the prompt "Debug:" to appear in the echo area. The following commands are recognized:

d
Enter a break-loop so that you can use the Lisp debugger. Proceeding with "go" will reenter Hemlock and give the "Debug:" prompt again.
e
Display the original error message in a pop-up window.
b
Show a stack backtrace in a pop-up window.
q, Escape
Quit from this error to the nearest command loop.
r
Display a list of the restart cases and prompt for the number of a restart-case with which to continue. Restarting may result in prompting in the window in which Lisp started.

Only errors within the editor process are handled in this way. Errors during eval server operations are handled using normal terminal I/O on a typescript in the eval server's slave buffer or background buffer (see page 9.1.4). Errors due to interaction in a slave buffer will cause the debugger to be entered in the slave buffer.

9.10 Command Line Switches

Two command line switches control the initialization of editor and eval servers for a Lisp process:

-edit
This switch starts up Hemlock. If there is a non-switch command line word immediately following the program name, then the system interprets it as a file to edit. For example, given lisp file.txt -edit Lisp will go immediately into Hemlock finding the file file.txt.
-slave [name]
This switch causes the Lisp process to become a slave of the editor process name. An editor Lisp determines name when it allows connections from slaves. Once the editor chooses a name, it keeps the same name until the editor's Lisp process terminates. Since the editor can automatically create slaves on its own machine, this switch is useful primarily for creating slaves that run on a different machine. hqb's machine is ME.CS.CMU.EDU, and he wants want to run a slave on SLAVE.CS.CMU.EDU, then he should use the Accept Slave Connections command, telnet to the machine, and invoke Lisp supplying -slave and the editor's name. The command displays the editor's name.