Hello,
I sent mail to Luke about this a few days ago, but I guess he's busy partying like it's 2003 :) (if not, then please check your common-lisp.net mailbox and disregard it!). Anyway, I've gotten the swank backend mostly working on CLISP. The file is attached. On the way, I've also discovered that the slime state machine generates an error on :read-string (and gives the "you've encountered an error in SLIME" message). This should probably be fixed (and I'm not man enough to do it), as it means that interactive restarts (and probably anything else that does query-io) doesn't work.
I also have a proposal stemming from potential problems with the current message-length and character encoding schemes. The stream character encoding should be specified by a slime variable (which defaults to something like "iso-8859-1"), whose value gets passed to a swank function on initialization, which then converts it to internal representation and binds it to a special variable, which is used when opening slime sockets. The message length should then be represented by arabic numerals - the first character in a message is 0-9 and indicated how many (1+) subsequent chars to read to get the message length (giving maximum message length of 10 9s). This is a lot less efficient than the current method, but it'll work with any character encoding scheme supporting arabic numerals (which the ANSI spec says are part of standard characters and so must be provided by every conforming implementation). I propose character encoding should be specified by ASCII strings like "UTF-8", with standard names used so you can just run find-symbol or equivalent on them to get at the encoding object in Lisp and Emacs.
Also, here are some patches for things I've changed along the way:
In slime.el (the RE doesn't work for CLISP's output, and I belive this type of formatting should be done in swank):
*************** *** 3689,3697 **** for (number string) = frame do (let (label framestring) ! (setq label (format "%s" number) ! framestring string) ! (slime-insert-propertized `(frame ,frame) " " (in-sldb-face frame-label label) " " (in-sldb-face frame-line framestring) "\n"))) (let ((number (sldb-previous-frame-number))) --- 3689,3699 ---- for (number string) = frame do (let (label framestring) ! (if (string-match "\([0-9]*:\)?\s *\(.*\)" string) ! (setq label (match-string 1 string) ! framestring (match-string 2 string)) ! (setq label "" framestring string)) ! (slime-insert-propertized `(frame ,frame) " " (in-sldb-face frame-label label) " " (in-sldb-face frame-line framestring) "\n"))) (let ((number (sldb-previous-frame-number)))
In swank-backend.lisp:
*************** *** 134,141 **** (defgeneric call-with-compilation-hooks (func) (:documentation "Call FUNC with hooks to trigger SLDB on compiler errors.")) ! (defmacro with-compilation-hooks ((&rest ignore) &body body) ! (declare (ignore ignore)) `(call-with-compilation-hooks (lambda () (progn ,@body))))
(defgeneric compile-string-for-emacs (string &key buffer position) --- 134,140 ---- (defgeneric call-with-compilation-hooks (func) (:documentation "Call FUNC with hooks to trigger SLDB on compiler errors.")) ! (defmacro with-compilation-hooks (() &body body) `(call-with-compilation-hooks (lambda () (progn ,@body))))
(defgeneric compile-string-for-emacs (string &key buffer position)
In swank.lisp (CLISP didn't like the for loop, and neither did I :)
*************** *** 434,455 ****
(defun eval-region (string &optional package-update-p) "Evaluate STRING and return the result. ! If PACKAGE-UPDATE-P is non-nil, and evaluation causes a package ! change, then send Emacs an update." ! (let ((*package* *buffer-package*) ! form ! (pos 0) ! return-values ! (end-symbol (gensym))) (unwind-protect ! (loop (multiple-value-setq (form pos) ! (read-from-string string nil end-symbol :start pos)) ! (if (eq form end-symbol) ! (return return-values) ! (setq return-values ! (multiple-value-list (eval form))))) (when (and package-update-p (not (eq *package* *buffer-package*))) ! (send-to-emacs (list :new-package (shortest-package-nickname *package*)))))))
(defun shortest-package-nickname (package) "Return the shortest nickname (or canonical name) of PACKAGE." --- 434,452 ----
(defun eval-region (string &optional package-update-p) "Evaluate STRING and return the result. ! If PACKAGE-UPDATE-P is non-nil, and evaluation causes a package ! change, then send Emacs an update." ! (let ((*package* *buffer-package*)) (unwind-protect ! (with-input-from-string (stream string) ! (loop for form = (read stream nil stream) ! until (eq form stream) ! for - = form ! for values = (multiple-value-list (eval form)) ! do (force-output) ! finally (return (values values -)))) (when (and package-update-p (not (eq *package* *buffer-package*))) ! (send-to-emacs (list :new-package (shortest-package-nickname *package*)))))))
(defun shortest-package-nickname (package) "Return the shortest nickname (or canonical name) of PACKAGE."
Happy New Years! Vladimir