Skip to content

Commit f33e9e6

Browse files
committed
Describe zip API sub editing in docs
Added a new section to user guide. Minor updates to docstrings to clarify, recategorize and point to user guide. Closes #111
1 parent ac0ca1d commit f33e9e6

File tree

6 files changed

+169
-26
lines changed

6 files changed

+169
-26
lines changed

CHANGELOG.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ For a list of breaking changes see link:#v1-breaking[breaking changes].
1717
=== Unreleased
1818

1919
* Beef up docs on node creation https://github.com/clj-commons/rewrite-clj/issues/97[#97]
20+
* Describe subedit in docs https://github.com/clj-commons/rewrite-clj/issues/111[#111]
2021

2122
=== v1.0.579-alpha
2223

doc/01-user-guide.adoc

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,112 @@ It offers some functions that correspond to the standard Clojure `seq` functions
324324
;; => "{:prefix/a 10 :prefix/b 20}"
325325
----
326326

327+
// Targeted from docstrings
328+
[#sub-editing]
329+
==== Sub Editing with the Zip API
330+
331+
Sub editing allows you to effect changes to an isolated subtree (actually a sub zipper) while preserving your original location in the zipper
332+
333+
When sub editing, your sub zipper is isolated to the current node and its children.
334+
The sub zipper acts like, and is, a full zipper; `rewrite-clj.zip/end?` will return `true` when you have navigated to the end of the sub zipper.
335+
336+
This can be useful when you:
337+
338+
* Are not interested in restoring your location after digging down deep to make a change
339+
* Want to restrict your changes to a node and its children.
340+
It can be helpful to bound your movement when using functions that also affect current location such as `rewrite-clj.zip/remove`.
341+
342+
[source,Clojure]
343+
----
344+
(require '[rewrite-clj.zip :as z])
345+
346+
;; A sample to illustrate
347+
(def zloc (z/of-string "[a [b [c [d [e [f]]]]] g h]"))
348+
349+
;; ... and a little helper that navigates our location to the end node:
350+
(defn to-end [zloc]
351+
(->> zloc
352+
(iterate z/next)
353+
(drop-while (complement z/end?))
354+
first))
355+
356+
;; ... and a little editor to show which node was hit:
357+
(defn update-at-loc [zloc]
358+
(z/edit zloc #(symbol "UPDATED" (str %))))
359+
360+
;; If we don't use a sub zipper our end node is h:
361+
(-> zloc
362+
to-end
363+
update-at-loc
364+
z/root-string)
365+
;; => "[a [b [c [d [e [f]]]]] g UPDATED/h]"
366+
367+
;; If we subedit on the first node in the vector, we are restricted to that node.
368+
;; In our case that node is a:
369+
(-> zloc
370+
z/down
371+
(z/subedit->
372+
to-end
373+
update-at-loc)
374+
z/root-string)
375+
;; => "[UPDATED/a [b [c [d [e [f]]]]] g h]"
376+
377+
;; If we subedit on the second node in the vector, we are restricted to that node.
378+
;; In our case that node is [b [c [d [f]]]] with subedit end node f
379+
(-> zloc
380+
z/down
381+
z/right
382+
(z/subedit->
383+
to-end
384+
update-at-loc)
385+
z/root-string)
386+
;; => "[a [b [c [d [e [UPDATED/f]]]]] g h]"
387+
388+
;; To show our original location was preserved,
389+
;; after a subedit of the last node within the 2nd node in the vector,
390+
;; a movement right brings us to node g
391+
(-> zloc
392+
z/down
393+
z/right
394+
(z/subedit->
395+
to-end
396+
(z/edit #(symbol "UPDATED" (str %))))
397+
z/right
398+
z/string)
399+
;; => "g"
400+
----
401+
402+
The zip API walk functions also isolate your work to the current node.
403+
Let's explore:
404+
405+
[source,Clojure]
406+
----
407+
(require '[rewrite-clj.zip :as z])
408+
409+
;; Let's contrive an example with multiple top level forms:
410+
(def zloc (z/of-string "(def x 1) (def y [2 3 [4 [5]]])"))
411+
412+
;; Now let's add 100 to all numbers:
413+
(-> zloc
414+
(z/postwalk (fn select [zloc] (number? (z/sexpr zloc)))
415+
(fn visit [zloc] (z/edit zloc + 100)))
416+
z/root-string)
417+
;; => "(def x 101) (def y [2 3 [4 [5]]])"
418+
419+
;; Hmmm... what happened? Only the first number was affected.
420+
;; A new zipper automaticaly navigates to the first non-whitespace/non-comment node.
421+
;; In our example, this is node (def x 1).
422+
;; Our walk was isolated to current node (def x 1) so that's all that got updated
423+
424+
;; We can adapt to walk all nodes with a movement up to the top level prior to our walk
425+
(-> zloc
426+
z/up
427+
(z/postwalk (fn select [zloc] (number? (z/sexpr zloc)))
428+
(fn visit [zloc] (z/edit zloc + 100)))
429+
z/root-string)
430+
;; => "(def x 101) (def y [102 103 [104 [105]]])"
431+
----
432+
327433
// Targeted from docstrings
328434
[#position-tracking]
329435
==== Tracking Position with the Zip API

src/rewrite_clj/zip.cljc

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -122,17 +122,19 @@
122122
[[append-child*]]
123123
[[remove*]]
124124
125-
**Isolated update without changing location**
125+
**Update without changing location**
126126
[[edit-node]]
127+
[[edit->]]
128+
[[edit->>]]
129+
130+
**Isolated update without changing location**
127131
[[subedit-node]]
128132
[[subzip]]
129133
[[prewalk]]
130134
[[postwalk]]
131-
[[edit->]]
132-
[[edit->>]]
133135
[[subedit->]]
134136
[[subedit->>]]
135-
137+
136138
**Sequence operations**
137139
[[map]]
138140
[[map-keys]]
@@ -675,44 +677,58 @@
675677
(defn edit-node
676678
"Return zipper applying function `f` to `zloc`. The resulting
677679
zipper will be located at the same path (i.e. the same number of
678-
downwards and right movements from the root) incoming `zloc`."
680+
downwards and right movements from the root) incoming `zloc`.
681+
682+
See also [[subedit-node]] for an isolated edit."
679683
[zloc f] (rewrite-clj.zip.subedit/edit-node zloc f))
680684

681685
;; DO NOT EDIT FILE, automatically imported from: rewrite-clj.zip.subedit
682686
(defn subedit-node
683687
"Return zipper replacing current node in `zloc` with result of `f` applied to said node as an isolated sub-tree.
684-
The resulting zipper will be located on the root of the modified sub-tree."
688+
The resulting zipper will be located on the root of the modified sub-tree.
689+
690+
See [docs on sub editing](/doc/01-user-guide.adoc#sub-editing)."
685691
[zloc f] (rewrite-clj.zip.subedit/subedit-node zloc f))
686692

687693
;; DO NOT EDIT FILE, automatically imported from: rewrite-clj.zip.subedit
688694
(defn subzip
689-
"Create and return a zipper whose root is the current node in `zloc`."
695+
"Create and return a zipper whose root is the current node in `zloc`.
696+
697+
See [docs on sub editing](/doc/01-user-guide.adoc#sub-editing)."
690698
[zloc] (rewrite-clj.zip.subedit/subzip zloc))
691699

692700
;; DO NOT EDIT FILE, automatically imported from: rewrite-clj.zip.subedit
693701
(defmacro edit->
694702
"Like `->`, threads `zloc` through forms.
695703
The resulting zipper will be located at the same path (i.e. the same
696-
number of downwards and right movements from the root) as incoming `zloc`."
704+
number of downwards and right movements from the root) as incoming `zloc`.
705+
706+
See also [[subedit->]] for an isolated edit."
697707
[zloc & body] `(rewrite-clj.zip.subedit/edit-> ~zloc ~@body))
698708

699709
;; DO NOT EDIT FILE, automatically imported from: rewrite-clj.zip.subedit
700710
(defmacro edit->>
701711
"Like `->>`, threads `zloc` through forms.
702712
The resulting zipper will be located at the same path (i.e. the same
703-
number of downwards and right movements from the root) as incoming `zloc`."
713+
number of downwards and right movements from the root) as incoming `zloc`.
714+
715+
See also [[subedit->>]] for an isolated edit."
704716
[zloc & body] `(rewrite-clj.zip.subedit/edit->> ~zloc ~@body))
705717

706718
;; DO NOT EDIT FILE, automatically imported from: rewrite-clj.zip.subedit
707719
(defmacro subedit->
708720
"Like `->`, threads `zloc`, as an isolated sub-tree through forms, then zips
709-
up to, and locates at, the root of the modified sub-tree."
721+
up to, and locates at, the root of the modified sub-tree.
722+
723+
See [docs on sub editing](/doc/01-user-guide.adoc#sub-editing)."
710724
[zloc & body] `(rewrite-clj.zip.subedit/subedit-> ~zloc ~@body))
711725

712726
;; DO NOT EDIT FILE, automatically imported from: rewrite-clj.zip.subedit
713727
(defmacro subedit->>
714728
"Like `->`. Threads `zloc`, as an isolated sub-tree through forms, then zips
715-
up to, and locates at, the root of the modified sub-tree."
729+
up to, and locates at, the root of the modified sub-tree.
730+
731+
See [docs on sub editing](/doc/01-user-guide.adoc#sub-editing)."
716732
[zloc & body] `(rewrite-clj.zip.subedit/subedit->> ~zloc ~@body))
717733

718734
;; DO NOT EDIT FILE, automatically imported from: rewrite-clj.zip.walk
@@ -753,7 +769,8 @@
753769
zip/up
754770
(zip/prewalk ...))
755771
```
756-
"
772+
773+
See [docs on sub editing](/doc/01-user-guide.adoc#sub-editing)."
757774
([zloc f] (rewrite-clj.zip.walk/prewalk zloc f))
758775
([zloc p? f] (rewrite-clj.zip.walk/prewalk zloc p? f)))
759776

@@ -795,7 +812,8 @@
795812
zip/up
796813
(zip/postwalk ...))
797814
```
798-
"
815+
816+
See [docs on sub editing](/doc/01-user-guide.adoc#sub-editing)."
799817
([zloc f] (rewrite-clj.zip.walk/postwalk zloc f))
800818
([zloc p? f] (rewrite-clj.zip.walk/postwalk zloc p? f)))
801819

src/rewrite_clj/zip/subedit.cljc

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@
3636
(defn edit-node
3737
"Return zipper applying function `f` to `zloc`. The resulting
3838
zipper will be located at the same path (i.e. the same number of
39-
downwards and right movements from the root) incoming `zloc`."
39+
downwards and right movements from the root) incoming `zloc`.
40+
41+
See also [[subedit-node]] for an isolated edit."
4042
[zloc f]
4143
(let [zloc' (f zloc)]
4244
(assert (not (nil? zloc')) "function applied in 'edit-node' returned nil.")
@@ -45,21 +47,27 @@
4547
(defmacro edit->
4648
"Like `->`, threads `zloc` through forms.
4749
The resulting zipper will be located at the same path (i.e. the same
48-
number of downwards and right movements from the root) as incoming `zloc`."
50+
number of downwards and right movements from the root) as incoming `zloc`.
51+
52+
See also [[subedit->]] for an isolated edit."
4953
[zloc & body]
5054
`(edit-node ~zloc #(-> % ~@body)))
5155

5256
(defmacro edit->>
5357
"Like `->>`, threads `zloc` through forms.
5458
The resulting zipper will be located at the same path (i.e. the same
55-
number of downwards and right movements from the root) as incoming `zloc`."
59+
number of downwards and right movements from the root) as incoming `zloc`.
60+
61+
See also [[subedit->>]] for an isolated edit."
5662
[zloc & body]
5763
`(edit-node ~zloc #(->> % ~@body)))
5864

5965
;; ## Sub-Zipper
6066

6167
(defn subzip
62-
"Create and return a zipper whose root is the current node in `zloc`."
68+
"Create and return a zipper whose root is the current node in `zloc`.
69+
70+
See [docs on sub editing](/doc/01-user-guide.adoc#sub-editing)."
6371
[zloc]
6472
(let [zloc' (some-> zloc
6573
zraw/node
@@ -69,20 +77,26 @@
6977

7078
(defn subedit-node
7179
"Return zipper replacing current node in `zloc` with result of `f` applied to said node as an isolated sub-tree.
72-
The resulting zipper will be located on the root of the modified sub-tree."
80+
The resulting zipper will be located on the root of the modified sub-tree.
81+
82+
See [docs on sub editing](/doc/01-user-guide.adoc#sub-editing)."
7383
[zloc f]
7484
(let [zloc' (f (subzip zloc))]
7585
(assert (not (nil? zloc')) "function applied in 'subedit-node' returned nil.")
7686
(zraw/replace zloc (zraw/root zloc'))))
7787

7888
(defmacro subedit->
7989
"Like `->`, threads `zloc`, as an isolated sub-tree through forms, then zips
80-
up to, and locates at, the root of the modified sub-tree."
90+
up to, and locates at, the root of the modified sub-tree.
91+
92+
See [docs on sub editing](/doc/01-user-guide.adoc#sub-editing)."
8193
[zloc & body]
8294
`(subedit-node ~zloc #(-> % ~@body)))
8395

8496
(defmacro subedit->>
8597
"Like `->`. Threads `zloc`, as an isolated sub-tree through forms, then zips
86-
up to, and locates at, the root of the modified sub-tree."
98+
up to, and locates at, the root of the modified sub-tree.
99+
100+
See [docs on sub editing](/doc/01-user-guide.adoc#sub-editing)."
87101
[zloc & body]
88102
`(subedit-node ~zloc #(->> % ~@body)))

src/rewrite_clj/zip/walk.cljc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@
6060
zip/up
6161
(zip/prewalk ...))
6262
```
63-
"
63+
64+
See [docs on sub editing](/doc/01-user-guide.adoc#sub-editing)."
6465
([zloc f] (prewalk zloc (constantly true) f))
6566
([zloc p? f]
6667
(->> (partial prewalk-subtree p? f)
@@ -116,7 +117,8 @@
116117
zip/up
117118
(zip/postwalk ...))
118119
```
119-
"
120+
121+
See [docs on sub editing](/doc/01-user-guide.adoc#sub-editing)."
120122
([zloc f] (postwalk zloc (constantly true) f))
121123
([zloc p? f]
122124
(subedit/subedit-node zloc #(postwalk-subtree p? f %))))

template/rewrite_clj/zip.cljc

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -121,17 +121,19 @@
121121
[[append-child*]]
122122
[[remove*]]
123123
124-
**Isolated update without changing location**
124+
**Update without changing location**
125125
[[edit-node]]
126+
[[edit->]]
127+
[[edit->>]]
128+
129+
**Isolated update without changing location**
126130
[[subedit-node]]
127131
[[subzip]]
128132
[[prewalk]]
129133
[[postwalk]]
130-
[[edit->]]
131-
[[edit->>]]
132134
[[subedit->]]
133135
[[subedit->>]]
134-
136+
135137
**Sequence operations**
136138
[[map]]
137139
[[map-keys]]

0 commit comments

Comments
 (0)