With raw CMUCL, I am able to do the following:
* (in-package #:pg-user)
#<The PLAYGROUND-USER package, 0/9 internal, 0/2 external> * (in-syntax-kick-reader-macros)
* !$( ls -F )
; [... snip for brevity ...] #<process 523 :EXITED> *
However, when I attempt the same thing in a SLIME REPL, I encounter the following blah stack:
End-of-File on #<String-Input Stream> [Condition of type END-OF-FILE]
Restarts: 0: [ABORT] Abort handling SLIME request. 1: [ABORT] Return to Top-Level.
Backtrace: 0: (LISP::STRING-INCH #<String-Input Stream> T NIL) 1: (LISP::FLUSH-WHITESPACE #<String-Input Stream>) 2: (LISP::READ-LIST #<String-Input Stream> #<unused-arg>) 3: (LISP::READ-PRESERVING-WHITESPACE-INTERNAL #<String-Input Stream> T NIL T) 4: (LISP::READ-PRESERVING-WHITESPACE-INTERNAL 4 #<String-Input Stream> T NIL ...)[:EXTERNAL] 5: (LISP::READ-INTERNAL #<String-Input Stream> T NIL T) 6: (READ #<String-Input Stream> T NIL T) 7: (LISP::BACKQUOTE-MACRO #<String-Input Stream> #<unused-arg>) 8: (|!` READER| #<String-Input Stream> #<#1=unused-arg> #<#1#>) 9: (|!$ READER| #<String-Input Stream> #<unused-arg> NIL) 10: (LISP::READ-PRESERVING-WHITESPACE-INTERNAL #1=#<String-Input Stream> NIL #1# T) 11: (LISP::READ-PRESERVING-WHITESPACE-INTERNAL #1=#<String-Input Stream> NIL #1# NIL) 12: (LISP::READ-PRESERVING-WHITESPACE-INTERNAL 4 #1=#<String-Input Stream> NIL #1# ...)[:EXTERNAL] 13: (LISP::READ-INTERNAL #1=#<String-Input Stream> NIL #1# NIL) 14: (READ #1=#<String-Input Stream> NIL #1# NIL) --more--
FWIW, here are the offending reader macros and relavent code, though I haven't included the code from _On Lisp_, e.g. AWHEN, AIF, etc.
(defmacro in-syntax-kick-reader-macros () `(eval-when (:compile-toplevel :load-toplevel :execute) (setq *readtable* (copy-readtable nil)) (make-dispatch-macro-character #!) (set-dispatch-macro-character #! #( #'|!( READER|) (set-dispatch-macro-character #! #' #'|!' READER|) (set-dispatch-macro-character #! #` #'|!` READER|) (set-dispatch-macro-character #! #$ #'|!$ READER|) (values)))
(defun |!( READER| (stream char n-arg) (declare (ignore char n-arg)) (let ((*readtable* (copy-readtable *readtable*))) (setf (readtable-case *readtable*) :preserve) #-(and)(read-delimited-list #) stream t) (funcall (get-macro-character #() stream #()))
(defun |!' READER| (stream char n-arg) (declare (ignore char n-arg)) (let ((*readtable* (copy-readtable *readtable*))) (setf (readtable-case *readtable*) :preserve) (funcall (get-macro-character #') stream #')))
(defun |!` READER| (stream char n-arg) (declare (ignore char n-arg)) (let ((*readtable* (copy-readtable *readtable*))) (setf (readtable-case *readtable*) :preserve) (funcall (get-macro-character #`) stream #`)))
(defun |!$ READER| (stream char n-arg) (declare (ignore char)) `(sh ,(|!` READER| stream #` n-arg)))
Damien Kick dkick1@motorola.com writes:
With raw CMUCL, I am able to do the following:
- (in-package #:pg-user)
#<The PLAYGROUND-USER package, 0/9 internal, 0/2 external>
(in-syntax-kick-reader-macros)
!$(
ls -F )
; [... snip for brevity ...] #<process 523 :EXITED>
However, when I attempt the same thing in a SLIME REPL, I encounter the following blah stack:
End-of-File on #<String-Input Stream> [Condition of type END-OF-FILE]
SLIME is getting confused and asking Lisp to evaluate your input before it's complete. When you press RET the first time Emacs is asking Lisp to eval "!$(" and is getting END-OF-FILE.
Quick workaround is to press C-j instead of RET when entering multi-line input with this syntax. C-j will always open a new line, whereas RET will try to decide if the input is finished or not.
Sorry but I haven't got time to make a proper fix today!