Skip to content

Commit 55bc7b6

Browse files
committed
Track parent location in zipper
1 parent e16ba20 commit 55bc7b6

File tree

2 files changed

+29
-19
lines changed

2 files changed

+29
-19
lines changed

src/rewrite_clj/zip/utils.clj

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@
44
;; ## Remove
55

66
(defn- update-in-path
7-
[{:keys [node path position] :as loc} k f]
7+
[{:keys [node path parent position] :as loc} k f]
88
(let [v (get path k)]
99
(if (seq v)
1010
{:node node
1111
:path (assoc path k (f v) :changed? true)
12+
:parent parent
1213
:position position}
1314
loc)))
1415

@@ -49,21 +50,23 @@
4950
(defn remove-and-move-left
5051
"Remove current node and move left. If current node is at the leftmost
5152
location, returns `nil`."
52-
[{:keys [position] {:keys [l] :as path} :path :as loc}]
53+
[{:keys [position parent] {:keys [l] :as path} :path :as loc}]
5354
(if (seq l)
5455
{:node (peek l)
5556
:path (-> path
5657
(update-in [:l] pop)
5758
(assoc :changed? true))
59+
:parent parent
5860
:position position}))
5961

6062
(defn remove-and-move-right
6163
"Remove current node and move right. If current node is at the rightmost
6264
location, returns `nil`."
63-
[{:keys [position] {:keys [r] :as path} :path :as loc}]
65+
[{:keys [position parent] {:keys [r] :as path} :path :as loc}]
6466
(if (seq r)
6567
{:node (first r)
6668
:path (-> path
6769
(update-in [:r] next)
6870
(assoc :changed? true))
71+
:parent parent
6972
:position position}))

src/rewrite_clj/zip/zip.clj

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
[root]
2222
{:node root
2323
:position [1 1]
24+
:parent nil
2425
:path nil})
2526

2627
(defn node
@@ -66,6 +67,7 @@
6667
(when cs
6768
{:node c
6869
:position [row (+ col (node/leader-length node))]
70+
:parent loc
6971
:path {:l []
7072
:pnodes (if path (conj (:pnodes path) node) [node])
7173
:ppath path
@@ -75,16 +77,14 @@
7577
"Returns the loc of the parent of the node at this loc, or nil if at
7678
the top"
7779
[loc]
78-
(let [{:keys [node position] {:keys [l ppath pnodes r changed?]} :path} loc]
79-
(when pnodes
80-
(let [pnode (peek pnodes)]
81-
(if changed?
82-
{:node (make-node loc pnode (concat l (cons node r)))
83-
:path (and ppath (assoc ppath :changed? true))
84-
:position position}
85-
{:node pnode
86-
:path ppath
87-
:position position})))))
80+
(let [{:keys [node parent position] {:keys [l ppath pnodes r changed?]} :path} loc]
81+
(when parent
82+
(if changed?
83+
{:node (make-node loc (peek pnodes) (concat l (cons node r)))
84+
:path (and ppath (assoc ppath :changed? true))
85+
:parent (:parent parent)
86+
:position position}
87+
parent))))
8888

8989
(defn root
9090
"zips all the way up and returns the root node, reflecting any
@@ -100,10 +100,11 @@
100100
(defn right
101101
"Returns the loc of the right sibling of the node at this loc, or nil"
102102
[loc]
103-
(let [{:keys [node position] {l :l [r & rnext :as rs] :r :as path} :path} loc]
103+
(let [{:keys [node parent position] {l :l [r & rnext :as rs] :r :as path} :path} loc]
104104
(when (and path rs)
105105
{:node r
106106
:path (assoc path :l (conj l node) :r rnext)
107+
:parent parent
107108
:position (node/+extent position (node/extent node))})))
108109

109110
(defn rightmost
@@ -116,42 +117,46 @@
116117
(defn left
117118
"Returns the loc of the left sibling of the node at this loc, or nil"
118119
[loc]
119-
(let [{:keys [node position] {:keys [l r] :as path} :path} loc]
120+
(let [{:keys [node parent position] {:keys [l r] :as path} :path} loc]
120121
(when (and path (seq l))
121122
{:node (peek l)
122123
:path (assoc path :l (pop l) :r (cons node r))
124+
:parent parent
123125
:position position})))
124126

125127
(defn leftmost
126128
"Returns the loc of the leftmost sibling of the node at this loc, or self"
127129
[loc]
128-
(let [{:keys [node position] {:keys [l r] :as path} :path} loc]
130+
(let [{:keys [node parent position] {:keys [l r] :as path} :path} loc]
129131
(if (and path (seq l))
130132
{:node (first l)
131133
:path (assoc path :l [] :r (concat (rest l) [node] r))
134+
:parent parent
132135
:position position}
133136
loc)))
134137

135138
(defn insert-left
136139
"Inserts the item as the left sibling of the node at this loc,
137140
without moving"
138141
[loc item]
139-
(let [{:keys [node position] {:keys [l] :as path} :path} loc]
142+
(let [{:keys [node parent position] {:keys [l] :as path} :path} loc]
140143
(if (nil? path)
141144
(throw (new Exception "Insert at top"))
142145
{:node node
143146
:path (assoc path :l (conj l item) :changed? true)
147+
:parent parent
144148
:position position})))
145149

146150
(defn insert-right
147151
"Inserts the item as the right sibling of the node at this loc,
148152
without moving"
149153
[loc item]
150-
(let [{:keys [node position] {:keys [r] :as path} :path} loc]
154+
(let [{:keys [node parent position] {:keys [r] :as path} :path} loc]
151155
(if (nil? path)
152156
(throw (new Exception "Insert at top"))
153157
{:node node
154158
:path (assoc path :r (cons item r) :changed? true)
159+
:parent parent
155160
:position position})))
156161

157162
(defn replace
@@ -214,16 +219,18 @@
214219
"Removes the node at loc, returning the loc that would have preceded
215220
it in a depth-first walk."
216221
[loc]
217-
(let [{:keys [node position] {:keys [l ppath pnodes r] :as path} :path} loc]
222+
(let [{:keys [node parent position] {:keys [l ppath pnodes r] :as path} :path} loc]
218223
(if (nil? path)
219224
(throw (new Exception "Remove at top"))
220225
(if (pos? (count l))
221226
(loop [loc {:node (peek l)
222227
:path (assoc path :l (pop l) :changed? true)
228+
:parent parent
223229
:position position}]
224230
(if-let [child (and (branch? loc) (down loc))]
225231
(recur (rightmost child))
226232
loc))
227233
{:node (make-node loc (peek pnodes) r)
228234
:path (and ppath (assoc ppath :changed? true))
235+
:parent (:parent parent)
229236
:position position}))))

0 commit comments

Comments
 (0)