Skip to content

Commit f65307e

Browse files
authored
Do not automatically insert ws after comment node (#347)
* Do not automatically insert ws after comment node We'll assume comment node is terminated with a newline (but it might not be and that's ok). Closes #346 This change adds `rewrite-clj.zip.test-helper` ns to make zipper tests (when appropriate to use) easier to: - setup - verify (including expected result location, which we often omit) - write by humans - read by humans * ran: apply-import-vars gen-code * address eastwood warnign on recur * koacha was a bit noisy use (is .. description) instead of (testing description) * fix test-helper for cljs * changelog * review/update docstrings * test libs: rewrite-edn: temporarily hit my PR So that we can get to green again, hit sha of my PR for rewrite-edn
1 parent b310b22 commit f65307e

File tree

6 files changed

+296
-96
lines changed

6 files changed

+296
-96
lines changed

CHANGELOG.adoc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ A release with known breaking changes is marked with:
2424
// (adjust these in publish.clj as you see fit)
2525
=== Unreleased
2626

27+
* `rewrite-clj.zip/insert-right` and `rewrite-clj.zip/append-child` no longer insert a space when inserting/appending after a comment node.
28+
{issue}346[#346] ({lread})
29+
2730
=== v1.1.49 - 2024-11-18 [[v1.1.49]]
2831

2932
* Fix parsing of `b//` symbol

script/test_libs.clj

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
opts (if token
4141
{:headers {"Authorization" (format "Bearer %s" token)}}
4242
{})]
43-
(case (:via github-release)
43+
(case (:via github-release)
4444
;; no official release
4545
:sha
4646
(-> (curl/get (format "https://api.github.com/repos/%s/git/refs/heads/master" (:repo github-release))
@@ -75,6 +75,7 @@
7575
(:repo github-release)
7676
(or (:version-prefix github-release) "")
7777
version))]
78+
(status/line :detail "Downloading lib release from: %s" download-url)
7879
(io/make-parents target)
7980
(io/copy
8081
(:body (curl/get download-url {:as :stream}))
@@ -411,11 +412,15 @@
411412
:show-deps-fn cli-deps-tree
412413
:test-cmds ["clojure -M:test"]}
413414
{:name "rewrite-edn"
414-
:version "0.4.8"
415+
;; very temporarily use sha of my PR that addresses failure
416+
;; move back to release when PR is merged
417+
:version "5659a1f650514d18c2356edeca16662e860ddd92"
415418
:platforms [:clj]
416419
:github-release {:repo "borkdude/rewrite-edn"
417-
:version-prefix "v"
418-
:via :tag}
420+
;; very temporarily use sha of PR that addresses failure
421+
;; :version-prefix "v"
422+
;; :via :tag
423+
:via :sha}
419424
:patch-fn deps-edn-v1-patch
420425
:show-deps-fn cli-deps-tree
421426
:test-cmds ["clojure -M:test"]}

src/rewrite_clj/zip.cljc

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -501,38 +501,45 @@
501501

502502
;; DO NOT EDIT FILE, automatically imported from: rewrite-clj.zip.insert
503503
(defn insert-right
504-
"Return zipper with `item` inserted to the right of the current node in `zloc`, without moving location.
504+
"Return `zloc` with `item` inserted to the right of the current node in `zloc`, without moving location.
505505
If `item` is not already a node, an attempt will be made to coerce it to one.
506506
507-
Will insert a space if necessary.
507+
Will insert spaces around `item` if necessary.
508+
There is no consideration on whitespaceness of `item` itself.
508509
509510
Use [[rewrite-clj.zip/insert-right*]] to insert without adding any whitespace."
510511
[zloc item] (rewrite-clj.zip.insert/insert-right zloc item))
511512

512513
;; DO NOT EDIT FILE, automatically imported from: rewrite-clj.zip.insert
513514
(defn insert-left
514515
"Return zipper with `item` inserted to the left of the current node in `zloc`, without moving location.
515-
Will insert a space if necessary.
516516
If `item` is not already a node, an attempt will be made to coerce it to one.
517517
518+
Will insert spaces around `item` if necessary.
519+
There is no consideration on whitespaceness of `item` itself.
520+
518521
Use [[insert-left*]] to insert without adding any whitespace."
519522
[zloc item] (rewrite-clj.zip.insert/insert-left zloc item))
520523

