Hello,
I've modified the code as follows (also not yet corrected the tilde bug) : What you can see is that insted of restoring the full initial readtable, I only restore the #" macro character previous function (the one I have overriden with (start). This way, I do not reset other -possible- personalized macro character functions. I also provide a (stop) method which restores the previous #" macro character.
I also twiked the main function in order to let the initial string unchanged in case no ${} is used (usefull for a lot of macros that only accept raw strings, such as defpackage, ...).
Please let me know if you think this would not work in a case I haven't seen.
The code follows :
(defpackage "ENHANCED-STRINGS" (:USE "COMMON-LISP") (:EXPORT "START") (:EXPORT "STOP"))
(in-package "ENHANCED-STRINGS")
(defun parse-enhanced-string (string) (loop :with chunks = '() :with args = '() :with start = 0 :for pos = (search "${" string :start2 start) :for end = (and pos (search "}" string :start2 pos)) :while end :do (progn (push (subseq string start pos) chunks) (multiple-value-bind (form next) (read-from-string string t nil :start (+ 2 pos) :end end) (loop :while (and (< next end) (member (aref string next) '(#\space #\newline))) :do (incf next)) (unless (= next end) (error "Junk in ~S" (subseq string pos end))) (push form args)) (setf start (1+ end))) :finally (progn (push (subseq string start) chunks) (if (rest chunks) (return `(format nil ,(format nil "~{~A~^~~A~}" (nreverse chunks)) ,@(nreverse args)))) (return string))))
(defun reader-macro--enhanced-string (stream dblquote) (let ((*readtable* (copy-readtable))) (set-macro-character #" (get-old-macro-character)) (unread-char dblquote stream) (parse-enhanced-string (read stream t nil t))))
(let ((old-macro-character nil)) (defun start () (unless old-macro-character (setf old-macro-character (get-macro-character #")) (set-macro-character #" #'reader-macro--enhanced-string))) (defun stop () (when old-macro-character (set-macro-character #" old-macro-character) (setf old-macro-character nil))) (defun get-old-macro-character () old-macro-character))