branch: elpa/parseedn
commit f84068fd37ccb498cb0884a0c03279dc285c2474
Author: IƱaki Arenaza <[email protected]>
Commit: vemv <[email protected]>
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)