[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