Skip to content

Commit 1b0a54a

Browse files
committed
Track position of lefter nodes
1 parent 524ca11 commit 1b0a54a

File tree

3 files changed

+41
-23
lines changed

3 files changed

+41
-23
lines changed

src/rewrite_clj/zip/utils.clj

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,12 @@
4848
location, returns `nil`."
4949
[{:keys [position left] :as loc}]
5050
(if (seq left)
51-
(assoc loc
52-
:changed? true
53-
:node (peek left)
54-
:left (pop left))))
51+
(let [[lnode lpos] (peek left)]
52+
(assoc loc
53+
:changed? true
54+
:node lnode
55+
:position lpos
56+
:left (pop left)))))
5557

5658
(defn remove-and-move-right
5759
"Remove current node and move right. If current node is at the rightmost

src/rewrite_clj/zip/zip.clj

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656
(defn lefts
5757
"Returns a seq of the left siblings of this loc"
5858
[loc]
59-
(seq (:left loc)))
59+
(map first (:left loc)))
6060

6161
(defn down
6262
"Returns the loc of the leftmost child of the node at this loc, or
@@ -81,7 +81,9 @@
8181
(if changed?
8282
(assoc parent
8383
:changed? true
84-
:node (make-node loc (:node parent) (concat left (cons node right))))
84+
:node (make-node loc
85+
(:node parent)
86+
(concat (map first left) (cons node right))))
8587
parent))))
8688

8789
(defn root
@@ -101,7 +103,7 @@
101103
(when (and parent right)
102104
(assoc loc
103105
:node r
104-
:left (conj left node)
106+
:left (conj left [node position])
105107
:right rnext
106108
:position (node/+extent position (node/extent node))))))
107109

@@ -117,32 +119,34 @@
117119
[loc]
118120
(let [{:keys [node parent left right]} loc]
119121
(when (and parent (seq left))
120-
(assoc loc
121-
:node (peek left)
122-
:left (pop left)
123-
:right (cons node right)))))
122+
(let [[lnode lpos] (peek left)]
123+
(assoc loc
124+
:node lnode
125+
:position lpos
126+
:left (pop left)
127+
:right (cons node right))))))
124128

125129
(defn leftmost
126130
"Returns the loc of the leftmost sibling of the node at this loc, or self"
127131
[loc]
128132
(let [{:keys [node parent left right]} loc]
129133
(if (and parent (seq left))
130134
(assoc loc
131-
:node (first left)
135+
:node (ffirst left)
132136
:left []
133-
:right (concat (rest left) [node] right))
137+
:right (concat (map first (rest left)) [node] right))
134138
loc)))
135139

136140
(defn insert-left
137141
"Inserts the item as the left sibling of the node at this loc,
138142
without moving"
139143
[loc item]
140-
(let [{:keys [parent left]} loc]
141-
(if-not parent
142-
(throw (new Exception "Insert at top"))
143-
(assoc loc
144-
:changed? true
145-
:left (conj left item)))))
144+
(let [{:keys [parent position left]} loc]
145+
(if-not parent
146+
(throw (new Exception "Insert at top"))
147+
(assoc loc
148+
:changed? true
149+
:left (conj left [item position])))))
146150

147151
(defn insert-right
148152
"Inserts the item as the right sibling of the node at this loc,
@@ -216,10 +220,12 @@
216220
(if-not parent
217221
(throw (new Exception "Remove at top"))
218222
(if (seq left)
219-
(loop [loc (assoc loc
220-
:changed? true
221-
:node (peek left)
222-
:left (pop left))]
223+
(loop [loc (let [[lnode lpos] (peek left)]
224+
(assoc loc
225+
:changed? true
226+
:position lpos
227+
:node lnode
228+
:left (pop left)))]
223229
(if-let [child (and (branch? loc) (down loc))]
224230
(recur (rightmost child))
225231
loc))

test/rewrite_clj/zip/zip_test.clj

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,13 @@
3232
(fact "z/rightmost tracks position correctly"
3333
(let [root (base/of-string "[hello world]")]
3434
(-> root z/down z/rightmost z/position) => [1 8]))
35+
36+
(tabular
37+
(fact "z/left tracks position correctly"
38+
(let [root (base/of-string "[hello world]")
39+
zloc (nth (iterate z/left (z/rightmost (z/down root))) ?n)]
40+
(z/position zloc) => ?pos))
41+
?n ?pos
42+
0 [1 8]
43+
1 [1 7]
44+
2 [1 2])

0 commit comments

Comments
 (0)