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.