Skip to content

Commit

Permalink
Rework the mechanism for legacy compatibility
Browse files Browse the repository at this point in the history
  • Loading branch information
akater committed Nov 25, 2020
1 parent a9aabb8 commit 78304a3
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 36 deletions.
57 changes: 33 additions & 24 deletions slime.el
Original file line number Diff line number Diff line change
Expand Up @@ -4058,30 +4058,39 @@ inserted in the current buffer."
(run-hooks 'slime-transcript-stop-hook)
(message "Evaluation aborted on %s." condition))))

(defun slime-eval-print (string)
"Eval STRING in Lisp; insert any output and the result at point."
(slime-eval-async `(swank:eval-and-grab-output ,string)
(lambda (result)
(cl-destructuring-bind (standard-output
value
error-output trace-output)
result
(push-mark)
(insert error-output trace-output standard-output
value)))))

(defun slime-eval-save (string)
"Evaluate STRING in Lisp and save the result in the kill ring."
(slime-eval-async `(swank:eval-and-grab-output ,string)
(lambda (result)
(cl-destructuring-bind (standard-output
value
error-output trace-output)
result
(let ((string (concat error-output trace-output standard-output
value)))
(kill-new string)
(message "Evaluation finished; pushed result to kill ring."))))))
(defconst slime-output-targets
'(common-lisp:values
common-lisp:*standard-output*
common-lisp:*trace-output*
common-lisp:*error-output*)
"Possible keys in the alist returned by Common Lisp function `swank:eval-and-grab-output'.")

(cl-defun slime-eval-print
(string &optional (targets-to-print '(common-lisp:*standard-output*
common-lisp:values)))
"Eval STRING in Lisp; insert standard output and the result at point.

Contents to be inserted may be specified via optional parameter `targets-to-print' which should be a (multi)subset of list `slime-output-targets'."
(cl-assert (null (cl-set-difference targets-to-print slime-output-targets)))
(slime-eval-async `(swank:eval-and-grab-output ,string ',targets-to-print)
(lambda (results-alist)
(push-mark)
(dolist (target targets-to-print)
(insert (cdr (assoc target results-alist)))))))

(cl-defun slime-eval-save
(string &optional (targets-to-save '(common-lisp:*standard-output*
common-lisp:values)))
"Evaluate STRING in Lisp and save the result in the kill ring.

Contents to be saved may be specified via optional parameter `targets-to-save' which should be a (multi)subset of list `slime-output-targets'."
(cl-assert (null (cl-set-difference targets-to-save slime-output-targets)))
(slime-eval-async `(swank:eval-and-grab-output ,string ',targets-to-save)
(lambda (results-alist)
(kill-new
(mapconcat (lambda (target) (cdr (assoc target results-alist)))
targets-to-save ""))
(message "Evaluation finished; pushed result to kill ring."))))

(defun slime-eval-describe (form)
"Evaluate FORM in Lisp and display the result in a new buffer."
Expand Down
44 changes: 32 additions & 12 deletions swank.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -1761,20 +1761,40 @@ Errors are trapped and invoke our debugger."
(finish-output)
(format-values-for-echo-area values)))))

(defslimefun eval-and-grab-output (string)
(defslimefun eval-and-grab-output
(string &optional (targets-to-capture '(*standard-output* values)))
"Evaluate contents of STRING, return alist of results including various output streams. Possible keys in the returned alist should be listed in the value of `slime-output-targets' variable in `slime.el'."
(with-buffer-syntax ()
(with-retry-restart (:msg "Retry SLIME evaluation request.")
(let* ((trace-output-stream (make-string-output-stream))
(*trace-output* trace-output-stream)
(error-output-stream (make-string-output-stream))
(*error-output* error-output-stream)
(standard-output-stream (make-string-output-stream))
(*standard-output* standard-output-stream)
(values (multiple-value-list (eval (from-string string)))))
(list (get-output-stream-string standard-output-stream)
(format nil "~{~S~^~%~}" values)
(get-output-stream-string error-output-stream)
(get-output-stream-string trace-output-stream))))))
(macrolet ((maybe-value-string (form)
`(if (member 'values targets-to-capture)
,form
""))
(maybe-output-stream-string (stream-symbol)
`(if (member ',stream-symbol targets-to-capture)
(get-output-stream-string ,stream-symbol)
""))
(maybe-make-string-output-stream (stream-symbol)
`(if (member ',stream-symbol targets-to-capture)
(make-string-output-stream)
,stream-symbol)))
(let* ((*trace-output*
(maybe-make-string-output-stream *trace-output*))
(*error-output*
(maybe-make-string-output-stream *error-output*))
(*standard-output*
(maybe-make-string-output-stream *standard-output*))
(values (multiple-value-list (eval (from-string string)))))
;; It is not clear what would be the most natural order here.
;; We picked the reversed binding order.
(list (cons 'values
(maybe-value-string (format nil "~{~S~^~%~}" values)))
(cons '*standard-output*
(maybe-output-stream-string *standard-output*))
(cons '*error-output*
(maybe-output-stream-string *error-output*))
(cons '*trace-output*
(maybe-output-stream-string *trace-output*))))))))

(defun eval-region (string)
"Evaluate STRING.
Expand Down

0 comments on commit 78304a3

Please sign in to comment.