521524
;; DO NOT EDIT FILE, automatically imported from: rewrite-clj.zip.insert
522525
(defn insert-child
523-
"Return zipper with `item` inserted as the first child of the current node in `zloc`, without moving location.
524-
Will insert a space if necessary.
526+
"Return `zloc` with `item` inserted as the first child of the current node in `zloc`, without moving location.
525527
If `item` is not already a node, an attempt will be made to coerce it to one.
526528
529+
Will insert space after `item` if necessary.
530+
There is no consideration on whitespaceness of `item` itself.
531+
527532
Use [[insert-child*]] to insert without adding any whitespace."
528533
[zloc item] (rewrite-clj.zip.insert/insert-child zloc item))
529534

530535
;; DO NOT EDIT FILE, automatically imported from: rewrite-clj.zip.insert
531536
(defn append-child
532-
"Return zipper with `item` inserted as the last child of the current node in `zloc`, without moving.
533-
Will insert a space if necessary.
537+
"Return `zloc` with `item` inserted as the last child of the current node in `zloc`, without moving location.
534538
If `item` is not already a node, an attempt will be made to coerce it to one.
535539
540+
Will insert space before `item` if necessary.
541+
There is no consideration on whitespaceness of `item` itself.
542+
536543
Use [[append-child*]] to append without adding any whitespace."
537544
[zloc item] (rewrite-clj.zip.insert/append-child zloc item))
538545

src/rewrite_clj/zip/insert.cljc

Lines changed: 61 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -9,69 +9,90 @@
99
(def ^:private space
1010
(nwhitespace/spaces 1))
1111

12-
(defn- insert
13-
"Generic insertion helper. If the node reached by `move-fn`
14-
is a whitespace, insert an additional space."
15-
[move-fn insert-fn prefix zloc item]
16-
(let [item-node (node/coerce item)
17-
next-node (move-fn zloc)]
18-
(->> (concat
19-
(when (and next-node (not (zwhitespace/whitespace? next-node)))
20-
[space])
21-
[item-node]
22-
(when (not (zwhitespace/whitespace? zloc))
23-
prefix))
24-
(reduce insert-fn zloc))))
12+
(defn- ends-with-ws? [zloc]
13+
(when zloc
14+
(or (zwhitespace/whitespace? zloc)
15+
;; a comment is not necessarily newline terminated, but we don't special case that
16+
;; inserting after a non-newline termnated comment is caveated in rewrite-clj.node/comment-node
17+
(zwhitespace/comment? zloc))))
18+
19+
(defn- starts-with-ws? [zloc]
20+
(zwhitespace/whitespace? zloc))
2521

2622
(defn insert-right
27-
"Return zipper with `item` inserted to the right of the current node in `zloc`, without moving location.
23+
"Return `zloc` with `item` inserted to the right of the current node in `zloc`, without moving location.
2824
If `item` is not already a node, an attempt will be made to coerce it to one.
2925
30-
Will insert a space if necessary.
26+
Will insert spaces around `item` if necessary.
27+
There is no consideration on whitespaceness of `item` itself.
3128
3229
Use [[rewrite-clj.zip/insert-right*]] to insert without adding any whitespace."
3330
[zloc item]
34-
(insert
35-
zraw/right
36-
zraw/insert-right
37-
[space]
38-
zloc item))
31+
(let [next-zloc (zraw/right zloc)
32+
item-node (node/coerce item)]
33+
(cond-> zloc
34+
(and next-zloc (not (starts-with-ws? next-zloc)))
35+
(zraw/insert-right space)
36+
37+
:always
38+
(zraw/insert-right item-node)
39+
40+
(not (ends-with-ws? zloc))
41+
(zraw/insert-right space))))
3942

4043
(defn insert-left
4144
"Return zipper with `item` inserted to the left of the current node in `zloc`, without moving location.
42-
Will insert a space if necessary.
4345
If `item` is not already a node, an attempt will be made to coerce it to one.
4446
47+
Will insert spaces around `item` if necessary.
48+
There is no consideration on whitespaceness of `item` itself.
49+
4550
Use [[insert-left*]] to insert without adding any whitespace."
4651
[zloc item]
47-
(insert
48-
zraw/left
49-
zraw/insert-left
50-
[space]
51-
zloc item))
52+
(let [prev-zloc (zraw/left zloc)
53+
item-node (node/coerce item)]
54+
(cond-> zloc
55+
(and prev-zloc (not (ends-with-ws? prev-zloc)))
56+
(zraw/insert-left space)
57+
58+
:always
59+
(zraw/insert-left item-node)
60+
61+
(not (starts-with-ws? zloc))
62+
(zraw/insert-left space))))
5263

