Closed digikar99 closed 5 months ago
I'm not sure I fully understand the desired functionality, but maybe something like this:
(cl:defpackage #:eclector.examples.package-local-readtable
(:use
#:cl))
(cl:in-package #:eclector.examples.package-local-readtable)
(defvar *custom-readtable-1*
(let ((table (eclector.readtable:copy-readtable eclector.reader:*readtable*)))
(eclector.readtable:set-macro-character
table #\- (lambda (stream char)
(declare (ignore char))
:from-readtable-1))
table))
(defvar *custom-readtable-2*
(let ((table (eclector.readtable:copy-readtable eclector.reader:*readtable*)))
(eclector.readtable:set-macro-character
table #\- (lambda (stream char)
(declare (ignore char))
:from-readtable-2))
table))
(defclass client () ())
(defgeneric readtable-for-package (client package)
(:method ((client client) (package t))
(let ((package-name (package-name package)))
(cond ((string= package-name "PACKAGE1")
*custom-readtable-1*)
((string= package-name "PACKAGE2")
*custom-readtable-2*)
(t
eclector.reader:*readtable*)))))
(defmethod eclector.reader:state-value ((client client)
(aspect (eql '*readtable*)))
(let ((package (eclector.reader:state-value client '*package*)))
(readtable-for-package client package)))
(defpackage #:package1)
(defpackage #:package2)
(defpackage #:package3)
(list (let ((eclector.reader:*client* (make-instance 'client))
(*package* (find-package "PACKAGE1") ))
(eclector.reader:read-from-string "(foo-bar)"))
(let ((eclector.reader:*client* (make-instance 'client))
(*package* (find-package "PACKAGE2") ))
(eclector.reader:read-from-string "(foo-bar)"))
(let ((eclector.reader:*client* (make-instance 'client))
(*package* (find-package "PACKAGE3") ))
(eclector.reader:read-from-string "(foo-bar)")))
;;; => ((PACKAGE1::FOO :FROM-READTABLE-1 PACKAGE1::BAR)
;;; (PACKAGE2::FOO :FROM-READTABLE-2 PACKAGE2::BAR)
;;; (PACKAGE3::FOO-BAR))
Yes, this is what I wanted. And this also illustrates a nice use of clients that I have been trying to wrap my head around.
Thank you much!
How easy or non-trivial might it to be use eclector to implement package local readtables? By package local, I mean that whether or not a character has a reader macro or whether it is a constituent character would depend on the value of
cl:*readtable*
.I'm looking for a lisp-only solution without going into the specifics of any IDE like SLIME/SLY.
I found it trivial to implement one for characters that already have a macro in the standard readtable. But doing the same for characters that are constituents in the standard readtable seemed to require digging into the implementation of
read/read-preserving-whitespace
.