RSS Feed

Lisp Project of the Day

lime

You can support this project by donating at:

Donate using PatreonDonate using Liberapay

limeslimeswankrepl

Documentation🥺
Docstrings😀
Tests 😀
Examples😀
RepositoryActivity🥺
CI 😀

Lime is a standalone SWANK client. It can be used to programmatically connect to the SWANK server without Emacs.

One useful thing, you might do is to make a command-line client to send a command to your server. One practical task is code hot-reload. Here is an example of how to implement it using another SWANK client.

Example from Lime's sources shows how to create a REPL connected to the SWANK. However, this example creates a SWANK server in the same process. I think it will be more realistic to connect from one lisp to another.

So, I modified example to make it connect to the localhost 20100, where we'll start a separate ClozureCL process with SWANK:

Clozure Common Lisp Version 1.12 (v1.12) DarwinX8664

For more information about CCL, please see http://ccl.clozure.com.

CCL is free software.  It is distributed under the terms of the Apache
Licence, Version 2.0.
? (ql:quickload :swank)
To load "swank":
  Load 1 ASDF system:
    swank
; Loading "swank"

? (swank:create-server :port 20100 :dont-close t :style :spawn)
;; Swank started at port: 20100.
20100

Now we need a function which will make a connection and provide us with the remote REPL.

I just removed the code which starts SWANK in the same process and replaced (uiop:hostname) with "localhost", because (uiop:hostname) didn't work for me:

POFTHEDAY> (defun repl ()
             "Start the REPL."
             (let ((conn (lime:make-connection "localhost"
                                               20100)))
               (lime:connect conn)

               (format t "Swank server running on ~A ~A~%"
                       (lime:connection-implementation-name conn)
                       (lime:connection-implementation-version conn))
               
               (loop
                 ;; Read all events
                 (sleep 0.05)
                 (let ((events (lime:pull-all-events conn)))
                   (loop for event in events do
                     (typecase event
                       (lime:write-string-event
                        (write-string (lime:event-string event)))
                       (lime:debugger-event
                        (write-string "Entered debugger!"))
                       (t
                        t))))
                 ;; Take input
                 (if (lime:connection-reader-waiting-p conn)
                     ;; Read a line to send as standard input
                     (progn
                       (format t "~%Read: ")
                       (let ((input (read-line)))
                         (lime:send-input conn input)))
                     ;; Read regular code
                     (progn
                       (format t "~A> " (lime:connection-package conn))
                       (let ((input (read)))
                         (lime:evaluate conn
                                        (with-standard-io-syntax
                                          (prin1-to-string input)))))))))

Now we can connect to our ClozureCL process and have a fun!

;; We are connecting from SBCL to CCL
POFTHEDAY> (lisp-implementation-type)
"SBCL"
POFTHEDAY> (lisp-implementation-version)
"2.0.2"

POFTHEDAY> (repl)
Swank server running on ccl Version 1.12 (v1.12) DarwinX8664

COMMON-LISP-USER> (lisp-implementation-type)
"Clozure Common Lisp"

COMMON-LISP-USER> (lisp-implementation-version)
"Version 1.12 (v1.12) DarwinX8664"

COMMON-LISP-USER> (+ 1 2)
3

If you are going to try Lime on CCL, use the patched swank-protocol system with this fix. Without the fix Lime will not work because of the following error:

<INFO> [23:48:47] swank-protocol swank-protocol.lisp (read-message) -
  Read message SWANK-PROTOCOL::RESULT: (:READER-ERROR
                                        "(:emacs-rex (swank-repl:listener-eval #A((7) common-lisp:base-char . \"(+ 1 2)\")) \"COMMON-LISP-USER\" :repl-thread 5)
"
                                        "Reader error on #<STRING-INPUT-STREAM  :CLOSED #x30200139FB9D>:
reader macro #A used without a rank integer")

I experienced the same error with Lem editor. And it was fixed with a similar patch.


Brought to you by 40Ants under Creative Commons License