[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[nongnu] elpa/parseclj a8e1de0d62 075/185: Merge pull request #4 from la
From: |
ELPA Syncer |
Subject: |
[nongnu] elpa/parseclj a8e1de0d62 075/185: Merge pull request #4 from lambdaisland/edn-ast-split |
Date: |
Tue, 28 Dec 2021 14:05:19 -0500 (EST) |
branch: elpa/parseclj
commit a8e1de0d62d9a23f84a6fe16fe2d7ff2cf7862e0
Merge: 1cf0fb9d3f 496c965edc
Author: Arne Brasseur <arne.brasseur@gmail.com>
Commit: GitHub <noreply@github.com>
Merge pull request #4 from lambdaisland/edn-ast-split
Split EDN and AST handling into their own files
---
.gitignore | 1 +
.travis.yml | 25 +--
Cask | 14 ++
README.md | 2 +-
benchmark/speed-comparison.el | 2 +-
clj-ast.el | 116 ++++++++++++
clj-edn.el | 145 ++++++++++++++
clj-lex.el | 4 +-
clj-parse-test-runner.el | 48 -----
clj-parse.el | 124 +-----------
test/clj-ast-test.el | 68 +++++++
test/clj-ast-unparse-test.el | 166 +++++++++++++++++
test/clj-edn-el-parity-test.el | 286 ++++++++++++++++++++++++++++
test/clj-edn-test.el | 77 ++++++++
{tests => test}/clj-lex-test.el | 10 +-
test/clj-parse-test-data.el | 298 +++++++++++++++++++++++++++++
test/clj-parse-test.el | 38 ++++
test/test-helper.el | 38 ++++
tests/clj-parse-test.el | 404 ----------------------------------------
tests/edn-el-test-suite.el | 281 ----------------------------
20 files changed, 1278 insertions(+), 869 deletions(-)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000..d4691b73a4
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+.cask
diff --git a/.travis.yml b/.travis.yml
index 16e2a68de7..5cfcd11bb1 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,20 +1,23 @@
language: generic
dist: trusty
env:
- - VERSION=25.2.2 EMACS=emacs-25.2 PACKAGE=emacs25
- - VERSION=25.2.2 EMACS=emacs-25.2 PACKAGE=emacs25 CLJ_PARSE_LINT=true
-
+ - EMACS=emacs25
+ - EMACS=emacs-snapshot
matrix:
allow_failures:
- - env: VERSION=25.2.2 EMACS=emacs-25.2 PACKAGE=emacs25 CLJ_PARSE_LINT=true
-
+ - env: EMACS=emacs-snapshot
before_install:
+ # Emacs 25
- sudo add-apt-repository -y ppa:kelleyk/emacs
+ # Nightly Emacs snapshot builds
+ - sudo add-apt-repository -y ppa:ubuntu-elisp/ppa
+ # Update and install the Emacs for our environment
- sudo apt-get update -qq
- - sudo apt-get install -qq $PACKAGE
-
+ - sudo apt-get install -qq -yy ${EMACS}
+ # Install and bootstrap cask
+ - travis_retry sh -c 'curl -fsSkL https://raw.github.com/cask/cask/master/go
| python'
+ - export PATH="${HOME}/.cask/bin:$PATH"
+install:
+ - cask install
script:
- - $EMACS --version
- - ls /usr/bin /usr/local/bin | grep emacs
- - $EMACS --version | grep $VERSION
- - $EMACS -batch -l clj-parse-test-runner.el
+ - cask exec ert-runner
diff --git a/Cask b/Cask
new file mode 100644
index 0000000000..528cd303fd
--- /dev/null
+++ b/Cask
@@ -0,0 +1,14 @@
+(source gnu)
+(source melpa)
+(source lambdaisland "https://lambdaisland.github.io/elpa/")
+
+(package-file "clj-parse.el")
+
+(files "clj-lex.el"
+ "clj-edn.el"
+ "clj-ast.el")
+
+(development
+ (depends-on "a")
+;; (depends-on "edn") ;; the edn.el parity tests require some edn.el functions
+ (depends-on "ert-runner"))
diff --git a/README.md b/README.md
index 520561f21b..124801fd07 100644
--- a/README.md
+++ b/README.md
@@ -8,4 +8,4 @@ WIP
© 2017 Arne Brasseur
-Distributed under the terms of the [Mozilla Public License
2.0](https://www.mozilla.org/media/MPL/2.0/index.txt). See LICENSE.
\ No newline at end of file
+Distributed under the terms of the GNU General Public License 3.0 or later.
See LICENSE.
diff --git a/benchmark/speed-comparison.el b/benchmark/speed-comparison.el
index b50a405940..2529e782eb 100644
--- a/benchmark/speed-comparison.el
+++ b/benchmark/speed-comparison.el
@@ -14,7 +14,7 @@
;;(message fn)
(with-current-buffer buff
(let ((start (time-to-seconds (current-time))))
- (clj-parse-edn)
+ (clj-edn-read)
(setq clj-time (+ clj-time (- (time-to-seconds (current-time))
start))))
(goto-char 1)
(let ((start (time-to-seconds (current-time))))
diff --git a/clj-ast.el b/clj-ast.el
new file mode 100644
index 0000000000..c295d316e6
--- /dev/null
+++ b/clj-ast.el
@@ -0,0 +1,116 @@
+;;; clj-ast.el --- Clojure parser/unparser -*- lexical-binding:
t; -*-
+
+;; Copyright (C) 2017 Arne Brasseur
+
+;; Author: Arne Brasseur <arne@arnebrasseur.net>
+
+;; This file is not part of GNU Emacs.
+
+;; This file is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; This file is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; Parse Clojure code to an AST, and unparse back to code.
+
+;;; Code:
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Parser
+
+(defun clj-parse--make-node (type position &rest kvs)
+ (apply 'a-list ':node-type type ':position position kvs))
+
+(defun clj-ast--reduce-leaf (stack token)
+ (if (eq (clj-lex-token-type token) :whitespace)
+ stack
+ (cons
+ (clj-parse--make-node (clj-lex-token-type token) (a-get token 'pos)
+ ':form (a-get token 'form)
+ ':value (clj-parse--leaf-token-value token))
+ stack)))
+
+(defun clj-ast--reduce-node (stack opener-token children)
+ (let* ((pos (a-get opener-token 'pos))
+ (type (clj-lex-token-type opener-token))
+ (type (cl-case type
+ (:lparen :list)
+ (:lbracket :vector)
+ (:lbrace :map)
+ (t type))))
+ (cl-case type
+ (:root (clj-parse--make-node :root 0 :children children))
+ (:discard stack)
+ (:tag (list (clj-parse--make-node :tag
+ pos
+ :tag (intern (substring (a-get
opener-token 'form) 1))
+ :children children)))
+ (t (cons
+ (clj-parse--make-node type pos :children children)
+ stack)))))
+
+(defun clj-ast-parse ()
+ "Parse Clojure code in buffer to AST.
+
+Parses code in the current buffer, starting from the current
+position of (point)."
+ (clj-parse-reduce #'clj-ast--reduce-leaf #'clj-ast--reduce-node))
+
+(defun clj-ast-parse-str (s)
+ "Parse Clojure code in string S to AST."
+ (with-temp-buffer
+ (insert s)
+ (goto-char 1)
+ (clj-ast-parse)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Unparser
+
+(defun clj-ast-unparse-collection (nodes ld rd)
+ (insert ld)
+ (when-let (node (car nodes))
+ (clj-ast-unparse node))
+ (seq-doseq (node (cdr nodes))
+ (insert " ")
+ (clj-ast-unparse node))
+ (insert rd))
+
+(defun clj-ast-unparse-tag (node)
+ (progn
+ (insert "#")
+ (insert (symbol-name (a-get node :tag)))
+ (insert " ")
+ (clj-ast-unparse (car (a-get node :children)))))
+
+(defun clj-ast-unparse (node)
+ (if (clj-parse--is-leaf? node)
+ (insert (alist-get ':form node))
+ (let ((subnodes (alist-get ':children node)))
+ (cl-case (a-get node ':node-type)
+ (:root (clj-ast-unparse-collection subnodes "" ""))
+ (:list (clj-ast-unparse-collection subnodes "(" ")"))
+ (:vector (clj-ast-unparse-collection subnodes "[" "]"))
+ (:set (clj-ast-unparse-collection subnodes "#{" "}"))
+ (:map (clj-ast-unparse-collection subnodes "{" "}"))
+ (:tag (clj-ast-unparse-tag node))))))
+
+(defun clj-ast-unparse-str (data)
+ (with-temp-buffer
+ (clj-ast-unparse data)
+ (buffer-substring-no-properties (point-min) (point-max))))
+
+(provide 'clj-ast)
+
+;;; clj-ast.el ends here
diff --git a/clj-edn.el b/clj-edn.el
new file mode 100644
index 0000000000..d509c6c4b0
--- /dev/null
+++ b/clj-edn.el
@@ -0,0 +1,145 @@
+;;; clj-edn.el --- EDN reader/writer -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2017 Arne Brasseur
+
+;; Author: Arne Brasseur <arne@arnebrasseur.net>
+
+;; This file is not part of GNU Emacs.
+
+;; This file is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; This file is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; The EDN <-> Elisp reader and printer
+
+;;; Code:
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Reader
+
+(defvar clj-edn-default-tag-readers
+ (a-list 'inst (lambda (s)
+ (cl-list* 'edn-inst (date-to-time s)))
+ 'uuid (lambda (s)
+ (list 'edn-uuid s)))
+ "Default reader functions for handling tagged literals in EDN.
+These are the ones defined in the EDN spec, #inst and #uuid. It
+is not recommended you change this variable, as this globally
+changes the behavior of the EDN reader. Instead pass your own
+handlers as an optional argument to the reader functions.")
+
+(defun clj-edn-reduce-leaf (stack token)
+ (if (member (clj-lex-token-type token) (list :whitespace :comment))
+ stack
+ (cons (clj-parse--leaf-token-value token) stack)))
+
+(defun clj-edn-reduce-node (tag-readers)
+ (lambda (stack opener-token children)
+ (let ((token-type (clj-lex-token-type opener-token)))
+ (if (member token-type '(:root :discard))
+ stack
+ (cons
+ (cl-case token-type
+ (:lparen children)
+ (:lbracket (apply #'vector children))
+ (:set (list 'edn-set children))
+ (:lbrace (let* ((kvs (seq-partition children 2))
+ (hash-map (make-hash-table :test 'equal :size
(length kvs))))
+ (seq-do (lambda (pair)
+ (puthash (car pair) (cadr pair) hash-map))
+ kvs)
+ hash-map))
+ (:tag (let* ((tag (intern (substring (a-get opener-token 'form) 1)))
+ (reader (a-get tag-readers tag :missing)))
+ (when (eq :missing reader)
+ (user-error "No reader for tag #%S in %S" tag (a-keys
tag-readers)))
+ (funcall reader (car children)))))
+ stack)))))
+
+(defun clj-edn-read (&optional tag-readers)
+ (clj-parse-reduce #'clj-edn-reduce-leaf
+ (clj-edn-reduce-node (a-merge clj-edn-default-tag-readers
tag-readers))))
+
+(defun clj-edn-read-str (s &optional tag-readers)
+ (with-temp-buffer
+ (insert s)
+ (goto-char 1)
+ (car (clj-edn-read tag-readers))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Printer
+
+
+(defun clj-edn-print-seq (coll)
+ (clj-edn-print (elt coll 0))
+ (let ((next (seq-drop coll 1)))
+ (when (not (seq-empty-p next))
+ (insert " ")
+ (clj-edn-print-seq next))))
+
+(defun clj-edn-print-kvs (map)
+ (let ((keys (a-keys map)))
+ (clj-edn-print (car keys))
+ (insert " ")
+ (clj-edn-print (a-get map (car keys)))
+ (let ((next (cdr keys)))
+ (when (not (seq-empty-p next))
+ (insert ", ")
+ (clj-edn-print-kvs next)))))
+
+(defun clj-edn-print (datum)
+ (cond
+ ((or (null datum) (numberp datum))
+ (prin1 datum (current-buffer)))
+
+ ((stringp datum)
+ (insert "\"")
+ (seq-doseq (char datum)
+ (insert (cl-case char
+ (?\t "\\t")
+ (?\f "\\f")
+ (?\" "\\\"")
+ (?\r "\\r")
+ (?\n"foo\t" "\\n")
+ (?\\ "\\\\")
+ (t (char-to-string char)))))
+ (insert "\""))
+
+ ((eq t datum)
+ (insert "true"))
+
+ ((symbolp datum)
+ (insert (symbol-name datum)))
+
+ ((vectorp datum) (insert "[") (clj-edn-print-seq datum) (insert "]"))
+
+ ((consp datum)
+ (cond
+ ((eq 'edn-set (car datum))
+ (insert "#{") (clj-edn-print-seq (cadr datum)) (insert "}"))
+ (t (insert "(") (clj-edn-print-seq datum) (insert ")"))))
+
+ ((hash-table-p datum)
+ (insert "{") (clj-edn-print-kvs datum) (insert "}"))))
+
+(defun clj-edn-print-str (datum)
+ (with-temp-buffer
+ (clj-edn-print datum)
+ (buffer-substring-no-properties (point-min) (point-max))))
+
+(provide 'clj-edn)
+
+;;; clj-edn.el ends here
diff --git a/clj-lex.el b/clj-lex.el
index 99b5264d34..f85818ecfb 100644
--- a/clj-lex.el
+++ b/clj-lex.el
@@ -25,15 +25,13 @@
;; A reader for EDN data files and parser for Clojure source files.
-(require 'dash)
-
(defun clj-lex-token (type form pos &rest args)
`((type . ,type)
(form . ,form)
(pos . ,pos)
,@(mapcar (lambda (pair)
(cons (car pair) (cadr pair)))
- (-partition 2 args))))
+ (seq-partition args 2))))
(defun clj-lex-token-type (token)
(and (listp token)
diff --git a/clj-parse-test-runner.el b/clj-parse-test-runner.el
deleted file mode 100644
index 4a49138c9a..0000000000
--- a/clj-parse-test-runner.el
+++ /dev/null
@@ -1,48 +0,0 @@
-;; Script used for the Travis build
-
-(setq package-archives
- '(("gnu" . "https://elpa.gnu.org/packages/")
- ("melpa" . "https://melpa.org/packages/")
- ("melpa-stable" . "https://stable.melpa.org/packages/")
- ("plexus-elpa" . "https://plexus.github.io/elpa/")))
-
-
-(package-initialize)
-(package-refresh-contents)
-
-;; Emacs before 25.1
-(when (not (fboundp 'let-alist))
- (package-install 'let-alist))
-
-(package-install 'package-lint)
-(package-install 'a)
-(package-install 'dash)
-(package-install 'edn) ;; required for the edn test suite
-
-(setq clj-parse-load-files '("clj-parse.el"
- "clj-lex.el"
- "tests/clj-parse-test.el"
- "tests/clj-lex-test.el"
- "tests/edn-el-test-suite.el"))
-
-(let ((pwd (replace-regexp-in-string "\n\\'" "" (shell-command-to-string
"pwd"))))
-
- (add-to-list 'load-path pwd)
-
- (dolist (file clj-parse-load-files)
- (load (concat pwd "/" file)))
-
- (if (getenv "CLJ_PARSE_LINT")
- (let ((success t))
- (dolist (file clj-parse-load-files)
- (with-temp-buffer
- (insert-file-contents file t)
- (emacs-lisp-mode)
- (let ((checking-result (package-lint-buffer)))
- (when checking-result
- (setq success nil)
- (message "In `%s':" file)
- (pcase-dolist (`(,line ,col ,type ,message) checking-result)
- (message " at %d:%d: %s: %s" line col type message))))))
- (kill-emacs (if success 0 1)))
- (ert-run-tests-batch-and-exit)))
diff --git a/clj-parse.el b/clj-parse.el
index c3d9a6f3e5..cfccdb59f8 100644
--- a/clj-parse.el
+++ b/clj-parse.el
@@ -4,7 +4,7 @@
;; Author: Arne Brasseur <arne@arnebrasseur.net>
;; Keywords: lisp
-;; Package-Requires: ((dash "2.12.0") (emacs "25") (a "0.1.0alpha2"))
+;; Package-Requires: ((emacs "25") (a "0.1.0alpha4"))
;; Version: 0.1.0
;; This file is not part of GNU Emacs.
@@ -30,10 +30,12 @@
;;; Code:
-(require 'a)
-(require 'dash)
(require 'cl-lib)
+(require 'a)
+
(require 'clj-lex)
+(require 'clj-edn)
+(require 'clj-ast)
(defvar clj-parse--leaf-tokens '(:whitespace
:comment
@@ -117,7 +119,7 @@
(:rparen :lparen)
(:rbracket :lbracket)
(:rbrace (clj-lex-token-type
- (-find (lambda (token) (member (clj-lex-token-type token)
'(:lbrace :set))) stack)))))
+ (seq-find (lambda (token) (member (clj-lex-token-type token)
'(:lbrace :set))) stack)))))
(defun clj-parse--reduce-coll (stack closer-token reduceN)
"Reduce collection based on the top of the stack"
@@ -161,120 +163,6 @@
stack))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Reducer implementations
-
-(defun clj-parse--make-node (type position &rest kvs)
- (apply 'a-list ':node-type type ':position position kvs))
-
-;; AST
-
-(defun clj-parse--ast-reduce-leaf (stack token)
- (if (eq (clj-lex-token-type token) :whitespace)
- stack
- (push
- (clj-parse--make-node (clj-lex-token-type token) (a-get token 'pos)
- ':form (a-get token 'form)
- ':value (clj-parse--leaf-token-value token))
- stack)))
-
-(defun clj-parse--ast-reduce-node (stack opener-token children)
- (let* ((pos (a-get opener-token 'pos))
- (type (cl-case (clj-lex-token-type opener-token)
- (:root :root)
- (:lparen :list)
- (:lbracket :vector)
- (:set :set)
- (:lbrace :map)
- (:discard :discard))))
- (cl-case type
- (:root (clj-parse--make-node :root 0 ':children children))
- (:discard stack)
- (t (push
- (clj-parse--make-node type pos
- ':children children)
- stack)))))
-
-(defun clj-parse-ast ()
- (clj-parse-reduce #'clj-parse--ast-reduce-leaf #'clj-parse--ast-reduce-node))
-
-; Elisp
-
-(defun clj-parse--edn-reduce-leaf (stack token)
- (if (member (clj-lex-token-type token) (list :whitespace :comment))
- stack
- (push (clj-parse--leaf-token-value token) stack)))
-
-(defun clj-parse--edn-reduce-node (tag-readers)
- (lambda (stack opener-token children)
- (let ((token-type (clj-lex-token-type opener-token)))
- (if (member token-type '(:root :discard))
- stack
- (push
- (cl-case token-type
- (:lparen children)
- (:lbracket (apply #'vector children))
- (:set (list 'edn-set children))
- (:lbrace (let* ((kvs (seq-partition children 2))
- (hash-map (make-hash-table :test 'equal :size
(length kvs))))
- (seq-do (lambda (pair)
- (puthash (car pair) (cadr pair) hash-map))
- kvs)
- hash-map))
- (:tag (let* ((tag (intern (substring (a-get opener-token 'form) 1)))
- (reader (a-get tag-readers tag :missing)))
- (when (eq :missing reader)
- (user-error "No reader for tag #%S in %S" tag (a-keys
tag-readers)))
- (funcall reader (car children)))))
- stack)))))
-
-(defvar clj-edn-default-tag-readers
- (a-list 'inst (lambda (s)
- (cl-list* 'edn-inst (date-to-time s)))
- 'uuid (lambda (s)
- (list 'edn-uuid s)))
- "Default reader functions for handling tagged literals in EDN.
-These are the ones defined in the EDN spec, #inst and #uuid. It
-is not recommended you change this variable, as this globally
-changes the behavior of the EDN reader. Instead pass your own
-handlers as an optional argument to the reader functions.")
-
-(defun clj-parse-edn (&optional tag-readers)
- (clj-parse-reduce #'clj-parse--edn-reduce-leaf
- (clj-parse--edn-reduce-node (a-merge
clj-edn-default-tag-readers tag-readers))))
-
-(defun clj-parse-edn-str (s &optional tag-readers)
- (with-temp-buffer
- (insert s)
- (goto-char 1)
- (car (clj-parse-edn tag-readers))))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Printer implementations
-
-;; AST
-
-(defun clj-parse--reduce-string-leaf (leaf)
- (alist-get ':form leaf))
-
-(defun clj-parse--string-with-delimiters (nodes ld rd)
- (concat ld
- (mapconcat #'clj-parse-ast-print nodes " ")
- rd))
-
-(defun clj-parse-ast-print (node)
- (if (clj-parse--is-leaf? node)
- (clj-parse--reduce-string-leaf node)
- (let ((subnodes (alist-get ':children node)))
- (cl-case (a-get node ':node-type)
- (:root (clj-parse--string-with-delimiters subnodes "" ""))
- (:list (clj-parse--string-with-delimiters subnodes "(" ")"))
- (:vector (clj-parse--string-with-delimiters subnodes "[" "]"))
- (:set (clj-parse--string-with-delimiters subnodes "#{" "}"))
- (:map (clj-parse--string-with-delimiters subnodes "{" "}"))
- ;; tagged literals
- ))))
-
(provide 'clj-parse)
;;; clj-parse.el ends here
diff --git a/test/clj-ast-test.el b/test/clj-ast-test.el
new file mode 100644
index 0000000000..5b383da516
--- /dev/null
+++ b/test/clj-ast-test.el
@@ -0,0 +1,68 @@
+;;; clj-ast-test.el --- Unit tests for AST parsing/unparsing
+
+;; Copyright (C) 2017 Arne Brasseur
+
+;; Author: Arne Brasseur <arne@arnebrasseur.net>
+
+;; This file is not part of GNU Emacs.
+
+;; This file is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; This file is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary
+
+;; Unit tests for AST parsing/unparsing
+
+;;; Code
+
+(require 'ert)
+(require 'clj-ast)
+
+(load "test/clj-parse-test-data.el")
+
+(defmacro define-clj-ast-parse-tests ()
+ `(progn
+ ,@(mapcar
+ (lambda (pair)
+ (let ((name (car pair))
+ (data (cdr pair)))
+ (if (and (a-get data :source) (a-get data :ast))
+ (let ((test-name (intern (concat "clj-ast-parse:" name))))
+ `(ert-deftest ,test-name ()
+ :tags '(clj-ast)
+ (with-temp-buffer
+ (insert ,(a-get data :source))
+ (goto-char 1)
+ (should (a-equal (clj-ast-parse) ',(a-get data
:ast)))))))))
+ clj-parse-test-data)))
+
+(defmacro define-clj-ast-roundtrip-tests ()
+ `(progn
+ ,@(mapcar
+ (lambda (pair)
+ (let ((name (car pair))
+ (data (cdr pair)))
+ (if (and (a-get data :ast) (a-get data :source))
+ (let ((test-name (intern (concat "clj-ast-rountrip:" name))))
+ `(ert-deftest ,test-name ()
+ :tags '(clj-ast-rountrip)
+ (should (a-equal (clj-ast-parse-str (clj-ast-unparse-str
',(a-get data :ast))) ',(a-get data :ast))))))))
+ clj-parse-test-data)))
+
+
+(define-clj-ast-roundtrip-tests)
+(define-clj-ast-parse-tests)
+
+;;; clj-ast-test.el ends here
diff --git a/test/clj-ast-unparse-test.el b/test/clj-ast-unparse-test.el
new file mode 100644
index 0000000000..798aba4f32
--- /dev/null
+++ b/test/clj-ast-unparse-test.el
@@ -0,0 +1,166 @@
+;;; clj-ast-unparse-test.el --- Print Clojure AST back to code - tests
+
+;; Copyright (C) 2017 Arne Brasseur
+
+;; Author: Arne Brasseur <arne@arnebrasseur.net>
+
+;; This file is not part of GNU Emacs.
+
+;; This file is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; This file is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; Print Clojure AST back to code - tests
+
+;;; Code:
+
+(require 'ert)
+(require 'clj-ast)
+
+;;; Printer modes
+;; ----------------------------------------------------------------------------
+
+(ert-deftest clj-ast-unparse-list ()
+ (should (equal "(0 1 2)"
+ (clj-ast-unparse-str '((:node-type . :root)
+ (:position . 0)
+ (:children . (((:node-type . :list)
+ (:position . 1)
+ (:children .
(((:node-type . :number)
+
(:position . 2)
+ (:form .
"0")
+ (:value
. 0))
+
((:node-type . :number)
+
(:position . 4)
+ (:form .
"1")
+ (:value
. 1))
+
((:node-type . :number)
+
(:position . 6)
+ (:form .
"2")
+ (:value
. 2))))))))))))
+
+(ert-deftest clj-ast-unparse-empty-list ()
+ (should (equal "()"
+ (clj-ast-unparse-str '((:node-type . :root)
+ (:position . 0)
+ (:children . (((:node-type . :list)
+ (:position . 1)
+ (:children .
nil)))))))))
+
+(ert-deftest clj-ast-unparse-nested-list ()
+ (should (equal "((.9 abc (true) (hello)))"
+ (clj-ast-unparse-str '((:node-type . :root)
+ (:position . 0)
+ (:children . (((:node-type . :list)
+ (:position . 1)
+ (:children .
(((:node-type . :list)
+
(:position . 2)
+
(:children ((:node-type . :number)
+
(:position . 3)
+
(:form . ".9")
+
(:value . 0.9))
+
((:node-type . :symbol)
+
(:position . 6)
+
(:form . "abc")
+
(:value . abc))
+
((:node-type . :list)
+
(:position . 10)
+
(:children ((:node-type . :true)
+
(:position . 11)
+
(:form . "true")
+
(:value . t))))
+
((:node-type . :list)
+
(:position . 17)
+
(:children ((:node-type . :symbol)
+
(:position . 18)
+
(:form . "hello")
+
(:value . hello))))))))))))))))
+
+(ert-deftest clj-ast-unparse-string ()
+ (should (equal "\"abc hello \\t\\\"x\""
+ (clj-ast-unparse-str '((:node-type . :root)
+ (:position . 0)
+ (:children . (((:node-type . :string)
+ (:position . 1)
+ (:form . "\"abc hello
\\t\\\"x\"")
+ (:value . "abc hello
\t\"x")))))))))
+
+(ert-deftest clj-ast-unparse-chars ()
+ (should (equal "(\\newline \\return \\space \\tab \\a \\b \\c \\u0078
\\o171)"
+ (clj-ast-unparse-str '((:node-type . :root)
+ (:position . 0)
+ (:children . (((:node-type . :list)
+ (:position . 1)
+ (:children .
(((:node-type . :character) (:position . 2) (:form . "\\newline") (:value .
?\n))
+
((:node-type . :character) (:position . 11) (:form . "\\return") (:value . ?\r))
+
((:node-type . :character) (:position . 19) (:form . "\\space") (:value . 32))
+
((:node-type . :character) (:position . 26) (:form . "\\tab") (:value . ?\t))
+
((:node-type . :character) (:position . 31) (:form . "\\a") (:value . ?a))
+
((:node-type . :character) (:position . 34) (:form . "\\b") (:value . ?b))
+
((:node-type . :character) (:position . 37) (:form . "\\c") (:value . ?c))
+
((:node-type . :character) (:position . 40) (:form . "\\u0078") (:value . ?x))
+
((:node-type . :character) (:position . 47) (:form . "\\o171") (:value .
?y)))))))))
+ )))
+
+(ert-deftest clj-ast-unparse-keyword ()
+ (should (equal ":foo-bar"
+ (clj-ast-unparse-str '((:node-type . :root)
+ (:position . 0)
+ (:children . (((:node-type . :keyword)
+ (:position . 1)
+ (:form . ":foo-bar")
+ (:value .
:foo-bar)))))))))
+
+(ert-deftest clj-ast-unparse-vector ()
+ (should (equal "[123]"
+ (clj-ast-unparse-str '((:node-type . :root)
+ (:position . 0)
+ (:children . (((:node-type . :vector)
+ (:position . 1)
+ (:children .
(((:node-type . :number)
+
(:position . 2)
+ (:form .
"123")
+ (:value
. 123))))))))))))
+
+(ert-deftest clj-ast-unparse-map ()
+ (should (equal "{:count 123}"
+ (clj-ast-unparse-str '((:node-type . :root)
+ (:position . 0)
+ (:children . (((:node-type . :map)
+ (:position . 1)
+ (:children .
(((:node-type . :keyword)
+
(:position . 2)
+ (:form .
":count")
+ (:value
. :count))
+
((:node-type . :number)
+
(:position . 9)
+ (:form .
"123")
+ (:value
. 123))))))))))))
+
+(ert-deftest clj-ast-unparse-set ()
+ (should (equal "#{:x}"
+ (clj-ast-unparse-str '((:node-type . :root)
+ (:position . 0)
+ (:children . (((:node-type . :set)
+ (:position . 1)
+ (:children .
(((:node-type . :keyword)
+
(:position . 3)
+ (:form .
":x")
+ (:value
. :x))))))))))))
+
+(provide 'clj-unparse-test)
+
+;;; clj-ast-unparse-test.el ends here
diff --git a/test/clj-edn-el-parity-test.el b/test/clj-edn-el-parity-test.el
new file mode 100644
index 0000000000..bae4d41609
--- /dev/null
+++ b/test/clj-edn-el-parity-test.el
@@ -0,0 +1,286 @@
+;;; edn-el-parity.el --- Tests from edn.el
+
+;; Author: Lars Andersen <expez@expez.com>, Arne Brasseur
<arne@arnebrasseur.net>
+
+;; Copyright (C) 2015 Lars Andersen
+
+;; This file is not part of GNU Emacs.
+
+;; This file is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; This file is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; These tests are copied verbatim from the edn.el source, and adapted to use
+;; our API. This way we assure that clj-parse can act as a drop-in replacement
+;; for edn.el.
+
+;;; Code:
+
+(require 'ert)
+(require 'clj-parse)
+(eval-when-compile (require 'subr-x)) ;; for things like hash-table-keys
+
+(ert-deftest whitespace ()
+ (should (null (clj-edn-read-str "")))
+ (should (null (clj-edn-read-str " ")))
+ (should (null (clj-edn-read-str " ")))
+ (should (null (clj-edn-read-str " ")))
+ (should (null (clj-edn-read-str " ")))
+ (should (null (clj-edn-read-str ",")))
+ (should (null (clj-edn-read-str ",,,,")))
+ (should (null (clj-edn-read-str " , ,\n")))
+ (should (null (clj-edn-read-str "\n ,, ")))
+ (should (equal [a b c d] (clj-edn-read-str "[a ,,,,,, b,,,,,c ,d]"))))
+
+(ert-deftest symbols ()
+ :tags '(edn symbol)
+ (should (equal 'foo (clj-edn-read-str "foo")))
+ (should (equal 'foo\. (clj-edn-read-str "foo.")))
+ (should (equal '%foo\. (clj-edn-read-str "%foo.")))
+ (should (equal 'foo/bar (clj-edn-read-str "foo/bar")))
+ (equal 'some\#sort\#of\#symbol (clj-edn-read-str "some#sort#of#symbol"))
+ (equal 'truefalse (clj-edn-read-str "truefalse"))
+ (equal 'true. (clj-edn-read-str "true."))
+ (equal '/ (clj-edn-read-str "/"))
+ (should (equal '.true (clj-edn-read-str ".true")))
+ (should (equal 'some:sort:of:symbol (clj-edn-read-str
"some:sort:of:symbol")))
+ (equal 'foo-bar (clj-edn-read-str "foo-bar"))
+ (should (equal '+some-symbol (clj-edn-read-str "+some-symbol")))
+ (should (equal '-symbol (clj-edn-read-str "-symbol"))))
+
+(ert-deftest booleans ()
+ :tags '(edn boolean)
+ (should (equal t (clj-edn-read-str "true")))
+ (should (equal nil (clj-edn-read-str "false "))))
+
+(ert-deftest characters ()
+ :tags '(edn characters)
+ (should (equal 97 (clj-edn-read-str "\\a")))
+ (should (equal 960 (clj-edn-read-str "\\u03C0")))
+ ;;(should (equal 'newline (clj-edn-read-str "\\newline")))
+ )
+
+(ert-deftest elision ()
+ :tags '(edn elision)
+ (should-not (clj-edn-read-str "#_foo"))
+ (should-not (clj-edn-read-str "#_ 123"))
+ (should-not (clj-edn-read-str "#_:foo"))
+ (should-not (clj-edn-read-str "#_ \\a"))
+ (should-not (clj-edn-read-str "#_
+\"foo\""))
+ (should-not (clj-edn-read-str "#_ (1 2 3)"))
+ (should (equal '(1 3) (clj-edn-read-str "(1 #_ 2 3)")))
+ (should (equal '[1 2 3 4] (clj-edn-read-str "[1 2 #_[4 5 6] 3 4]")))
+ (should (map-equal (make-seeded-hash-table :foo :bar)
+ (clj-edn-read-str "{:foo #_elided :bar}")))
+ (should (equal '(edn-set (1 2 3 4))
+ (clj-edn-read-str "#{1 2 #_[1 2 3] 3 #_ (1 2) 4}")))
+ (should (equal [a d] (clj-edn-read-str "[a #_ ;we are discarding what comes
next
+ c d]"))))
+
+(ert-deftest string ()
+ :tags '(edn string)
+ (should (equal "this is a string" (clj-edn-read-str "\"this is a string\"")))
+ (should (equal "this has an escaped \"quote in it"
+ (clj-edn-read-str "\"this has an escaped \\\"quote in it\"")))
+ (should (equal "foo\tbar" (clj-edn-read-str "\"foo\\tbar\"")))
+ (should (equal "foo\nbar" (clj-edn-read-str "\"foo\\nbar\"")))
+ (should (equal "this is a string \\ that has an escaped backslash"
+ (clj-edn-read-str "\"this is a string \\\\ that has an
escaped backslash\"")))
+ (should (equal "[" (clj-edn-read-str "\"[\""))))
+
+(ert-deftest keywords ()
+ :tags '(edn keywords)
+ (should (equal :namespace\.of\.some\.length/keyword-name
+ (clj-edn-read-str ":namespace.of.some.length/keyword-name")))
+ (should (equal :\#/\# (clj-edn-read-str ":#/#")))
+ (should (equal :\#/:a (clj-edn-read-str ":#/:a")))
+ (should (equal :\#foo (clj-edn-read-str ":#foo"))))
+
+(ert-deftest integers ()
+ :tags '(edn integers)
+ (should (= 0 (clj-edn-read-str "0")))
+ (should (= 0 (clj-edn-read-str "+0")))
+ (should (= 0 (clj-edn-read-str "-0")))
+ (should (= 100 (clj-edn-read-str "100")))
+ (should (= -100 (clj-edn-read-str "-100"))))
+
+(ert-deftest floats ()
+ :tags '(edn floats)
+ (should (= 12.32 (clj-edn-read-str "12.32")))
+ (should (= -12.32 (clj-edn-read-str "-12.32")))
+ (should (= 9923.23 (clj-edn-read-str "+9923.23")))
+ (should (= 4.5e+044 (clj-edn-read-str "45e+43")))
+ (should (= -4.5e-042 (clj-edn-read-str "-45e-43")))
+ (should (= 4.5e+044 (clj-edn-read-str "45E+43"))))
+
+(ert-deftest lists ()
+ :tags '(edn lists)
+ (should-not (clj-edn-read-str "()"))
+ (should (equal '(1 2 3) (clj-edn-read-str "( 1 2 3)")))
+ (should (equal '(12.1 ?a foo :bar) (clj-edn-read-str "(12.1 \\a foo :bar)")))
+ (should (equal '((:foo bar :bar 12)) (clj-edn-read-str "( (:foo bar :bar
12))")))
+ (should (equal
+ '(defproject com\.thortech/data\.edn "0.1.0-SNAPSHOT")
+ (clj-edn-read-str "(defproject com.thortech/data.edn
\"0.1.0-SNAPSHOT\")"))))
+
+(ert-deftest vectors ()
+ :tags '(edn vectors)
+ (should (equal [] (clj-edn-read-str "[]")))
+ (should (equal [] (clj-edn-read-str "[ ]")))
+ (should (equal '[1 2 3] (clj-edn-read-str "[ 1 2 3 ]")))
+ (should (equal '[12.1 ?a foo :bar] (clj-edn-read-str "[ 12.1 \\a foo
:bar]")))
+ (should (equal '[[:foo bar :bar 12]] (clj-edn-read-str "[[:foo bar :bar
12]]")))
+ (should (equal '[( :foo bar :bar 12 ) "foo"]
+ (clj-edn-read-str "[(:foo bar :bar 12) \"foo\"]")))
+ (should (equal '[/ \. * ! _ \? $ % & = - +]
+ (clj-edn-read-str "[/ . * ! _ ? $ % & = - +]")))
+ (should (equal
+ ;;[99 newline return space tab]
+ [99 10 13 32 9]
+ (clj-edn-read-str "[\\c \\newline \\return \\space \\tab]"))))
+
+(defun map-equal (m1 m2)
+ (and (and (hash-table-p m1) (hash-table-p m2))
+ (eq (hash-table-test m1) (hash-table-test m2))
+ (= (hash-table-count m1) (hash-table-count m2))
+ (equal (hash-table-keys m1) (hash-table-keys m2))
+ (equal (hash-table-values m1) (hash-table-values m2))))
+
+(defun make-seeded-hash-table (&rest keys-and-values)
+ (let ((m (make-hash-table :test #'equal)))
+ (while keys-and-values
+ (puthash (pop keys-and-values) (pop keys-and-values) m))
+ m))
+
+(ert-deftest maps ()
+ :tags '(edn maps)
+ (should (hash-table-p (clj-edn-read-str "{ }")))
+ (should (hash-table-p (clj-edn-read-str "{}")))
+ (should (map-equal (make-seeded-hash-table :foo :bar :baz :qux)
+ (clj-edn-read-str "{ :foo :bar :baz :qux}")))
+ (should (map-equal (make-seeded-hash-table 1 "123" 'vector [1 2 3])
+ (clj-edn-read-str "{ 1 \"123\" vector [1 2 3]}")))
+ (should (map-equal (make-seeded-hash-table [1 2 3] "some numbers")
+ (clj-edn-read-str "{[1 2 3] \"some numbers\"}"))))
+
+(ert-deftest sets ()
+ :tags '(edn sets)
+ (should (eq 'edn-set (car (clj-edn-read-str "#{}"))))
+ (should (eq 'edn-set (car (clj-edn-read-str "#{ }"))))
+ (should (equal '(edn-set (1 2 3)) (clj-edn-read-str "#{1 2 3}")))
+ (should (equal '(edn-set (1 [1 2 3] 3)) (clj-edn-read-str "#{1 [1 2 3]
3}"))))
+
+(ert-deftest comment ()
+ :tags '(edn comments)
+ (should-not (clj-edn-read-str ";nada"))
+ (should (equal 1 (clj-edn-read-str ";; comment
+1")))
+ (should (equal [1 2 3] (clj-edn-read-str "[1 2 ;comment to eol
+3]")))
+ (should (equal '[valid more items] (clj-edn-read-str "[valid;touching
trailing comment
+ more items]")))
+ (should (equal [valid vector more vector items] (clj-edn-read-str "[valid
vector
+ ;;comment in vector
+ more vector items]"))))
+
+(defun test-val-passed-to-handler (val)
+ (should (listp val))
+ (should (= (length val) 2))
+ (should (= 1 (car val)))
+ 1)
+
+(setq clj-edn-test-extra-handlers
+ (a-list
+ 'my/type #'test-val-passed-to-handler
+ 'my/other-type (lambda (val) 2)))
+
+(ert-deftest tags ()
+ :tags '(edn tags)
+ (should-error (clj-edn-read-str "#my/type value"
clj-edn-test-extra-handlers))
+ (should (= 1 (clj-edn-read-str "#my/type (1 2)"
clj-edn-test-extra-handlers)))
+ (should (= 2 (clj-edn-read-str "#my/other-type {:foo :bar}"
clj-edn-test-extra-handlers)))
+ (should-error (clj-edn-read-str "#myapp/Person {:first \"Fred\" :last
\"Mertz\"}")))
+
+(ert-deftest roundtrip ()
+ :tags '(edn roundtrip)
+ (let ((data [1 2 3 :foo (4 5) qux "quux"]))
+ (should (equal data (clj-edn-read-str (clj-edn-print-str data))))
+ (should (map-equal (make-seeded-hash-table :foo :bar)
+ (clj-edn-read-str (clj-edn-print-str
(make-seeded-hash-table :foo :bar)))))
+ (should (equal '(edn-set (1 2 3 [3 1.11]))
+ (clj-edn-read-str (clj-edn-print-str '(edn-set (1 2 3 [3
1.11]))))))))
+
+(ert-deftest inst ()
+ :tags '(edn inst)
+ (let* ((inst-str "#inst \"1985-04-12T23:20:50.52Z\"")
+ (inst (clj-edn-read-str inst-str))
+ (time (date-to-time "1985-04-12T23:20:50.52Z")))
+ (should (eq 'edn-inst (car inst)))
+ (should (equal time (cdr inst)))))
+
+(ert-deftest uuid ()
+ :tags '(edn uuid)
+ (let* ((str "f81d4fae-7dec-11d0-a765-00a0c91e6bf6")
+ (uuid (clj-edn-read-str (concat "#uuid \"" str "\""))))
+ (should (eq 'edn-uuid (car uuid)))))
+
+;; (ert-deftest invalid-edn ()
+;; (should-error (clj-edn-read-str "///"))
+;; (should-error (clj-edn-read-str "~cat"))
+;; (should-error (clj-edn-read-str "foo/bar/baz/qux/quux"))
+;; (should-error (clj-edn-read-str "#foo/"))
+;; (should-error (clj-edn-read-str "foo/"))
+;; (should-error (clj-edn-read-str ":foo/"))
+;; (should-error (clj-edn-read-str "#/foo"))
+;; (should-error (clj-edn-read-str "/symbol"))
+;; (should-error (clj-edn-read-str ":/foo"))
+;; (should-error (clj-edn-read-str "+5symbol"))
+;; (should-error (clj-edn-read-str ".\\newline"))
+;; (should-error (clj-edn-read-str "0cat"))
+;; (should-error (clj-edn-read-str "-4cats"))
+;; (should-error (clj-edn-read-str ".9"))
+;; (should-error (clj-edn-read-str ":keyword/with/too/many/slashes"))
+;; (should-error (clj-edn-read-str ":a.b.c/"))
+;; (should-error (clj-edn-read-str "\\itstoolong"))
+;; (should-error (clj-edn-read-str ":#/:"))
+;; (should-error (clj-edn-read-str "/foo//"))
+;; (should-error (clj-edn-read-str "///foo"))
+;; (should-error (clj-edn-read-str ":{}"))
+;; (should-error (clj-edn-read-str "//"))
+;; (should-error (clj-edn-read-str "##"))
+;; (should-error (clj-edn-read-str "::"))
+;; (should-error (clj-edn-read-str "::a"))
+;; (should-error (clj-edn-read-str ".5symbol"))
+;; (should-error (clj-edn-read-str "{ \"foo\""))
+;; (should-error (clj-edn-read-str "{ \"foo\" :bar"))
+;; (should-error (clj-edn-read-str "{"))
+;; (should-error (clj-edn-read-str ":{"))
+;; (should-error (clj-edn-read-str "{{"))
+;; (should-error (clj-edn-read-str "}"))
+;; (should-error (clj-edn-read-str ":}"))
+;; (should-error (clj-edn-read-str "}}"))
+;; (should-error (clj-edn-read-str "#:foo"))
+;; (should-error (clj-edn-read-str "\\newline."))
+;; (should-error (clj-edn-read-str "\\newline0.1"))
+;; (should-error (clj-edn-read-str "^"))
+;; (should-error (clj-edn-read-str ":^"))
+;; (should-error (clj-edn-read-str "_:^"))
+;; (should-error (clj-edn-read-str "#{{[}}"))
+;; (should-error (clj-edn-read-str "[}"))
+;; (should-error (clj-edn-read-str "@cat")))
+
+;;; edn-el-parity-test.el ends here
diff --git a/test/clj-edn-test.el b/test/clj-edn-test.el
new file mode 100644
index 0000000000..310b1324fa
--- /dev/null
+++ b/test/clj-edn-test.el
@@ -0,0 +1,77 @@
+;;; clj-edn-test.el --- Unit tests for EDN reading/printing
+
+;; Copyright (C) 2017 Arne Brasseur
+
+;; Author: Arne Brasseur <arne@arnebrasseur.net>
+
+;; This file is not part of GNU Emacs.
+
+;; This file is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; This file is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary
+
+;; Unit tests for EDN reading/printing
+
+;;; Code
+
+(require 'ert)
+(require 'clj-parse)
+
+(load "test/clj-parse-test-data.el")
+
+(ert-deftest clj-edn-print-test ()
+ (should (equal (clj-edn-print-str nil) "nil"))
+ (should (equal (clj-edn-print-str 100) "100"))
+ (should (equal (clj-edn-print-str 1.2) "1.2"))
+ (should (equal (clj-edn-print-str [1 2 3]) "[1 2 3]"))
+ (should (equal (clj-edn-print-str t) "true")))
+
+(ert-deftest clj-edn-read-test ()
+ (should (equal (clj-edn-read-str "true") t)))
+
+(defmacro define-clj-edn-read-tests ()
+ `(progn
+ ,@(mapcar
+ (lambda (pair)
+ (let ((name (car pair))
+ (data (cdr pair)))
+ (if (and (a-get data :edn) (a-get data :source))
+ (let ((test-name (intern (concat "clj-edn-read:" name))))
+ `(ert-deftest ,test-name ()
+ :tags '(clj-edn)
+ (with-temp-buffer
+ (insert ,(a-get data :source))
+ (goto-char 1)
+ (should (a-equal (clj-edn-read) ',(a-get data
:edn)))))))))
+ clj-parse-test-data)))
+
+(defmacro define-clj-edn-roundtrip-tests ()
+ `(progn
+ ,@(mapcar
+ (lambda (pair)
+ (let ((name (car pair))
+ (data (cdr pair)))
+ (if (and (a-get data :edn) (a-get data :source) (member
:edn-roundtrip (a-get data :tags)))
+ (let ((test-name (intern (concat "clj-edn-rountrip:" name))))
+ `(ert-deftest ,test-name ()
+ :tags '(clj-edn-rountrip)
+ (should (equal (clj-edn-print-str (car ',(a-get data
:edn))) ,(a-get data :source))))))))
+ clj-parse-test-data)))
+
+(define-clj-edn-read-tests)
+(define-clj-edn-roundtrip-tests)
+
+;;; clj-edn-test.el
diff --git a/tests/clj-lex-test.el b/test/clj-lex-test.el
similarity index 99%
rename from tests/clj-lex-test.el
rename to test/clj-lex-test.el
index b50de580f2..ae8325b741 100644
--- a/tests/clj-lex-test.el
+++ b/test/clj-lex-test.el
@@ -1,4 +1,4 @@
-;;; clj-lex-test.el --- Clojure/EDN parser
+;;; clj-lex-test.el --- Unit tests for the lexer
;; Copyright (C) 2017 Arne Brasseur
@@ -21,8 +21,14 @@
;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
-(require 'clj-lex)
+;;; Commentary
+
+;; Unit tests for the lexer
+
+;;; Code
+
(require 'ert)
+(require 'clj-lex)
(ert-deftest clj-lex-test-next ()
(with-temp-buffer
diff --git a/test/clj-parse-test-data.el b/test/clj-parse-test-data.el
new file mode 100644
index 0000000000..d6f5645d9d
--- /dev/null
+++ b/test/clj-parse-test-data.el
@@ -0,0 +1,298 @@
+;;; clj-parse-test-data.el --- Clojure/EDN parser - test data
+
+;; Copyright (C) 2017 Arne Brasseur
+
+;; Author: Arne Brasseur <arne@arnebrasseur.net>
+
+;; This file is not part of GNU Emacs.
+
+;; This file is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; This file is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; Test data for reader / parser / printer / unparser
+
+;;; Code:
+
+(setq clj-parse-test-data
+ (a-list
+
+ "simple-list"
+ (a-list
+ :tags '(:edn-roundtrip)
+ :source "(1 2 3)"
+ :edn '((1 2 3))
+ :ast '((:node-type . :root)
+ (:position . 0)
+ (:children . (((:node-type . :list)
+ (:position . 1)
+ (:children . (((:node-type . :number)
+ (:position . 2)
+ (:form . "1")
+ (:value . 1))
+ ((:node-type . :number)
+ (:position . 4)
+ (:form . "2")
+ (:value . 2))
+ ((:node-type . :number)
+ (:position . 6)
+ (:form . "3")
+ (:value . 3)))))))))
+
+
+ "empty-list"
+ (a-list
+ :source "()"
+ :edn '(())
+ :ast '((:node-type . :root)
+ (:position . 0)
+ (:children . (((:node-type . :list)
+ (:position . 1)
+ (:children . nil))))))
+
+ "size-1"
+ (a-list
+ :tags '(:edn-roundtrip)
+ :source "(1)"
+ :edn '((1))
+ :ast '((:node-type . :root)
+ (:position . 0)
+ (:children . (((:node-type . :list)
+ (:position . 1)
+ (:children . (((:node-type . :number)
+ (:position . 2)
+ (:form . "1")
+ (:value . 1)))))))))
+
+ "leafs"
+ (a-list
+ :source "(nil true false hello-world)"
+ :edn '((nil t nil hello-world))
+ :ast '((:node-type . :root)
+ (:position . 0)
+ (:children . (((:node-type . :list)
+ (:position . 1)
+ (:children . (((:node-type . :nil)
+ (:position . 2)
+ (:form . "nil")
+ (:value . nil))
+ ((:node-type . :true)
+ (:position . 6)
+ (:form . "true")
+ (:value . t))
+ ((:node-type . :false)
+ (:position . 11)
+ (:form . "false")
+ (:value . nil))
+ ((:node-type . :symbol)
+ (:position . 17)
+ (:form . "hello-world")
+ (:value . hello-world)))))))))
+
+ "qualified-symbol"
+ (a-list
+ :tags '(:edn-roundtrip)
+ :source "clojure.string/join"
+ :edn '(clojure.string/join)
+ :ast '((:node-type . :root)
+ (:position . 0)
+ (:children . (((:node-type . :symbol)
+ (:position . 1)
+ (:form . "clojure.string/join")
+ (:value . clojure.string/join))))))
+
+ "nested-lists"
+ (a-list
+ :source "((.9 abc (true) (hello)))"
+ :edn '(((0.9 abc (t) (hello))))
+ :ast '((:node-type . :root)
+ (:position . 0)
+ (:children . (((:node-type . :list)
+ (:position . 1)
+ (:children . (((:node-type . :list)
+ (:position . 2)
+ (:children ((:node-type . :number)
+ (:position . 3)
+ (:form . ".9")
+ (:value . 0.9))
+ ((:node-type . :symbol)
+ (:position . 6)
+ (:form . "abc")
+ (:value . abc))
+ ((:node-type . :list)
+ (:position . 10)
+ (:children ((:node-type .
:true)
+ (:position .
11)
+ (:form .
"true")
+ (:value .
t))))
+ ((:node-type . :list)
+ (:position . 17)
+ (:children ((:node-type .
:symbol)
+ (:position .
18)
+ (:form .
"hello")
+ (:value .
hello)))))))))))))
+
+ "strings-1"
+ (a-list
+ :tags '(:edn-roundtrip)
+ :source "\"abc hello \\t\\\"x\""
+ :edn '("abc hello \t\"x")
+ :ast '((:node-type . :root)
+ (:position . 0)
+ (:children . (((:node-type . :string)
+ (:position . 1)
+ (:form . "\"abc hello \\t\\\"x\"")
+ (:value . "abc hello \t\"x"))))))
+
+ "strings-2"
+ (a-list
+ :source "(\"---\\f---\\\"-'\\'-\\\\-\\r\\n\")"
+ :edn '(("---\f---\"-''-\\-\r\n"))
+ :ast '((:node-type . :root)
+ (:position . 0)
+ (:children . (((:node-type . :list)
+ (:position . 1)
+ (:children . (((:node-type . :string)
+ (:position . 2)
+ (:form .
"\"---\\f---\\\"-'\\'-\\\\-\\r\\n\"")
+ (:value .
"---\f---\"-''-\\-\r\n")))))))))
+
+ "chars-1"
+ (a-list
+ :source "(\\newline \\return \\space \\tab \\a \\b \\c \\u0078 \\o171)"
+ :edn '((?\n ?\r ?\ ?\t ?a ?b ?c ?x ?y))
+ :ast '((:node-type . :root)
+ (:position . 0)
+ (:children . (((:node-type . :list)
+ (:position . 1)
+ (:children . (((:node-type . :character) (:position
. 2) (:form . "\\newline") (:value . ?\n))
+ ((:node-type . :character) (:position
. 11) (:form . "\\return") (:value . ?\r))
+ ((:node-type . :character) (:position
. 19) (:form . "\\space") (:value . 32))
+ ((:node-type . :character) (:position
. 26) (:form . "\\tab") (:value . ?\t))
+ ((:node-type . :character) (:position
. 31) (:form . "\\a") (:value . ?a))
+ ((:node-type . :character) (:position
. 34) (:form . "\\b") (:value . ?b))
+ ((:node-type . :character) (:position
. 37) (:form . "\\c") (:value . ?c))
+ ((:node-type . :character) (:position
. 40) (:form . "\\u0078") (:value . ?x))
+ ((:node-type . :character) (:position
. 47) (:form . "\\o171") (:value . ?y)))))))))
+
+ "chars-2"
+ (a-list
+ :source "\"\\u0078 \\o171\""
+ :edn '("x y")
+ :ast '((:node-type . :root)
+ (:position . 0)
+ (:children . (((:node-type . :string)
+ (:position . 1)
+ (:form . "\"\\u0078 \\o171\"")
+ (:value . "x y"))))))
+
+ "keywords"
+ (a-list
+ :tags '(:edn-roundtrip)
+ :source ":foo-bar"
+ :edn '(:foo-bar)
+ :ast '((:node-type . :root)
+ (:position . 0)
+ (:children . (((:node-type . :keyword)
+ (:position . 1)
+ (:form . ":foo-bar")
+ (:value . :foo-bar))))))
+
+ "vector"
+ (a-list
+ :tags '(:edn-roundtrip)
+ :source "[123]"
+ :edn '([123])
+ :ast '((:node-type . :root)
+ (:position . 0)
+ (:children . (((:node-type . :vector)
+ (:position . 1)
+ (:children . (((:node-type . :number)
+ (:position . 2)
+ (:form . "123")
+ (:value . 123)))))))))
+
+ "map"
+ (a-list
+ :tags '(:edn-roundtrip)
+ :source "{:count 123}"
+ :edn (list (a-hash-table :count 123))
+ :ast '((:node-type . :root)
+ (:position . 0)
+ (:children . (((:node-type . :map)
+ (:position . 1)
+ (:children . (((:node-type . :keyword)
+ (:position . 2)
+ (:form . ":count")
+ (:value . :count))
+ ((:node-type . :number)
+ (:position . 9)
+ (:form . "123")
+ (:value . 123)))))))))
+
+ "set"
+ (a-list
+ :tags '(:edn-roundtrip)
+ :source "#{:x}"
+ :edn '((edn-set (:x)))
+ :ast '((:node-type . :root)
+ (:position . 0)
+ (:children . (((:node-type . :set)
+ (:position . 1)
+ (:children . (((:node-type . :keyword)
+ (:position . 3)
+ (:form . ":x")
+ (:value . :x)))))))))
+
+ "discard"
+ (a-list
+ :source "(10 #_11 12 #_#_ 13 14)"
+ :edn '((10 12))
+ :ast '((:node-type . :root)
+ (:position . 0)
+ (:children . (((:node-type . :list)
+ (:position . 1)
+ (:children . (((:node-type . :number)
+ (:position . 2)
+ (:form . "10")
+ (:value . 10))
+ ((:node-type . :number)
+ (:position . 10)
+ (:form . "12")
+ (:value . 12)))))))))
+
+
+ "tag"
+ (a-list
+ :source "#foo/bar [1]"
+ :ast '((:node-type . :root)
+ (:position . 0)
+ (:children . (((:node-type . :tag)
+ (:position . 1)
+ (:tag . foo/bar)
+ (:children . (((:node-type . :vector)
+ (:position . 10)
+ (:children . (((:node-type . :number)
+ (:position . 11)
+ (:form . "1")
+ (:value . 1))))))))))))
+
+ "booleans"
+ (a-list
+ :source "[nil true false]"
+ :edn '([nil t nil]))))
+
+;;; clj-parse-test-data.el ends here
diff --git a/test/clj-parse-test.el b/test/clj-parse-test.el
new file mode 100644
index 0000000000..172664cfb1
--- /dev/null
+++ b/test/clj-parse-test.el
@@ -0,0 +1,38 @@
+;;; clj-parse-test.el --- Clojure/EDN parser - tests
+
+;; Copyright (C) 2017 Arne Brasseur
+
+;; Author: Arne Brasseur <arne@arnebrasseur.net>
+
+;; This file is not part of GNU Emacs.
+
+;; This file is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; This file is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; A reader for EDN data files and parser for Clojure source files - tests
+
+;;; Code:
+
+(require 'ert)
+(require 'clj-parse)
+
+;; needs testing of individual functions. all testing now is at the top level
+;; through parse/unparse
+
+(provide 'clj-parse-test)
+
+;;; clj-parse-test.el ends here
diff --git a/test/test-helper.el b/test/test-helper.el
new file mode 100644
index 0000000000..ebc4a58ac2
--- /dev/null
+++ b/test/test-helper.el
@@ -0,0 +1,38 @@
+;;; test-helper.el --- unit test helper functions -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2017 Arne Brasseur
+
+;; Author: Arne Brasseur <arne@arnebrasseur.net>
+
+;; This file is not part of GNU Emacs.
+
+;; This file is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; This file is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; Unit Test setup and helper functions
+
+;;; Code:
+
+(message "Running tests on Emacs %s" emacs-version)
+
+(let* ((current-file (if load-in-progress load-file-name (buffer-file-name)))
+ (source-directory (locate-dominating-file current-file "Cask"))
+ ;; Do not load outdated byte code for tests
+ (load-prefer-newer t))
+ (add-to-list 'load-path source-directory))
+
+;; test-helper.el ends here
diff --git a/tests/clj-parse-test.el b/tests/clj-parse-test.el
deleted file mode 100644
index 726740b545..0000000000
--- a/tests/clj-parse-test.el
+++ /dev/null
@@ -1,404 +0,0 @@
-;;; clj-parse-test.el --- Clojure/EDN parser
-
-;; Copyright (C) 2017 Arne Brasseur
-
-;; Author: Arne Brasseur <arne@arnebrasseur.net>
-
-;; This file is not part of GNU Emacs.
-
-;; This file is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 3, or (at your option)
-;; any later version.
-
-;; This file is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
-
-;;; Commentary:
-
-;; A reader for EDN data files and parser for Clojure source files.
-
-;;; Code:
-
-(require 'a)
-(require 'ert)
-(require 'clj-parse)
-
-(defun clj-parse--equal (a b)
- (cond
- ((and (hash-table-p a) (hash-table-p b))
- (a-equal a b))
- ((and (consp a) (consp b))
- (and (clj-parse--equal (car a) (car b))
- (clj-parse--equal (cdr a) (cdr b))))
- (t (equal a b))))
-
-(defun clj-parse--deftest-mode (mode test-name test-string expected)
- (let* ((parse-fn (intern (concat "clj-parse-" mode)))
- (test-name (intern (concat (symbol-name parse-fn) "-" (symbol-name
test-name)))))
- `(ert-deftest ,test-name ()
- (with-temp-buffer
- (insert ,test-string)
- (goto-char 1)
- (should (clj-parse--equal (,parse-fn) ,expected))))))
-
-(defmacro clj-parse-deftest (test-name test-string mode-vs-expected-alist)
- (declare (indent defun))
- `(progn
- ,@(mapcar (lambda (vs) (clj-parse--deftest-mode (car vs)
- test-name
- test-string
- (cadr vs)))
- mode-vs-expected-alist)))
-
-
-;;; Parser modes
-;; ----------------------------------------------------------------------------
-
-(clj-parse-deftest simple-list "(1 2 3)"
- (("edn" '((1 2 3)))
- ("ast" '((:node-type . :root)
- (:position . 0)
- (:children . (((:node-type . :list)
- (:position . 1)
- (:children . (((:node-type . :number)
- (:position . 2)
- (:form . "1")
- (:value . 1))
- ((:node-type . :number)
- (:position . 4)
- (:form . "2")
- (:value . 2))
- ((:node-type . :number)
- (:position . 6)
- (:form . "3")
- (:value . 3)))))))))))
-
-
-(clj-parse-deftest empty-list "()"
- (("edn" '(()))
- ("ast" '((:node-type . :root)
- (:position . 0)
- (:children . (((:node-type . :list)
- (:position . 1)
- (:children . nil))))))))
-
-(clj-parse-deftest size-1 "(1)"
- (("edn" '((1)))
- ("ast" '((:node-type . :root)
- (:position . 0)
- (:children . (((:node-type . :list)
- (:position . 1)
- (:children . (((:node-type . :number)
- (:position . 2)
- (:form . "1")
- (:value . 1)))))))))))
-
-(clj-parse-deftest leafs "(nil true false hello-world)"
- (("edn" '((nil t nil hello-world)))
- ("ast" '((:node-type . :root)
- (:position . 0)
- (:children . (((:node-type . :list)
- (:position . 1)
- (:children . (((:node-type . :nil)
- (:position . 2)
- (:form . "nil")
- (:value . nil))
- ((:node-type . :true)
- (:position . 6)
- (:form . "true")
- (:value . t))
- ((:node-type . :false)
- (:position . 11)
- (:form . "false")
- (:value . nil))
- ((:node-type . :symbol)
- (:position . 17)
- (:form . "hello-world")
- (:value . hello-world)))))))))))
-
-(clj-parse-deftest qualified-symbol "clojure.string/join"
- (("edn" '(clojure.string/join))
- ("ast" '((:node-type . :root)
- (:position . 0)
- (:children . (((:node-type . :symbol)
- (:position . 1)
- (:form . "clojure.string/join")
- (:value . clojure.string/join))))))))
-
-(clj-parse-deftest nested-lists "((.9 abc (true) (hello)))"
- (("edn" '(((0.9 abc (t) (hello)))))
- ("ast" '((:node-type . :root)
- (:position . 0)
- (:children . (((:node-type . :list)
- (:position . 1)
- (:children . (((:node-type . :list)
- (:position . 2)
- (:children ((:node-type . :number)
- (:position . 3)
- (:form . ".9")
- (:value . 0.9))
- ((:node-type . :symbol)
- (:position . 6)
- (:form . "abc")
- (:value . abc))
- ((:node-type . :list)
- (:position . 10)
- (:children ((:node-type
. :true)
- (:position .
11)
- (:form .
"true")
- (:value .
t))))
- ((:node-type . :list)
- (:position . 17)
- (:children ((:node-type
. :symbol)
- (:position .
18)
- (:form .
"hello")
- (:value .
hello)))))))))))))))
-
-(clj-parse-deftest strings-1 "\"abc hello \\t\\\"x\""
- (("edn" '("abc hello \t\"x"))
- ("ast" '((:node-type . :root)
- (:position . 0)
- (:children . (((:node-type . :string)
- (:position . 1)
- (:form . "\"abc hello \\t\\\"x\"")
- (:value . "abc hello \t\"x"))))))))
-
-(clj-parse-deftest strings-2 "(\"---\\f---\\\"-'\\'-\\\\-\\r\\n\")"
- (("edn" '(("---\f---\"-''-\\-\r\n")))
- ("ast" '((:node-type . :root)
- (:position . 0)
- (:children . (((:node-type . :list)
- (:position . 1)
- (:children . (((:node-type . :string)
- (:position . 2)
- (:form .
"\"---\\f---\\\"-'\\'-\\\\-\\r\\n\"")
- (:value .
"---\f---\"-''-\\-\r\n")))))))))))
-
-(clj-parse-deftest chars-1 "(\\newline \\return \\space \\tab \\a \\b \\c
\\u0078 \\o171)"
- (("edn" '((?\n ?\r ?\ ?\t ?a ?b ?c ?x ?y)))
- ("ast" '((:node-type . :root)
- (:position . 0)
- (:children . (((:node-type . :list)
- (:position . 1)
- (:children . (((:node-type . :character) (:position
. 2) (:form . "\\newline") (:value . ?\n))
- ((:node-type . :character) (:position
. 11) (:form . "\\return") (:value . ?\r))
- ((:node-type . :character) (:position
. 19) (:form . "\\space") (:value . 32))
- ((:node-type . :character) (:position
. 26) (:form . "\\tab") (:value . ?\t))
- ((:node-type . :character) (:position
. 31) (:form . "\\a") (:value . ?a))
- ((:node-type . :character) (:position
. 34) (:form . "\\b") (:value . ?b))
- ((:node-type . :character) (:position
. 37) (:form . "\\c") (:value . ?c))
- ((:node-type . :character) (:position
. 40) (:form . "\\u0078") (:value . ?x))
- ((:node-type . :character) (:position
. 47) (:form . "\\o171") (:value . ?y)))))))))))
-
-(clj-parse-deftest chars-2 "\"\\u0078 \\o171\""
- (("edn" '("x y"))
- ("ast" '((:node-type . :root)
- (:position . 0)
- (:children . (((:node-type . :string)
- (:position . 1)
- (:form . "\"\\u0078 \\o171\"")
- (:value . "x y"))))))))
-
-(clj-parse-deftest keywords ":foo-bar"
- (("edn" '(:foo-bar))
- ("ast" '((:node-type . :root)
- (:position . 0)
- (:children . (((:node-type . :keyword)
- (:position . 1)
- (:form . ":foo-bar")
- (:value . :foo-bar))))))))
-
-(clj-parse-deftest vector "[123]"
- (("edn" '([123]))
- ("ast" '((:node-type . :root)
- (:position . 0)
- (:children . (((:node-type . :vector)
- (:position . 1)
- (:children . (((:node-type . :number)
- (:position . 2)
- (:form . "123")
- (:value . 123)))))))))))
-
-(clj-parse-deftest map "{:count 123}"
- (("edn" (list (a-hash-table :count 123)))
- ("ast" '((:node-type . :root)
- (:position . 0)
- (:children . (((:node-type . :map)
- (:position . 1)
- (:children . (((:node-type . :keyword)
- (:position . 2)
- (:form . ":count")
- (:value . :count))
- ((:node-type . :number)
- (:position . 9)
- (:form . "123")
- (:value . 123)))))))))))
-
-(clj-parse-deftest set "#{:x}"
- (("edn" '((edn-set (:x))))
- ("ast" '((:node-type . :root)
- (:position . 0)
- (:children . (((:node-type . :set)
- (:position . 1)
- (:children . (((:node-type . :keyword)
- (:position . 3)
- (:form . ":x")
- (:value . :x)))))))))))
-
-(clj-parse-deftest discard "(10 #_11 12 #_#_ 13 14)"
- (("edn" '((10 12)))
- ("ast" '((:node-type . :root)
- (:position . 0)
- (:children . (((:node-type . :list)
- (:position . 1)
- (:children . (((:node-type . :number)
- (:position . 2)
- (:form . "10")
- (:value . 10))
- ((:node-type . :number)
- (:position . 10)
- (:form . "12")
- (:value . 12)))))))))))
-
-
-;;; Printer modes
-;; ----------------------------------------------------------------------------
-
-(ert-deftest clj-parse-ast-print-list ()
- (should (equal "(0 1 2)"
- (clj-parse-ast-print '((:node-type . :root)
- (:position . 0)
- (:children . (((:node-type . :list)
- (:position . 1)
- (:children .
(((:node-type . :number)
-
(:position . 2)
- (:form .
"0")
- (:value
. 0))
-
((:node-type . :number)
-
(:position . 4)
- (:form .
"1")
- (:value
. 1))
-
((:node-type . :number)
-
(:position . 6)
- (:form .
"2")
- (:value
. 2))))))))))))
-
-(ert-deftest clj-parse-ast-print-empty-list ()
- (should (equal "()"
- (clj-parse-ast-print '((:node-type . :root)
- (:position . 0)
- (:children . (((:node-type . :list)
- (:position . 1)
- (:children .
nil)))))))))
-
-(ert-deftest clj-parse-ast-print-nested-list ()
- (should (equal "((.9 abc (true) (hello)))"
- (clj-parse-ast-print '((:node-type . :root)
- (:position . 0)
- (:children . (((:node-type . :list)
- (:position . 1)
- (:children .
(((:node-type . :list)
-
(:position . 2)
-
(:children ((:node-type . :number)
-
(:position . 3)
-
(:form . ".9")
-
(:value . 0.9))
-
((:node-type . :symbol)
-
(:position . 6)
-
(:form . "abc")
-
(:value . abc))
-
((:node-type . :list)
-
(:position . 10)
-
(:children ((:node-type . :true)
-
(:position . 11)
-
(:form . "true")
-
(:value . t))))
-
((:node-type . :list)
-
(:position . 17)
-
(:children ((:node-type . :symbol)
-
(:position . 18)
-
(:form . "hello")
-
(:value . hello))))))))))))))))
-
-(ert-deftest clj-parse-ast-print-string ()
- (should (equal "\"abc hello \\t\\\"x\""
- (clj-parse-ast-print '((:node-type . :root)
- (:position . 0)
- (:children . (((:node-type . :string)
- (:position . 1)
- (:form . "\"abc hello
\\t\\\"x\"")
- (:value . "abc hello
\t\"x")))))))))
-
-(ert-deftest clj-parse-ast-print-chars ()
- (should (equal "(\\newline \\return \\space \\tab \\a \\b \\c \\u0078
\\o171)"
- (clj-parse-ast-print '((:node-type . :root)
- (:position . 0)
- (:children . (((:node-type . :list)
- (:position . 1)
- (:children .
(((:node-type . :character) (:position . 2) (:form . "\\newline") (:value .
?\n))
-
((:node-type . :character) (:position . 11) (:form . "\\return") (:value . ?\r))
-
((:node-type . :character) (:position . 19) (:form . "\\space") (:value . 32))
-
((:node-type . :character) (:position . 26) (:form . "\\tab") (:value . ?\t))
-
((:node-type . :character) (:position . 31) (:form . "\\a") (:value . ?a))
-
((:node-type . :character) (:position . 34) (:form . "\\b") (:value . ?b))
-
((:node-type . :character) (:position . 37) (:form . "\\c") (:value . ?c))
-
((:node-type . :character) (:position . 40) (:form . "\\u0078") (:value . ?x))
-
((:node-type . :character) (:position . 47) (:form . "\\o171") (:value .
?y))))))))))))
-
-(ert-deftest clj-parse-ast-print-keyword ()
- (should (equal ":foo-bar"
- (clj-parse-ast-print '((:node-type . :root)
- (:position . 0)
- (:children . (((:node-type . :keyword)
- (:position . 1)
- (:form . ":foo-bar")
- (:value .
:foo-bar)))))))))
-
-(ert-deftest clj-parse-ast-print-vector ()
- (should (equal "[123]"
- (clj-parse-ast-print '((:node-type . :root)
- (:position . 0)
- (:children . (((:node-type . :vector)
- (:position . 1)
- (:children .
(((:node-type . :number)
-
(:position . 2)
- (:form .
"123")
- (:value
. 123))))))))))))
-
-(ert-deftest clj-parse-ast-print-map ()
- (should (equal "{:count 123}"
- (clj-parse-ast-print '((:node-type . :root)
- (:position . 0)
- (:children . (((:node-type . :map)
- (:position . 1)
- (:children .
(((:node-type . :keyword)
-
(:position . 2)
- (:form .
":count")
- (:value
. :count))
-
((:node-type . :number)
-
(:position . 9)
- (:form .
"123")
- (:value
. 123))))))))))))
-
-(ert-deftest clj-parse-ast-print-set ()
- (should (equal "#{:x}"
- (clj-parse-ast-print '((:node-type . :root)
- (:position . 0)
- (:children . (((:node-type . :set)
- (:position . 1)
- (:children .
(((:node-type . :keyword)
-
(:position . 3)
- (:form .
":x")
- (:value
. :x))))))))))))
-
-(provide 'clj-parse-test)
-
-;;; clj-parse-test.el ends here
diff --git a/tests/edn-el-test-suite.el b/tests/edn-el-test-suite.el
deleted file mode 100644
index f2dc7e387b..0000000000
--- a/tests/edn-el-test-suite.el
+++ /dev/null
@@ -1,281 +0,0 @@
-;;; edn-el-test-suite.el --- Tests from edn.el
-
-;; Author: Lars Andersen <expez@expez.com>, Arne Brasseur
<arne@arnebrasseur.net>
-
-;; Copyright (C) 2015 Lars Andersen
-
-;; This file is not part of GNU Emacs.
-
-;; This file is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 3, or (at your option)
-;; any later version.
-
-;; This file is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
-
-;;; Code:
-
-(require 'ert)
-(require 'edn)
-
-(ert-deftest whitespace ()
- (should (null (clj-parse-edn-str "")))
- (should (null (clj-parse-edn-str " ")))
- (should (null (clj-parse-edn-str " ")))
- (should (null (clj-parse-edn-str " ")))
- (should (null (clj-parse-edn-str " ")))
- (should (null (clj-parse-edn-str ",")))
- (should (null (clj-parse-edn-str ",,,,")))
- (should (null (clj-parse-edn-str " , ,
-")))
- (should (null (clj-parse-edn-str"
- ,, ")))
- (should (equal [a b c d] (clj-parse-edn-str "[a ,,,,,, b,,,,,c ,d]"))))
-
-(ert-deftest symbols ()
- :tags '(edn symbol)
- (should (equal 'foo (clj-parse-edn-str "foo")))
- (should (equal 'foo\. (clj-parse-edn-str "foo.")))
- (should (equal '%foo\. (clj-parse-edn-str "%foo.")))
- (should (equal 'foo/bar (clj-parse-edn-str "foo/bar")))
- (equal 'some\#sort\#of\#symbol (clj-parse-edn-str "some#sort#of#symbol"))
- (equal 'truefalse (clj-parse-edn-str "truefalse"))
- (equal 'true. (clj-parse-edn-str "true."))
- (equal '/ (clj-parse-edn-str "/"))
- (should (equal '.true (clj-parse-edn-str ".true")))
- (should (equal 'some:sort:of:symbol (clj-parse-edn-str
"some:sort:of:symbol")))
- (equal 'foo-bar (clj-parse-edn-str "foo-bar"))
- (should (equal '+some-symbol (clj-parse-edn-str "+some-symbol")))
- (should (equal '-symbol (clj-parse-edn-str "-symbol"))))
-
-(ert-deftest booleans ()
- :tags '(edn boolean)
- (should (equal t (clj-parse-edn-str "true")))
- (should (equal nil (clj-parse-edn-str "false "))))
-
-(ert-deftest characters ()
- :tags '(edn characters)
- (should (equal 97 (clj-parse-edn-str "\\a")))
- (should (equal 960 (clj-parse-edn-str "\\u03C0")))
- ;;(should (equal 'newline (clj-parse-edn-str "\\newline")))
- )
-
-(ert-deftest elision ()
- :tags '(edn elision)
- (should-not (clj-parse-edn-str "#_foo"))
- (should-not (clj-parse-edn-str "#_ 123"))
- (should-not (clj-parse-edn-str "#_:foo"))
- (should-not (clj-parse-edn-str "#_ \\a"))
- (should-not (clj-parse-edn-str "#_
-\"foo\""))
- (should-not (clj-parse-edn-str "#_ (1 2 3)"))
- (should (equal '(1 3) (clj-parse-edn-str "(1 #_ 2 3)")))
- (should (equal '[1 2 3 4] (clj-parse-edn-str "[1 2 #_[4 5 6] 3 4]")))
- (should (map-equal (make-seeded-hash-table :foo :bar)
- (clj-parse-edn-str "{:foo #_elided :bar}")))
- (should (equal (edn-list-to-set '(1 2 3 4))
- (clj-parse-edn-str "#{1 2 #_[1 2 3] 3 #_ (1 2) 4}")))
- (should (equal [a d] (clj-parse-edn-str "[a #_ ;we are discarding what comes
next
- c d]"))))
-
-(ert-deftest string ()
- :tags '(edn string)
- (should (equal "this is a string" (clj-parse-edn-str "\"this is a
string\"")))
- (should (equal "this has an escaped \"quote in it"
- (clj-parse-edn-str "\"this has an escaped \\\"quote in
it\"")))
- (should (equal "foo\tbar" (clj-parse-edn-str "\"foo\\tbar\"")))
- (should (equal "foo\nbar" (clj-parse-edn-str "\"foo\\nbar\"")))
- (should (equal "this is a string \\ that has an escaped backslash"
- (clj-parse-edn-str "\"this is a string \\\\ that has an
escaped backslash\"")))
- (should (equal "[" (clj-parse-edn-str "\"[\""))))
-
-(ert-deftest keywords ()
- :tags '(edn keywords)
- (should (equal :namespace\.of\.some\.length/keyword-name
- (clj-parse-edn-str ":namespace.of.some.length/keyword-name")))
- (should (equal :\#/\# (clj-parse-edn-str ":#/#")))
- (should (equal :\#/:a (clj-parse-edn-str ":#/:a")))
- (should (equal :\#foo (clj-parse-edn-str ":#foo"))))
-
-(ert-deftest integers ()
- :tags '(edn integers)
- (should (= 0 (clj-parse-edn-str "0")))
- (should (= 0 (clj-parse-edn-str "+0")))
- (should (= 0 (clj-parse-edn-str "-0")))
- (should (= 100 (clj-parse-edn-str "100")))
- (should (= -100 (clj-parse-edn-str "-100"))))
-
-(ert-deftest floats ()
- :tags '(edn floats)
- (should (= 12.32 (clj-parse-edn-str "12.32")))
- (should (= -12.32 (clj-parse-edn-str "-12.32")))
- (should (= 9923.23 (clj-parse-edn-str "+9923.23")))
- (should (= 4.5e+044 (clj-parse-edn-str "45e+43")))
- (should (= -4.5e-042 (clj-parse-edn-str "-45e-43")))
- (should (= 4.5e+044 (clj-parse-edn-str "45E+43"))))
-
-(ert-deftest lists ()
- :tags '(edn lists)
- (should-not (clj-parse-edn-str "()"))
- (should (equal '(1 2 3) (clj-parse-edn-str "( 1 2 3)")))
- (should (equal '(12.1 ?a foo :bar) (clj-parse-edn-str "(12.1 \\a foo
:bar)")))
- (should (equal '((:foo bar :bar 12)) (clj-parse-edn-str "( (:foo bar :bar
12))")))
- (should (equal
- '(defproject com\.thortech/data\.edn "0.1.0-SNAPSHOT")
- (clj-parse-edn-str "(defproject com.thortech/data.edn
\"0.1.0-SNAPSHOT\")"))))
-
-(ert-deftest vectors ()
- :tags '(edn vectors)
- (should (equal [] (clj-parse-edn-str "[]")))
- (should (equal [] (clj-parse-edn-str "[ ]")))
- (should (equal '[1 2 3] (clj-parse-edn-str "[ 1 2 3 ]")))
- (should (equal '[12.1 ?a foo :bar] (clj-parse-edn-str "[ 12.1 \\a foo
:bar]")))
- (should (equal '[[:foo bar :bar 12]] (clj-parse-edn-str "[[:foo bar :bar
12]]")))
- (should (equal '[( :foo bar :bar 12 ) "foo"]
- (clj-parse-edn-str "[(:foo bar :bar 12) \"foo\"]")))
- (should (equal '[/ \. * ! _ \? $ % & = - +]
- (clj-parse-edn-str "[/ . * ! _ ? $ % & = - +]")))
- (should (equal
- ;;[99 newline return space tab]
- [99 10 13 32 9]
- (clj-parse-edn-str "[\\c \\newline \\return \\space \\tab]"))))
-
-(defun map-equal (m1 m2)
- (and (and (hash-table-p m1) (hash-table-p m2))
- (eq (hash-table-test m1) (hash-table-test m2))
- (= (hash-table-count m1) (hash-table-count m2))
- (equal (hash-table-keys m1) (hash-table-keys m2))
- (equal (hash-table-values m1) (hash-table-values m2))))
-
-(defun make-seeded-hash-table (&rest keys-and-values)
- (let ((m (make-hash-table :test #'equal)))
- (while keys-and-values
- (puthash (pop keys-and-values) (pop keys-and-values) m))
- m))
-
-(ert-deftest maps ()
- :tags '(edn maps)
- (should (hash-table-p (clj-parse-edn-str "{ }")))
- (should (hash-table-p (clj-parse-edn-str "{}")))
- (should (map-equal (make-seeded-hash-table :foo :bar :baz :qux)
- (clj-parse-edn-str "{ :foo :bar :baz :qux}")))
- (should (map-equal (make-seeded-hash-table 1 "123" 'vector [1 2 3])
- (clj-parse-edn-str "{ 1 \"123\" vector [1 2 3]}")))
- (should (map-equal (make-seeded-hash-table [1 2 3] "some numbers")
- (clj-parse-edn-str "{[1 2 3] \"some numbers\"}"))))
-
-(ert-deftest sets ()
- :tags '(edn sets)
- (should (edn-set-p (clj-parse-edn-str "#{}")))
- (should (edn-set-p (clj-parse-edn-str "#{ }")))
- (should (equal (edn-list-to-set '(1 2 3)) (clj-parse-edn-str "#{1 2 3}")))
- (should (equal (edn-list-to-set '(1 [1 2 3] 3)) (clj-parse-edn-str "#{1 [1 2
3] 3}"))))
-
-(ert-deftest comment ()
- :tags '(edn comments)
- (should-not (clj-parse-edn-str ";nada"))
- (should (equal 1 (clj-parse-edn-str ";; comment
-1")))
- (should (equal [1 2 3] (clj-parse-edn-str "[1 2 ;comment to eol
-3]")))
- (should (equal '[valid more items] (clj-parse-edn-str "[valid;touching
trailing comment
- more items]")))
- (should (equal [valid vector more vector items] (clj-parse-edn-str "[valid
vector
- ;;comment in vector
- more vector items]"))))
-
-(defun test-val-passed-to-handler (val)
- (should (listp val))
- (should (= (length val) 2))
- (should (= 1 (car val)))
- 1)
-
-(setq clj-edn-test-extra-handlers
- (a-list
- 'my/type #'test-val-passed-to-handler
- 'my/other-type (lambda (val) 2)))
-
-(ert-deftest tags ()
- :tags '(edn tags)
- (should-error (clj-parse-edn-str "#my/type value"
clj-edn-test-extra-handlers))
- (should (= 1 (clj-parse-edn-str "#my/type (1 2)"
clj-edn-test-extra-handlers)))
- (should (= 2 (clj-parse-edn-str "#my/other-type {:foo :bar}"
clj-edn-test-extra-handlers))))
-
-(ert-deftest roundtrip ()
- :tags '(edn roundtrip)
- (let ((data [1 2 3 :foo (4 5) qux "quux"]))
- (should (equal data (clj-parse-edn-str (edn-print-string data))))
- (should (map-equal (make-seeded-hash-table :foo :bar)
- (clj-parse-edn-str (edn-print-string
(make-seeded-hash-table :foo :bar)))))
- (should (equal (edn-list-to-set '(1 2 3 [3 1.11]))
- (clj-parse-edn-str (edn-print-string (edn-list-to-set '(1 2
3 [3 1.11]))))))
- (should-error (clj-parse-edn-str "#myapp/Person {:first \"Fred\" :last
\"Mertz\"}"))))
-
-(ert-deftest inst ()
- :tags '(edn inst)
- (let* ((inst-str "#inst \"1985-04-12T23:20:50.52Z\"")
- (inst (clj-parse-edn-str inst-str))
- (time (date-to-time "1985-04-12T23:20:50.52Z")))
- (should (edn-inst-p inst))
- (should (equal time (edn-inst-to-time inst)))))
-
-(ert-deftest uuid ()
- :tags '(edn uuid)
- (let* ((str "f81d4fae-7dec-11d0-a765-00a0c91e6bf6")
- (uuid (clj-parse-edn-str (concat "#uuid \"" str "\""))))
- (should (edn-uuid-p uuid))))
-
-;; (ert-deftest invalid-edn ()
-;; (should-error (clj-parse-edn-str "///"))
-;; (should-error (clj-parse-edn-str "~cat"))
-;; (should-error (clj-parse-edn-str "foo/bar/baz/qux/quux"))
-;; (should-error (clj-parse-edn-str "#foo/"))
-;; (should-error (clj-parse-edn-str "foo/"))
-;; (should-error (clj-parse-edn-str ":foo/"))
-;; (should-error (clj-parse-edn-str "#/foo"))
-;; (should-error (clj-parse-edn-str "/symbol"))
-;; (should-error (clj-parse-edn-str ":/foo"))
-;; (should-error (clj-parse-edn-str "+5symbol"))
-;; (should-error (clj-parse-edn-str ".\\newline"))
-;; (should-error (clj-parse-edn-str "0cat"))
-;; (should-error (clj-parse-edn-str "-4cats"))
-;; (should-error (clj-parse-edn-str ".9"))
-;; (should-error (clj-parse-edn-str ":keyword/with/too/many/slashes"))
-;; (should-error (clj-parse-edn-str ":a.b.c/"))
-;; (should-error (clj-parse-edn-str "\\itstoolong"))
-;; (should-error (clj-parse-edn-str ":#/:"))
-;; (should-error (clj-parse-edn-str "/foo//"))
-;; (should-error (clj-parse-edn-str "///foo"))
-;; (should-error (clj-parse-edn-str ":{}"))
-;; (should-error (clj-parse-edn-str "//"))
-;; (should-error (clj-parse-edn-str "##"))
-;; (should-error (clj-parse-edn-str "::"))
-;; (should-error (clj-parse-edn-str "::a"))
-;; (should-error (clj-parse-edn-str ".5symbol"))
-;; (should-error (clj-parse-edn-str "{ \"foo\""))
-;; (should-error (clj-parse-edn-str "{ \"foo\" :bar"))
-;; (should-error (clj-parse-edn-str "{"))
-;; (should-error (clj-parse-edn-str ":{"))
-;; (should-error (clj-parse-edn-str "{{"))
-;; (should-error (clj-parse-edn-str "}"))
-;; (should-error (clj-parse-edn-str ":}"))
-;; (should-error (clj-parse-edn-str "}}"))
-;; (should-error (clj-parse-edn-str "#:foo"))
-;; (should-error (clj-parse-edn-str "\\newline."))
-;; (should-error (clj-parse-edn-str "\\newline0.1"))
-;; (should-error (clj-parse-edn-str "^"))
-;; (should-error (clj-parse-edn-str ":^"))
-;; (should-error (clj-parse-edn-str "_:^"))
-;; (should-error (clj-parse-edn-str "#{{[}}"))
-;; (should-error (clj-parse-edn-str "[}"))
-;; (should-error (clj-parse-edn-str "@cat")))
-
-;;; edn-el-test-suite.el ends here
- [nongnu] elpa/parseclj 2da47798d9 057/185: Enable more edn.el tests, document how time/uuid are stored, (continued)
- [nongnu] elpa/parseclj 2da47798d9 057/185: Enable more edn.el tests, document how time/uuid are stored, ELPA Syncer, 2021/12/28
- [nongnu] elpa/parseclj f6de87fbe6 067/185: Split EDN and AST handling in separate files, ELPA Syncer, 2021/12/28
- [nongnu] elpa/parseclj d410a1530e 096/185: Add code-checking defaults to `dir-locals.el`, ELPA Syncer, 2021/12/28
- [nongnu] elpa/parseclj 3a92eafce9 079/185: Rename reduce-node to reduce-branch, ELPA Syncer, 2021/12/28
- [nongnu] elpa/parseclj 7beff77b15 083/185: Introduce parseclj-parse-clojure, ELPA Syncer, 2021/12/28
- [nongnu] elpa/parseclj 3d261f5d3c 072/185: Bump version of a, ELPA Syncer, 2021/12/28
- [nongnu] elpa/parseclj 47cf208a91 091/185: Fix parsing of tags/discard with :lexical-preservation, ELPA Syncer, 2021/12/28
- [nongnu] elpa/parseclj da4bacb5f5 078/185: Rename parseclj-reduce to parseclj-parse, ELPA Syncer, 2021/12/28
- [nongnu] elpa/parseclj 2a42dcb6fa 066/185: Update License info in README, ELPA Syncer, 2021/12/28
- [nongnu] elpa/parseclj ba9f4d723f 076/185: Document proposal for alternative package organization, ELPA Syncer, 2021/12/28
- [nongnu] elpa/parseclj a8e1de0d62 075/185: Merge pull request #4 from lambdaisland/edn-ast-split,
ELPA Syncer <=
- [nongnu] elpa/parseclj 6fdf22a553 062/185: Update license, fix dependencies, ELPA Syncer, 2021/12/28
- [nongnu] elpa/parseclj 5fbe901cba 071/185: Parse/unparse :tag, rountrip AST, ELPA Syncer, 2021/12/28
- [nongnu] elpa/parseclj 6e0dc9516c 093/185: Add missing require, ELPA Syncer, 2021/12/28
- [nongnu] elpa/parseclj b79b3a5438 098/185: Add documentation to `parseclj-ast.el`, ELPA Syncer, 2021/12/28
- [nongnu] elpa/parseclj 1b071d7775 104/185: Add documentation to `parseedn` module, ELPA Syncer, 2021/12/28
- [nongnu] elpa/parseclj e1cb9e5514 113/185: Add a few more node accessors., ELPA Syncer, 2021/12/28
- [nongnu] elpa/parseclj 80e92cdf9f 001/185: Move into its own repo, ELPA Syncer, 2021/12/28
- [nongnu] elpa/parseclj 2588470302 116/185: Merge pull request #9 from lambdaisland/docstrings-and-conventions, ELPA Syncer, 2021/12/28
- [nongnu] elpa/parseclj 92396d11cf 127/185: Merge pull request #17 from lambdaisland/travis-evm, ELPA Syncer, 2021/12/28
- [nongnu] elpa/parseclj f87278a70e 135/185: Merge pull request #18 from clojure-emacs/doc-&-style-fixes-part-2, ELPA Syncer, 2021/12/28