5364
(defn insert-child
54-
"Return zipper with `item` inserted as the first child of the current node in `zloc`, without moving location.
55-
Will insert a space if necessary.
65+
"Return `zloc` with `item` inserted as the first child of the current node in `zloc`, without moving location.
5666
If `item` is not already a node, an attempt will be made to coerce it to one.
5767
68+
Will insert space after `item` if necessary.
69+
There is no consideration on whitespaceness of `item` itself.
70+
5871
Use [[insert-child*]] to insert without adding any whitespace."
5972
[zloc item]
60-
(insert
61-
zraw/down
62-
zraw/insert-child
63-
[]
64-
zloc item))
73+
(let [prev-zloc (zraw/down zloc)
74+
item-node (node/coerce item)]
75+
(cond-> zloc
76+
(and prev-zloc (not (starts-with-ws? prev-zloc)))
77+
(zraw/insert-child space)
78+
79+
:always
80+
(zraw/insert-child item-node))))
6581

6682
(defn append-child
67-
"Return zipper with `item` inserted as the last child of the current node in `zloc`, without moving.
68-
Will insert a space if necessary.
83+
"Return `zloc` with `item` inserted as the last child of the current node in `zloc`, without moving location.
6984
If `item` is not already a node, an attempt will be made to coerce it to one.
7085
86+
Will insert space before `item` if necessary.
87+
There is no consideration on whitespaceness of `item` itself.
88+
7189
Use [[append-child*]] to append without adding any whitespace."
7290
[zloc item]
73-
(insert
74-
#(some-> % zraw/down zraw/rightmost)
75-
zraw/append-child
76-
[]
77-
zloc item))
91+
(let [prev-zloc (some-> zloc zraw/down zraw/rightmost)
92+
item-node (node/coerce item)]
93+
(cond-> zloc
94+
(and prev-zloc (not (ends-with-ws? prev-zloc)))
95+
(zraw/append-child space)
96+
97+
:always
98+
(zraw/append-child item-node))))

test/rewrite_clj/zip/insert_test.cljc

