branch: elpa/parseedn commit f84068fd37ccb498cb0884a0c03279dc285c2474 Author: IƱaki Arenaza <inaki.aren...@magnet.coop> Commit: vemv <v...@users.noreply.github.com>
Add support for namespaced maps parseclj already added support for namespaced maps in 2018 (in commit b40670a56147214f0486763529897cb688a09692). As Alex Miller said in https://github.com/edn-format/edn/issues/78 > Clojure introduced namespace map syntax in Clojure 1.9. The Clojure > edn reader was also updated to support the non-autoresolved parts of > namespace map syntax (edn doesn't do anything autoresolved like > ::foo or #::foo{}). > > The edn spec should be updated to a new version that includes the > namespace map syntax such as #:foo{:bar 1} (syntax alternative for > {:foo/bar 1}). So it's pretty clear that the intention is for edn spec to support namespaced maps (the reference implementation in Clojure already does!). In addition to the use case mentioned in issue #16, not supporting this seems to cause trouble in CIDER when integrating with shadow-cljs (https://github.com/clojure-emacs/cider/issues/3437) Fixes: #16 --- parseedn.el | 18 +++++++++++++++-- test/parseedn-test-data.el | 50 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/parseedn.el b/parseedn.el index 99dd703007..0532268fb9 100644 --- a/parseedn.el +++ b/parseedn.el @@ -113,10 +113,24 @@ on available options." ((eq :lbracket token-type) (apply #'vector children)) ((eq :set token-type) (list 'edn-set children)) ((eq :lbrace token-type) (let* ((kvs (seq-partition children 2)) - (hash-map (make-hash-table :test 'equal :size (length kvs)))) + (hash-map (make-hash-table :test 'equal :size (length kvs))) + (prefixed-map? (eq :map-prefix (parseclj-lex-token-type (car stack)))) + (map-prefix (when prefixed-map? + ;; map-prefix forms are always "#:...." + (substring (parseclj-lex-token-form (car stack)) 2)))) (seq-do (lambda (pair) - (puthash (car pair) (cadr pair) hash-map)) + (let* ((k (if (not prefixed-map?) + (car pair) + (let ((key-name (substring (symbol-name (car pair)) 1))) + (if (string-match-p "/" key-name) + ;; keyword is already qualified, we must not add the prefix. + (car pair) + (intern (concat ":" map-prefix "/" key-name)))))) + (v (cadr pair))) + (puthash k v hash-map))) kvs) + (when prefixed-map? + (setq stack (cdr stack))) hash-map)) ((eq :tag token-type) (let* ((tag (intern (substring (alist-get :form opening-token) 1))) (reader (alist-get tag tag-readers)) diff --git a/test/parseedn-test-data.el b/test/parseedn-test-data.el index 7fe31ac7c8..212e8df199 100644 --- a/test/parseedn-test-data.el +++ b/test/parseedn-test-data.el @@ -245,6 +245,56 @@ (:form . "123") (:value . 123))))))))) + "prefixed-map-1" + (a-list + :source "#:foo.bar{:baz 1 :other.ns.prefix/qux 2}" + :edn (list (a-hash-table :foo.bar/baz 1 :other.ns.prefix/qux 2)) + :ast '((:node-type . :root) + (:position . 1) + (:children . (((:map-prefix + (:token-type . :map-prefix) + (:form . "#:foo.bar") + (:pos . 1)) + (:node-type . :map) + (:position . 10) + (:children . (((:node-type . :keyword) + (:position . 11) + (:form . ":baz") + (:value . :baz)) + ((:node-type . :number) + (:position . 16) + (:form . "1") + (:value . 1)) + ((:node-type . :keyword) + (:position . 18) + (:form . ":other.ns.prefix/qux") + (:value . :other.ns.prefix/qux)) + ((:node-type . :number) + (:position . 39) + (:form . "2") + (:value . 2))))))))) + + "prefixed-map-2" + (a-list + :source "#:foo.bar {:baz 1}" + :edn (list (a-hash-table :foo.bar/baz 1)) + :ast '((:node-type . :root) + (:position . 1) + (:children . (((:map-prefix + (:token-type . :map-prefix) + (:form . "#:foo.bar") + (:pos . 1)) + (:node-type . :map) + (:position . 10) + (:children . (((:node-type . :keyword) + (:position . 11) + (:form . ":baz") + (:value . :baz)) + ((:node-type . :number) + (:position . 16) + (:form . "1") + (:value . 1))))))))) + "set" (a-list :tags '(:edn-roundtrip)