swank-protocol is a small, low-level client for Swank. It handles connections and reading/writing messages.
This is not a full client for Swank, it's a permissively-licensed library for building Swank clients. It doesn't match requests to responses, it doesn't asynchronously read responses and events from Swank. It just takes care of the low level details: Connecting, sending messages down the socket, reading and parsing incoming events and responses, and optionally logging.
First, load everything:
Run this to start a Swank server on
(setf swank:*configure-emacs-indentation* nil) (let ((swank::*loopback-interface* (uiop:hostname))) (swank:create-server :port 5000 :dont-close t))
Now we connect:
(defparameter connection (swank-protocol-make-connection (uiop:hostname) 5000)) (swank-protocol:connect connection)
Now we can start sending requests:
And reading responses:
For instance, let's create a REPL. First, we require some modules:
(swank-protocol:request-swank-require connection '(swank-presentations swank-repl)) (swank-protocol:request-init-presentations connection)
(Don't worry about the symbols' package)
Now we actually create it:
Now we can send things for evaluation:
(swank-protocol:request-listener-eval connection "(+ 2 2)")
And receive the results:
connection class has the following readers:
connection-hostname: The Swank server's hostname.
connection-port: The Swank server's port.
And the following accessors:
connection-request-count: The integer ID of the last request sent to the Swank server. Starts at zero.
connection-package: The package where things are evaluated. This should be changed when you send a request to Swank to change the current package.
connection-thread: This is the keyword ID of the thread to execute things in.
tis used by default to tell Swank to pick the default thread.
connection-log-p: Whether to log messages as they are read/written.
connection-logging-stream: The stream to log things to, by default,
connection can be created with
;; A regular connection (make-connection "my-hostname" "1234") ;; A connection with logging (make-connection "my-test-server" "1234" :logp t)
connect function connects to the Swank server and returns t.
After connecting, you can do two things: Send messages or read them.
To write messages, you can use
emacs-rex, which takes a connection and an S-expression to send to Swank. Implicit in this request, and stored in the
connection object, are two bits of information: The current package and the request ID.
To read messages, you use
read-message, which takes a connection and reads the next message coming from Swank. The result is an S-expression.
There are higher-level convenience functions that call
emacs-rex, to minimize repetition and error:
Requests connection information. The matching response is a plist with connection information.
(:return (:ok (:pid 1234 :style :spawn :encoding (:coding-systems ("utf-8-unix" "iso-latin-1-unix")) :lisp-implementation (:type "SBCL" :name "sbcl" :version "1.2.9" :program "/usr/local/bin/sbcl") :machine (:instance "laptop" :type "X86-64" :version "Intel(R) Core(TM) i5-2410M CPU @ 2.30GHz") :features (:bordeaux-threads ... :x86-64) :modules ("SWANK-REPL" ... "uiop") :package (:name "COMMON-LISP-USER" :prompt "CL-USER") :version "2014-12-23")) 1)
Copyright (c) 2015 Fernando Borretti
Licensed under the MIT License.