Lines changed: 115 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,118 @@
11
(ns rewrite-clj.zip.insert-test
2-
(:require [clojure.test :refer [deftest is]]
3-
[rewrite-clj.interop :as interop]
4-
[rewrite-clj.zip :as z]))
5-
6-
(deftest t-whitespace-aware-insertion
7-
(doseq [[fmt m n f s]
8-
[["[%s]" z/next 0 z/insert-right "[1 2 3 4] x"]
9-
["[%s]" z/next 1 z/insert-right "[1 x 2 3 4]"]
10-
["[%s]" z/next 2 z/insert-right "[1 2 x 3 4]"]
11-
["[%s]" z/next 3 z/insert-right "[1 2 3 x 4]"]
12-
["[%s]" z/next 4 z/insert-right "[1 2 3 4 x]"]
13-
["[%s]" z/next 0 z/insert-left "x [1 2 3 4]"]
14-
["[%s]" z/next 1 z/insert-left "[x 1 2 3 4]"]
15-
["[%s]" z/next 2 z/insert-left "[1 x 2 3 4]"]
16-
["[%s]" z/next 3 z/insert-left "[1 2 x 3 4]"]
17-
["[%s]" z/next 4 z/insert-left "[1 2 3 x 4]"]
18-
["[%s]" z/next 0 z/insert-child "[x 1 2 3 4]"]
19-
["[%s]" z/next 0 z/append-child "[1 2 3 4 x]"]
20-
["[ %s]" z/next 0 z/insert-child "[x 1 2 3 4]"]
21-
["[%s ]" z/next 0 z/append-child "[1 2 3 4 x]"]
22-
["[%s]" z/next* 2 z/insert-right "[1 x 2 3 4]"]
23-
["\n[%s]" z/leftmost* 1 z/insert-left "x\n[1 2 3 4]"]
24-
["\n[%s]" z/leftmost* 1 z/insert-right "\nx [1 2 3 4]"]]]
25-
(let [elements (->> (z/of-string
26-
(interop/simple-format fmt "1 2 3 4"))
27-
(iterate m))
28-
loc (nth elements n)
29-
loc' (f loc 'x)]
30-
(is (= (z/tag loc') (z/tag loc)))
31-
(is (= s (z/root-string loc'))))))
2+
(:require [clojure.test :refer [deftest is testing]]
3+
[rewrite-clj.zip :as z]
4+
[rewrite-clj.zip.test-helper :as th]))
5+
6+
(def zipper-opts [{} {:track-position? true}])
7+
8+
;; special positional markers recognized by test-helper fns
9+
;; ⊚ - node location
10+
;; ◬ - root :forms node
11+
12+
(deftest t-insert-right
13+
(doseq [zopts zipper-opts]
14+
(testing (str "zipper opts " zopts)
15+
(doseq [[in expected]
16+
[["⊚[1 2 3 4]" "⊚[1 2 3 4] x"]
17+
["[⊚1 2 3 4]" "[⊚1 x 2 3 4]"]
18+
["[1 ⊚2 3 4]" "[1 ⊚2 x 3 4]"]
19+
["[1 2 ⊚3 4]" "[1 2 ⊚3 x 4]"]
20+
["[1 2 3 ⊚4]" "[1 2 3 ⊚4 x]"]
21+
["[1\n⊚ 2 3 4]" "[1\n⊚ x 2 3 4]"]
22+
["\n[1 2 3 4]" "\nx [1 2 3 4]"]
23+
["[1 2 3 4⊚;; comment\n]" "[1 2 3 4⊚;; comment\nx]"]
24+
["⊚;; unterminated cmt" "⊚;; unterminated cmtx"] ;; an odd thing to do, but allowed
25+
["⊚;; comment\n" "⊚;; comment\nx"]]]
26+
(let [zloc (th/of-locmarked-string in zopts)]
27+
(is (= expected (th/root-locmarked-string (z/insert-right zloc 'x)))
28+
in))))))
29+
30+
(deftest t-insert-rigth-contrived
31+
(doseq [zopts zipper-opts]
32+
(testing (str "zipper opts " zopts)
33+
(let [zloc (-> (th/of-locmarked-string "1⊚ 2" zopts) z/remove*)]
34+
(is (= "⊚12" (th/root-locmarked-string zloc)) "sanity pre-condition")
35+
(is (= "⊚1 x 2" (-> zloc
36+
(z/insert-right 'x)
37+
th/root-locmarked-string)))))))
38+
39+
(deftest t-insert-left
40+
(doseq [zopts zipper-opts]
41+
(testing (str "zipper opts " zopts)
42+
(doseq [[in expected]
43+
[["⊚[1 2 3 4]" "x ⊚[1 2 3 4]"]
44+
["[⊚1 2 3 4]" "[x ⊚1 2 3 4]"]
45+
["[1 ⊚2 3 4]" "[1 x ⊚2 3 4]"]
46+
["[1 2 ⊚3 4]" "[1 2 x ⊚3 4]"]
47+
["[1 2 3 ⊚4]" "[1 2 3 x ⊚4]"]
48+
["[1\n⊚ 2 3 4]" "[1\nx⊚ 2 3 4]"]
49+
["\n[1 2 3 4]" "x⊚\n[1 2 3 4]"]
50+
["⊚;; comment\n" "x ⊚;; comment\n"]
51+
["⊚;; unterminated cmt" "x ⊚;; unterminated cmt"]]]
52+
(let [zloc (th/of-locmarked-string in zopts)]
53+
(is (= expected (th/root-locmarked-string (z/insert-left zloc 'x)))
54+
in))))))
55+
56+
(deftest t-insert-left-contrived
57+
(doseq [zopts zipper-opts]
58+
(testing (str "zipper opts " zopts)
59+
(let [zloc (-> (th/of-locmarked-string "1⊚ 2" zopts) z/remove* z/right*)]
60+
(is (= "1⊚2" (th/root-locmarked-string zloc)) "sanity pre-condition")
61+
(is (= "1 x ⊚2" (-> zloc
62+
(z/insert-left 'x)
63+
th/root-locmarked-string)))))))
64+
65+
(deftest t-insert-child
66+
(doseq [zopts zipper-opts]
67+
(testing (str "zipper opts " zopts)
68+
(doseq [[in expected]
69+
[["⊚[1 2 3 4]" "⊚[x 1 2 3 4]"]
70+
["⊚[]" "⊚[x]"]
71+
["⊚[1]" "⊚[x 1]"]
72+
["⊚[ 1]" "⊚[x 1]"]
73+
["⊚[ 1 ]" "⊚[x 1 ]"]
74+
["⊚[ ]" "⊚[x ]"]
75+
["⊚[ 1 2 3 4]" "⊚[x 1 2 3 4]"]
76+
["⊚[;; comment\n1 2 3 4]" "⊚[x ;; comment\n1 2 3 4]"]
77+
["◬;; unterminated cmt" "◬x ;; unterminated cmt"]
78+
["◬;; comment\n" "◬x ;; comment\n"]]]
79+
(let [zloc (th/of-locmarked-string in zopts)]
80+
(is (= expected (th/root-locmarked-string (z/insert-child zloc 'x)))
81+
in))))))
82+
83+
(deftest t-append-child
84+
(doseq [zopts zipper-opts]
85+
(testing (str "zipper opts " zopts)
86+
(doseq [[in expected]
87+
[["⊚[1 2 3 4 ]" "⊚[1 2 3 4 x]"]
88+
["⊚[]" "⊚[x]"]
89+
["⊚[1]" "⊚[1 x]"]
90+
["⊚[1 ]" "⊚[1 x]"]
91+
["⊚[ 1 ]" "⊚[ 1 x]"]
92+
["⊚[ ]" "⊚[ x]"]
93+
["⊚[1 2 3 4;; comment\n]" "⊚[1 2 3 4;; comment\nx]"]
94+
["◬;; unterminated cmt" "◬;; unterminated cmtx"] ;; odd to do but allowed
95+
["◬#! unterminated cmt" "◬#! unterminated cmtx"] ;; try alternate comment syntax
96+
["◬;; comment\n" "◬;; comment\nx"]]]
97+
(let [zloc (th/of-locmarked-string in zopts)]
98+
(is (= expected (th/root-locmarked-string (z/append-child zloc 'x)))
99+
in))))))
32100

33101
(deftest t-different-node-types-that-allow-insertion
34-
(doseq [[s depth result]
35-
[["[1 2]" 0 "[1 x 2 y]"]
36-
["(1 2)" 0 "(1 x 2 y)"]
37-
["#{1 2}" 0 "#{1 x 2 y}"]
38-
["#(1 2)" 0 "#(1 x 2 y)"]
39-
["'(1 2)" 1 "'(1 x 2 y)"]
40-
["#=(1 2)" 1 "#=(1 x 2 y)"]
41-
["#_(1 2)" 1 "#_(1 x 2 y)"]
42-
["@(f 2)" 1 "@(f x 2 y)"]]]
43-
(let [loc (-> (iterate z/down (z/of-string s))
44-
(nth (inc depth))
45-
z/right
46-
(z/insert-left 'x)
47-
(z/insert-right 'y))]
48-
(is (= result (z/root-string loc))))))
102+
(doseq [zopts zipper-opts]
103+
(testing (str "zipper opts " zopts)
104+
(doseq [[in expected]
105+
[["[1 ⊚2]" "[1 x ⊚2 y]"]
106+
["(1 ⊚2)" "(1 x ⊚2 y)"]
107+
["#{1 ⊚2}" "#{1 x ⊚2 y}"]
108+
["#(1 ⊚2)" "#(1 x ⊚2 y)"]
109+
["'(1 ⊚2)" "'(1 x ⊚2 y)"]
110+
["#=(1 ⊚2)" "#=(1 x ⊚2 y)"]
111+
["#_(1 ⊚2)" "#_(1 x ⊚2 y)"]
112+
["@(f ⊚2)" "@(f x ⊚2 y)"]]]
113+
(let [zloc (th/of-locmarked-string in zopts)]
114+
(is (= expected (-> zloc
115+
(z/insert-left 'x)
116+
(z/insert-right 'y)
117+
(th/root-locmarked-string)))
118+
in))))))

0 commit comments

Comments
 (0)