[slime-devel] Evaluate forms from within Lisp buffers and displaying the result in the REPL
Bill Clementson
billclem at gmail.com
Wed Apr 18 17:08:04 UTC 2007
Hi Rainer,
On 4/17/07, Rainer Joswig <joswig at 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.
> If the cursor is behind a Lisp form in a Lisp editor window,
> one can press Enter (or control-return)
> and the form will be enqueued into the REPL of the
> front most listener. Doing this in a listener, the form will
> be displayed at the prompt and enqueued in the listener's REPL.
> Pressing Enter only has the effect that the form and the result
> is shown in the listener. In the Editor window, nothing
> happens (no cursor moved, no character entered, no
> window focus changed).
>
> The listener REPL gets the forms from its queue and displays
> the form and the result at the end of the current buffer.
> This way you get interaction histories in the listener.
>
> Currently SLIME lets me evaluate a form in a text buffer and
> the form gets printed into the listener and the result gets
> printed in the mini-buffer. I can see then in the listener
> the history of evaluated forms, but not the history of results.
> Additionally the form will be printed with additional characters
> before and after.
>
> 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?
>
> 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.
> * One gets reusable interaction histories in the listener where form and result
> are displayed together.
>
>
> 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):
(defun slime-send-dwim (arg)
"Send the appropriate forms to CL to be evaluated."
(interactive "P")
(save-excursion
(cond
;;Region selected - evaluate region
((not (equal mark-active nil))
(copy-region-as-kill-nomark (mark) (point)))
;; At/before sexp - evaluate next sexp
((or (looking-at "\\s\(")
(save-excursion
(forward-char 1)
(looking-at "\\s\(")))
(forward-list 1)
(let ((end (point))
(beg (save-excursion
(backward-list 1)
(point))))
(copy-region-as-kill-nomark beg end)))
;; At/after sexp - evaluate last sexp
((or (looking-at "\\s\)")
(save-excursion
(backward-char 1)
(looking-at "\\s\)")))
(if (looking-at "\\s\)")
(forward-char 1))
(let ((end (point))
(beg (save-excursion
(backward-list 1)
(point))))
(copy-region-as-kill-nomark beg end)))
;; Default - evaluate enclosing top-level sexp
(t (progn
(while (ignore-errors (progn
(backward-up-list)
t)))
(forward-list 1)
(let ((end (point))
(beg (save-excursion
(backward-list 1)
(point))))
(copy-region-as-kill-nomark beg end)))))
(set-buffer (slime-output-buffer))
(unless (eq (current-buffer) (window-buffer))
(pop-to-buffer (current-buffer) t))
(goto-char (point-max))
(yank)
(if arg (progn
(slime-repl-return)
(other-window 1)))))
(define-key lisp-mode-map [f9] 'slime-send-dwim)
--
Bill Clementson
More information about the slime-devel
mailing list