Skip to content

Commit c81e112

Browse files
author
Yannick Scherer
committed
Fixed Behaviour of some of the operations; added indentation-aware splice.
1 parent 4952aee commit c81e112

File tree

6 files changed

+88
-40
lines changed

6 files changed

+88
-40
lines changed

CHANGES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
- `insert-left`
1919
- `insert-right
2020
- `remove`
21+
- `splice`
2122

2223
### 0.2.0
2324

examples/rewrite_clj/cljx.clj

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
(ns ^{ :doc "Implementation of lynaghk/cljx's basic semantics using rewrite-clj."}
22
rewrite-clj.cljx
3-
(:require [rewrite-clj.parser :as p]
4-
[rewrite-clj.zip :as z]
5-
[rewrite-clj.printer :as prn]))
3+
(:require [rewrite-clj.zip :as z]))
64

75
;; ## Semantics
86
;;
@@ -36,10 +34,14 @@
3634
(or (.startsWith nm "+") (.startsWith nm "-")))))))
3735

3836
(defn- replace-with-spaces
39-
"Replace the given reader macro node with spaces."
37+
"Replace the given reader macro node with spaces. The resulting zipper
38+
will be on the first element following it."
4039
[zloc]
41-
(let [w (prn/estimate-length (z/node zloc))]
42-
(-> zloc (z/prepend-space w) z/remove)))
40+
(let [w (z/length zloc)]
41+
(-> zloc
42+
(z/prepend-space w) ;; add space
43+
z/remove* ;; remove original (without removing an extra space)
44+
z/next))) ;; go to following node
4345

4446
(defn- remove-reader-macro
4547
"Remove the macro part of the given reader macro node."
@@ -70,7 +72,12 @@
7072

7173
(defn run-cljx-test
7274
[profiles]
73-
(let [data (z/of-string ";; Test it!\n(defn my-inc\n [x]\n #+debug (println \"inc: x =\" x #-nomark \"[debug]\")\n (+ x 1))")]
75+
(let [data (z/of-string ";; Test it!
76+
(defn my-inc
77+
[x]
78+
#+debug (println \"inc: x =\" x #-nomark \"[debug]\" {:a 0
79+
:b 1})
80+
(+ x 1))")]
7481
(println "Original Code:")
7582
(z/print-root data)
7683
(println "\n")

src/rewrite_clj/zip.clj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
(def leftmost* z/leftmost)
7272
(def replace* z/replace)
7373
(def edit* z/edit)
74+
(def remove* z/remove)
7475

7576
;; ## Convenience Functions
7677

src/rewrite_clj/zip/edit.clj

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -60,19 +60,29 @@
6060
(z/replace zloc (conv/->tree (apply f form args)))))
6161

6262
(defn remove
63-
"Remove value at the given zipper location. Will remove a single whitespace following the
64-
node, too."
63+
"Remove value at the given zipper location. Returns the first non-whitespace node
64+
that would have preceded it in a depth-first walk. Will remove a single whitespace
65+
character following the current node."
6566
[zloc]
66-
(let [rloc (z/remove zloc)
67-
ws (z/right rloc)]
68-
(->> (if (= (zc/tag ws) :whitespace)
69-
(let [w (count (zc/value ws))]
70-
(-> ws (zc/append-space (dec w)) z/remove))
71-
rloc)
67+
(let [ws (z/right zloc)
68+
zloc (or
69+
(when (= (zc/tag ws) :whitespace)
70+
(let [w (dec (zc/length ws))]
71+
(when-not (neg? w)
72+
(-> ws z/remove (zc/append-space w)))))
73+
zloc)]
74+
(->> zloc
75+
z/remove
7276
(zc/skip-whitespace z/prev))))
7377

7478
(defn splice
75-
"Add the current node's children to the parent branch (in place of the current node)."
79+
"Add the current node's children to the parent branch (in place of the current node).
80+
The resulting zipper will be positioned on the first non-whitespace \"child\"."
7681
[zloc]
77-
(let [ch (z/children zloc)]
78-
(-> (reduce z/insert-right zloc (reverse ch)) z/remove z/right)))
82+
(if-not (z/branch? zloc)
83+
zloc
84+
(let [ch (z/children zloc)]
85+
(-> (reduce z/insert-right zloc (reverse ch))
86+
z/remove
87+
z/next
88+
zc/skip-whitespace))))

src/rewrite_clj/zip/indent.clj

Lines changed: 44 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -94,13 +94,15 @@
9494
"Searches for a multi-line node right of the given location (starting on
9595
the same line). If there is none, `nil` is returned."
9696
[zloc]
97-
(loop [zloc zloc]
98-
(when-not (or (not zloc) (z/end? zloc) (zc/linebreak? zloc))
99-
(if-not (z/branch? zloc)
100-
(recur (z/right zloc))
101-
(if (zf/find-tag zloc z/next :newline)
102-
zloc
103-
(recur (z/right zloc)))))))
97+
(or
98+
(loop [zloc zloc]
99+
(when-not (or (not zloc) (z/end? zloc) (zc/linebreak? zloc))
100+
(if-not (z/branch? zloc)
101+
(recur (z/right zloc))
102+
(if (zf/find-tag (zc/subzip zloc) z/next :newline)
103+
zloc
104+
(recur (z/right zloc))))))
105+
(recur (z/up zloc))))
104106

105107
;; ## Low-Level Indentation
106108

@@ -151,11 +153,11 @@
151153
;;
152154
;; The insert function should return the inserted element.
153155

154-
(defn insert-left
156+
(defn- insert-left*
155157
"Insert the given sexpr to the left of the given zipper location and indent
156158
accordingly."
157-
[zloc v]
158-
(let [rloc (ze/insert-left zloc v)
159+
[f zloc v]
160+
(let [rloc (f zloc v)
159161
delta (inc (zc/length (-> rloc z/left z/left)))]
160162
(if (zero? delta) rloc
161163
(if-let [iloc (find-node-to-indent rloc)]
@@ -164,11 +166,16 @@
164166
(zc/move-to-node rloc))
165167
rloc))))
166168

167-
(defn insert-right
169+
(def insert-left
170+
"Insert the given sexpr to the left of the given zipper location and indent
171+
accordingly."
172+
(partial insert-left* ze/insert-left))
173+
174+
(defn insert-right*
168175
"Insert the given sexpr to the right of the given zipper location and indent
169176
accordingly."
170-
[zloc v]
171-
(let [rloc (ze/insert-right zloc v)
177+
[f zloc v]
178+
(let [rloc (f zloc v)
172179
delta (inc (zc/length (-> rloc z/right z/right)))]
173180
(if (zero? delta) rloc
174181
(if-let [iloc (find-node-to-indent (-> rloc z/right z/right))]
@@ -177,16 +184,38 @@
177184
(zc/move-to-node rloc))
178185
rloc))))
179186

187+
(def insert-right
188+
"Insert the given sexpr to the right of the given zipper location and indent
189+
accordingly."
190+
(partial insert-right* ze/insert-right))
191+
180192
;; ## Remove + Indent
181193

182194
(defn remove
183195
"Remove the node at the given zipper location and indent accordingly."
184196
[zloc]
185-
(let [delta (dec (- (zc/length zloc)))
197+
(let [delta (- -1 (zc/length zloc))
186198
rloc (ze/remove zloc)]
187199
(if (zero? delta) rloc
188-
(if-let [iloc (find-node-to-indent (-> rloc z/next zc/skip-whitespace))]
200+
(if-let [iloc (find-node-to-indent (->> rloc z/next (zc/skip-whitespace z/next)))]
189201
(-> iloc
190202
(indent-children delta)
191203
(zc/move-to-node rloc))
192204
rloc))))
205+
206+
(defn splice
207+
"Add the current node's children to the parent branch (in place of the current node).
208+
The resulting zipper will be positioned on the first non-whitespace \"child\"."
209+
[zloc]
210+
(if-not (z/branch? zloc)
211+
zloc
212+
(let [w0 (zc/length zloc)
213+
w1 (apply + (map p/estimate-length (z/children zloc)))
214+
delta (- w1 w0)
215+
rloc (ze/splice zloc)]
216+
(if (zero? delta) rloc
217+
(if-let [iloc (find-node-to-indent rloc)]
218+
(-> iloc
219+
(indent-children delta)
220+
(zc/move-to-node rloc))
221+
rloc)))))

src/rewrite_clj/zip/walk.clj

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,18 @@
33
rewrite-clj.zip.walk
44
(:require [fast-zip.core :as z]
55
[rewrite-clj.zip.core :as c :only [subzip]]
6-
[rewrite-clj.zip.move :as m :only [next]]))
6+
[rewrite-clj.zip.move :as m :only [next]]
7+
[rewrite-clj.zip.find :as f :only [find]]))
78

89
(defn prewalk
910
"Perform a depth-first pre-order traversal starting at the given zipper location
1011
and apply the given function to each child node. If a predicate `p?` is given,
1112
only apply the function to nodes matching it."
1213
([zloc f] (prewalk zloc (constantly true) f))
1314
([zloc p? f]
14-
(loop [loc (c/subzip zloc)
15-
prv loc]
16-
(if-let [n0 (find loc m/next p?)]
15+
(loop [loc zloc]
16+
(if-let [n0 (f/find loc m/next p?)]
1717
(if-let [n1 (f n0)]
18-
(recur (m/next n1) n1)
19-
(recur (m/next n0) n0))
20-
(z/replace zloc (z/root prv))))))
18+
(recur (m/next n1))
19+
(recur (m/next n0)))
20+
(c/move-to-node loc zloc)))))

0 commit comments

Comments
 (0)