Hi everybody,
I noticed that slime provides a function eval-in-emacs that sends a form to the emacs side where it is evaluated. However, I would like to get the results on the lisp side but I always get NIL.
Is there a different swank function for that? (in the emacs-lisp-interface from Franz I used a lep::eval-in-emacs that did precisely what I needed).
This is very useful to provide refactoring operations (that operate on the Lisp side) that need to interact with the user using emacs lisp operations such as y-or-n-p or read-from-minibuffer.
I know that it might be difficult to find a general scheme to translate from emacs lisp values to common lisp values but all I need is symbols, strings, numbers and such.
-----------------
A few years ago I developed a 'window'-debugger and 'window'-inspector for Ilisp+CMUCL similar to what I used in the Explorer Lisp Machines. I recently adapted it to Slime+Whatever-Common-Lisp-slime-supports. If anyone is interested I can post it. However, I would like to suggest two changes to Slime in order to improve its portability:
1. The function swank::inspected-parts should provide a recognizable value for unbound slots. Here is one example in SBCL
CL-USER> (defclass c () ((a))) #<STANDARD-CLASS C> CL-USER> (swank::inspected-parts (make-instance 'c)) "The object is a STANDARD-OBJECT of type C. " (("A" . #:INSPECT-UNBOUND-OBJECT-3530))
and in CLISP
CL-USER> (swank::inspected-parts (make-instance 'c)) "#<COMMON-LISP-USER::C #x20426856> standard object type: COMMON-LISP-USER::C" (("A" . INSPECT-TMP-PACKAGE-5413::|#<unbound>|))
I know that the returned values are recognizable (e.g., by being the value of the variable sb-impl::*inspect-unbound-object-marker* or something similar) but given the fact that it depends on the Common Lisp being used, it would be preferable if Slime provided a function that recognizes such value. If it already does, my apologies.
2. The function swank::frame-locals doesn't distinguish valid locals from invalid ones. I know that not all Common Lisps make that distinction but for the ones that make, it would be useful to get that information (for Common Lisps that don't provide such information a default could be chosen). Currently, Slime puts a :not-available as value which, IMHO, is error-prone. It would be nicer to have an extra field for each local that describes its status or (as in 1.) a slime function that recognizes such special value or as a third (and not so good) alternative, swank::frame-locals should not produce invalid locals.
Thanks in advance,
António Leitão.
Antonio Menezes Leitao aml@gia.ist.utl.pt writes:
Is there a different swank function for that? (in the emacs-lisp-interface from Franz I used a lep::eval-in-emacs that did precisely what I needed).
No, there's currently no such thing. We could probably generalize the code that reads input from the REPL (see READ-USER-INPUT-FROM-EMACS) to support arbitrary calls. But this will not happen before the Great Release.
This is very useful to provide refactoring operations (that operate on the Lisp side) that need to interact with the user using emacs lisp operations such as y-or-n-p or read-from-minibuffer.
I think it is good principle to keep the interaction between Emacs and Lisp to a minimum. I'm not sure, tough, whether such Y-OR-N-P-style functions help to reduce the interactions; experience will tell.
I know that it might be difficult to find a general scheme to translate from emacs lisp values to common lisp values but all I need is symbols, strings, numbers and such.
Yes, keywords, strings, numbers, and cons trees map quite nicely between the to dialects. For other objects it's better to exchange some index or numeric id.
A few years ago I developed a 'window'-debugger and 'window'-inspector for Ilisp+CMUCL similar to what I used in the Explorer Lisp Machines. I recently adapted it to Slime+Whatever-Common-Lisp-slime-supports. If anyone is interested I can post it.
Please post the code, so that we have some examples for your needs.
- The function swank::inspected-parts should provide a recognizable value for unbound slots. Here is one example in SBCL
[...]
- The function swank::frame-locals doesn't distinguish valid locals from invalid ones.
[...]
We have this UNBOUND-SLOT-FILLER objects, but I think they aren't used very consistently, probably only for Allegro. I'll have look at it.
Helmut.
Hi,
Helmut Eller e9626484@stud3.tuwien.ac.at writes:
Antonio Menezes Leitao aml@gia.ist.utl.pt writes:
Is there a different swank function for that? (in the emacs-lisp-interface from Franz I used a lep::eval-in-emacs that did precisely what I needed).
No, there's currently no such thing. We could probably generalize the code that reads input from the REPL (see READ-USER-INPUT-FROM-EMACS) to support arbitrary calls. But this will not happen before the Great Release.
This is very useful to provide refactoring operations (that operate on the Lisp side) that need to interact with the user using emacs lisp operations such as y-or-n-p or read-from-minibuffer.
I think it is good principle to keep the interaction between Emacs and Lisp to a minimum. I'm not sure, tough, whether such Y-OR-N-P-style functions help to reduce the interactions; experience will tell.
I know that it might be difficult to find a general scheme to translate from emacs lisp values to common lisp values but all I need is symbols, strings, numbers and such.
Yes, keywords, strings, numbers, and cons trees map quite nicely between the to dialects. For other objects it's better to exchange some index or numeric id.
Six months later, I decided to bite the bullet. I'm not sure I did it correctly but it's working. However, I did a bit of copy&paste that surely could be improved by someone that knows about slime internals.
I would be glad if someone could correct/improve my patches. Here are the changes:
---------------------------------------------------------------------- In file slime.el, I added a function that is a simplified version of slime-repl-read-string:
(defun evaluate-in-emacs (expr thread tag) (push thread slime-read-string-threads) (push tag slime-read-string-tags) (slime-repl-return-string (eval expr)))
and I also included an extra clause in slime-dispatch-event, as follows:
(defun slime-dispatch-event (event &optional process) ... ((:read-string thread tag) (assert thread) (slime-repl-read-string thread tag)) ((:evaluate-in-emacs string thread tag) ;;<-- (assert thread) (evaluate-in-emacs (car (read-from-string string)) thread tag)) ((:read-aborted thread tag) (assert thread) (slime-repl-abort-read thread tag)) ...))) ----------------------------------------------------------------------
In file swank.lisp, I added a function that was mostly copied&pasted from read-user-input-from-emacs:
(defun evaluate-in-emacs (string) (let ((*read-input-catch-tag* (1+ *read-input-catch-tag*))) (force-output) (send-to-emacs `(:evaluate-in-emacs ,string ,(current-thread) ,*read-input-catch-tag*)) (let ((ok nil)) (unwind-protect (prog1 (catch (intern-catch-tag *read-input-catch-tag*) (loop (read-from-emacs))) (setq ok t)) (unless ok (send-to-emacs `(:read-aborted ,(current-thread) *read-input-catch-tag*)))))))
and I also included an extra clause in dispatch-event, as follows:
(defun dispatch-event (event socket-io) ... ((:read-string thread &rest args) (encode-message `(:read-string ,(thread-id thread) ,@args) socket-io)) ((:evaluate-in-emacs string thread &rest args) ;;AML (encode-message `(:evaluate-in-emacs ,string ,(thread-id thread) ,@args) socket-io)) ((:read-aborted thread &rest args) (encode-message `(:read-aborted ,(thread-id thread) ,@args) socket-io)) ...))
That's all.
These changes allow me to evaluate, on the Common Lisp side, expressions that interact with the user via the Emacs editor, such as:
CL-USER> (swank::evaluate-in-emacs "(y-or-n-p "Continue?")") T CL-USER> (swank::evaluate-in-emacs "(read-from-minibuffer "Your name:")") "Antonio Leitao"
These (and others) are very useful to implement some refactoring operations that need to interact with the user and that should be hidden in the Common Lisp side.
Best regards,
António Leitão.