In article m2hcrb6xhw.fsf@bese.it, Marco Baringer mb@bese.it wrote:
"Bill Clementson" billclem@gmail.com writes:
Hi Rainer,
On 4/17/07, Rainer Joswig joswig@lisp.de wrote:
I'm a bit used to the behavior of MCL when it comes to Lisp buffers and listeners. Maybe SLIME developers know how to achieve a similar behavior or would like to provide something similar.
MCL allowed multiple Lisp text editor windows and listener windows. If there are multiple listeners one is the front most.
SLIME does allow you to have multiple REPL windows. When you do "M-x slime" multiple times, it will ask you whether you want to create an additional repl.
are you sure? i tried this today and multiple M-x slime will start multiple swank-servers in the lisp but you still only get one repl buffer (this looks a lot like a bug).
SLIME displays several forms evaluated from a text buffer in the REPL like this:
;;;; (+ 1 2) ... ;;;; (+ 1 2) ... ;;;; (+ 1 2) ...
The normal REPL interaction display would be like:
CL-USER> (+ 1 2) 3 CL-USER> (+ 1 2) 3 CL-USER> (+ 1 2) 3
Both ways look different. Why not use the latter for both interactions?
this would only make sense, imho, if evaling code in the buffers respected the repl's *package*, *readtable*, etc. and updated *, **, ***, +, ++, etc.
I reread a bit the MCL manual.
The command for evaluation is bound to Enter. You can press Enter when you are right after or before a form in the Lisp editor. If a region is marked, use the region.
MCL usually reads the form using the package of the Lisp buffer. If there is no package set, it uses the value of cl:*package* .
I guess it uses the readtable of the Listener.
The form is enqueued in the Listener, which also means that the execution will run in the process thread of the listener. In MCL you can let the listener work on a few enqueued forms, and continue to use the Lisp buffer (move around, edit, ...).
Normally the form is not printed, but the result will be printed in the Listener.
The variables *, **, ***, etc. are updated.
The standard output stream is also set to the listener and any output the code prints is by default going to the listener.
The standard-input is also set to the listener.
After the listener has finished executing the enqueued forms, the listener's mini-buffer shows 'Done' as a message.
There is a lot of trickery involved in MCL's editor code.
But the basic idea is for simple execution of code is:
* read the code from the editor using its package * execute the code in the environment of the top-most listener using its setting, streams, ...
Some Commands in MCL:
Enter Eval or Compile Current Sexp C-x C-c Eval or Compile Top Level Sexp C-x C-e Eval Current Sexp C-M Macro Expand (result printed to the top-level listener) C-x C-r Read Current Sexp (the result will be pretty printed in the top-level listener)
For me using a listener as output buffer makes a lot of sense.
But MCL is multithreaded. Maybe this is difficult to replicate with Emacs? Maybe some simplified version would be useful.
is this what you're suggesting? i'm not sure i like it, it's nice to have some code in the repl which tests a function and have recompiling that function not upset the state of the repl. however if we allowed multiple, independant, repls this wouldn't be such a problem.
Useful is then also a command to rotate between the various listeners (next, previous) and Lisp buffers (next, previous).
Advantages I see for MCL:
- With MCL you get the same REPL listener display if you evaluate forms from
the Lisp editor buffer (via RETURN) or if you use the REPL in the listener.
- Using the enter key (vs. Return) to evaluate code in the editor gets rid of one complex keystroke.
what's the complex key stroke you want t get rid of?
C-x C-e
Opinion: In a Lisp environment there should be direct keys for basic Lisp interaction commands. Entering code to the REPL for execution would be such a basic interaction. Others are indenting (Tab), entering a break loop, aborting, completion, ...
- One gets reusable interaction histories in the listener where form and result are displayed together.
do you use this with normal functions as well or just snippets of test code? if so how do you avoid being overwhelemed with slightly similar but different function/class/whatever definitions interspersed with 'interesting' code and results?
See above, I think normally (IIRC, one could set this with a variable) only the result gets printed in the Listener.
In the listener it worked a bit different. There the form is being copied to the current prompt. Typically I would scroll back in the history, place my cursor to some Lisp expression and press enter. Then the form gets copied to the prompt, gets executed and the result gets printed.
Is SLIME already providing something similar? Would others find this way of interaction between Lisp buffers and a REPL buffer useful?
I don't think SLIME provides this as a standard feature. However, I have a function that I use to do this. It sends to the repl buffer either the current highlighted region, or the sexp that is on/before the point, or the sexp that is on/after the point, or the top-level sexp (if the point is not on/before/after a paren). With a prefix arg, it will also press "Enter" in the repl so you don't have to press enter yourself. I frequently use the function when I'm doing presentations and want to step through code in a listener for the audience.
Here's the code with a sample binding of F9 (so use either F9 or C-u F9):
did bill's code do something similar to what you wanted?
I have to check that. I'll report later.