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)

Reply via email to