In my rushed article yesterday, I started making an eev eepitches-using-emacsclient class which I didn’t quite finish. Let’s finish now.
Quickly, my reason for using emacsclient was that I wanted the eepitches to be performed from-outside. When I was doing them via swank:eval-in-emacs
in certain cases, things happened not-in-the-order-I-wanted. Hence emacsclient. (Eduardo has been thinking about doing something special with named pipes, but this is where I am at right now).
Since we are going via spawning emacsclient
processes, you need to issue M-x start-server
for this to be enabled.
emacsclient --eval
s towards eepitch
Syncronously swank:eval-in-emacs
es to get the current eepitch-buffer-name
, then changes the eepitch target to the target
, and eepitch
es.
• (setq inferior-lisp-program "sbcl")
• (slime)
• (setq eepitch-buffer-name "*slime-repl sbcl*")
• (setq inferior-lisp-program "ecl")
• (slime)
From before.
(defclass eepitch ()
((target :initarg :target)
(previous))
(:default-initargs :target "*slime-repl ECL*"))
(defmethod send ((obj eepitch) expression)
(with-slots (previous target) obj
(uiop:launch-program
(let ((*print-pretty* nil))
(format nil "emacsclient -e '~?'"
"(progn (setq eepitch-buffer-name ~s) ~@
(eepitch-line ~a~s~a) ~@
(setq eepitch-buffer-name ~s))"
`(,target #" ,expression #" ,previous))))))
(defmethod send :before ((obj eepitch) expression)
(with-slots (target previous) obj
(setf previous
(swank:eval-in-emacs 'eepitch-buffer-name))))
• (setq eepitch-buffer-name "*slime-repl sbcl*")
(defparameter *ecl*
(make-instance 'eepitch
:target "*slime-repl ECL*"))
eepitch-buffer-name
(send *ecl* '(1+ 1))
eepitch-buffer-name
Voila. In *slime-repl ECL*
:
; SLIME 2.29.1
CL-USER> (1+ 1)
2
Back in *slime-repl sbcl*
:
CL-USER> (defparameter *ecl*
(make-instance 'eepitch
:target "*slime-repl ECL*"))
*ECL*
CL-USER> (send *ecl* '(1+ 1))
#<UIOP/LAUNCH-PROGRAM::PROCESS-INFO {1002C4C663}>
CL-USER>
• (setq eepitch-buffer-name "*slime-repl ECL*")
;; above definitions again.
(defparameter *sbcl* (make-instance 'eepitch :Target "*slime-repl sbcl*"))
(send *sbcl* '(1+ 1))
Having done the defclass eepitch
in the ECL repl:
CL-USER> (defparameter *sbcl* (make-instance 'eepitch :Target "*slime-repl sbcl*"))
*SBCL*
CL-USER> (send *sbcl* '(1+ 1))
#<a UIOP/RUN-PROGRAM::PROCESS-INFO 0x7f40f03f9a00>
CL-USER>
Whence in *slime-repl sbcl*
:
CL-USER> (1+ 1)
2
CL-USER>
This begs the question:
• (setq eepitch-buffer-name "*slime-repl sbcl*")
(send *ecl* '(send *sbcl* '(1+ 2)))
• eepitch-buffer-name
Got it, seems to unwind as expected.
sbcl:
CL-USER> (send *ecl* '(send *sbcl* '(1+ 2)))
#<UIOP/LAUNCH-PROGRAM::PROCESS-INFO {1002C4E6D3}>
CL-USER> (1+ 2)
3
CL-USER>
ecl:
CL-USER> (SEND *SBCL* (QUOTE (1+ 2)))
#<a UIOP/RUN-PROGRAM::PROCESS-INFO 0x7f40f03f95c0>
CL-USER>
We wrote a common lisp class that uses an emacsclient
async process to eepitch forms to other targets using the emacs server (i.e. M-x server-start
).
This stores the previous eepitch-buffer-name
using the :before
common lisp object system method qualifier, which eepitch-buffer-name
is returned to in a progn
with the form being pitched. This appears to unwind correctly, while being sent asyncronously using uiop:launch-program
.
Hence we have fairly robust eepitching eepitching eepitching eepitching eepitching, though the aesthetically appealling process is to have eepitch’s three buffer configuration and watch the two buffers’ conversation happening in real time. Creating a sequence of two-repl conversations, into which the human can interject freely with their own eepitches, hopefully with the current converse-ees, so as not to disrupt the three panel layout.
This interimage communication medium has the oddly human semblance of a series of three-person dialogs which would be disrupted by any of the participants starting a conversation with a fourth member. Rather, there would be a subsequent meeting with a new set of participants.
The human is different to the two lisp images in that each lisp-image would use for-example yes-or-no-p
in their own repl to receive responses from the human, whereas the lisp images communicate with each other by asyncronously sending one-way instructions (the instruction may be get back to me).
All right! What do you think? (On the Mastodon thread). Is my idea of a sequence of three-party conversations more than superficial?
screwlisp proposes kittens