Skip to content

Commit 8941fc9

Browse files
authored
paredit: pos arguments now also accept vector (#354)
Also tweaked/corrected related content in docstrings. Closes #344
1 parent 671238d commit 8941fc9

File tree

6 files changed

+109
-38
lines changed

6 files changed

+109
-38
lines changed

CHANGELOG.adoc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ A release with known breaking changes is marked with:
2626

2727
* `rewrite-clj.zip/insert-right` and `rewrite-clj.zip/append-child` no longer insert a space when inserting/appending after a comment node.
2828
{issue}346[#346] ({lread})
29+
* `rewrite.clj.paredit`
30+
** `pos` arguments now accepts vector `[row col]` in addition to map `{:row :col}`
31+
{issue}344[#344] ({lread})
2932

3033
=== v1.1.49 - 2024-11-18 [[v1.1.49]]
3134

src/rewrite_clj/paredit.cljc

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
(:require [rewrite-clj.custom-zipper.utils :as u]
66
[rewrite-clj.node :as nd]
77
[rewrite-clj.zip :as z]
8+
[rewrite-clj.zip.findz :as fz]
89
[rewrite-clj.zip.whitespace :as ws]))
910

1011
#?(:clj (set! *warn-on-reflection* true))
@@ -130,16 +131,20 @@
130131
- if inside string kills to end of string and stops there
131132
- If inside comment kills to end of line (not including linebreak)
132133
133-
`pos` should provide `{:row :col }` which are relative to the start of the given form the zipper represents
134-
`zloc` must be positioned at a node previous (given depth first) to the node at given pos"
134+
- `zloc` location is (inclusive) starting point for `pos` depth-first search
135+
- `pos` can be a `{:row :col}` map or a `[row col]` vector. The `row` and `col` values are
136+
1-based and relative to the start of the source code the zipper represents.
137+
138+
Throws if `zloc` was not created with [position tracking](/doc/01-user-guide.adoc#position-tracking)."
135139
[zloc pos]
136140
(if-let [candidate (z/find-last-by-pos zloc pos)]
137-
(cond
138-
(string-node? candidate) (kill-in-string-node candidate pos)
139-
(ws/comment? candidate) (kill-in-comment-node candidate pos)
140-
(and (empty-seq? candidate)
141-
(> (:col pos) (-> candidate z/node meta :col))) (z/remove candidate)
142-
:else (kill candidate))
141+
(let [pos (fz/pos-as-map pos)]
142+
(cond
143+
(string-node? candidate) (kill-in-string-node candidate pos)
144+
(ws/comment? candidate) (kill-in-comment-node candidate pos)
145+
(and (empty-seq? candidate)
146+
(> (:col pos) (-> candidate z/node meta :col))) (z/remove candidate)
147+
:else (kill candidate)))
143148
zloc))
144149

145150

@@ -194,14 +199,21 @@
194199
(defn kill-one-at-pos
195200
"In string and comment aware kill for one node/word at `pos` in `zloc`.
196201
202+
- `zloc` location is (inclusive) starting point for `pos` depth-first search
203+
- `pos` can be a `{:row :col}` map or a `[row col]` vector. The `row` and `col` values are
204+
1-based and relative to the start of the source code the zipper represents.
205+
206+
Throws if `zloc` was not created with [position tracking](/doc/01-user-guide.adoc#position-tracking).
207+
197208
- `(+ |100 100) => (+ |100)`
198209
- `(for |(bar do)) => (foo)`
199210
- `\"|hello world\" => \"| world\"`
200211
- ` ; |hello world => ; |world`"
201212
[zloc pos]
202213
(if-let [candidate (->> (z/find-last-by-pos zloc pos)
203214
(ws/skip z/right* ws/whitespace?))]
204-
(let [[bounds-row bounds-col] (z/position candidate)
215+
(let [pos (fz/pos-as-map pos)
216+
[bounds-row bounds-col] (z/position candidate)
205217
kill-in-node? (not (and (= (:row pos) bounds-row)
206218
(<= (:col pos) bounds-col)))]
207219
(cond
@@ -457,17 +469,19 @@
457469
(defn split-at-pos
458470
"In string aware split
459471
460-
Perform split at given position `pos` Like split, but:
472+
Perform split at given position `pos` Like split, but if inside string splits string into two strings.
461473
462-
- if inside string splits string into two strings
474+
- `zloc` location is (inclusive) starting point for `pos` depth-first search
475+
- `pos` can be a `{:row :col}` map or a `[row col]` vector. The `row` and `col` values are
476+
1-based and relative to the start of the source code the zipper represents.
463477
464-
`pos` should provide `{:row :col }` which are relative to the start of the given form the zipper represents
465-
`zloc` must be positioned at a node previous (given depth first) to the node at given pos"
478+
Throws if `zloc` was not created with [position tracking](/doc/01-user-guide.adoc#position-tracking)."
466479
[zloc pos]
467480
(if-let [candidate (z/find-last-by-pos zloc pos)]
468-
(if (string-node? candidate)
469-
(split-string candidate pos)
470-
(split candidate))
481+
(let [pos (fz/pos-as-map pos)]
482+
(if (string-node? candidate)
483+
(split-string candidate pos)
484+
(split candidate)))
471485
zloc))
472486

473487
(defn- join-seqs [left right]

src/rewrite_clj/zip.cljc

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -486,17 +486,30 @@
486486

487487
;; DO NOT EDIT FILE, automatically imported from: rewrite-clj.zip.findz
488488
(defn find-last-by-pos
489-
"Return `zloc` located to the last node spanning position `pos` that satisfies predicate `p?` else `nil`.
490-
Search is depth-first from the current node.
489+
"Return `zloc` located at the last node spanning position `pos` that satisfies the predicate `p?`, else `nil`.
491490
492-
NOTE: Does not ignore whitespace/comment nodes."
491+
- `zloc` location is (inclusive) starting point for `pos` depth-first search
492+
- `pos` can be a `{:row :col}` map or a `[row col]` vector. The `row` and `col` values are 1-based and relative to the
493+
start of the form represented by the zipper.
494+
- `p?` is optional and defaults to `(constantly true)`
495+
496+
Throws if `zloc` was not created with [position tracking](/doc/01-user-guide.adoc#position-tracking).
497+
498+
NOTE: Whitespace and comment nodes are included in the search."
493499
([zloc pos] (rewrite-clj.zip.findz/find-last-by-pos zloc pos))
494500
([zloc pos p?] (rewrite-clj.zip.findz/find-last-by-pos zloc pos p?)))
495501

496502
;; DO NOT EDIT FILE, automatically imported from: rewrite-clj.zip.findz
497503
(defn find-tag-by-pos
498-
"Return `zloc` located to the last node spanning position `pos` with tag `t` else `nil`.
499-
Search is depth-first from the current node."
504+
"Return `zloc` located at the last node spanning position `pos` with tag `t`, else `nil`.
505+
506+
- `zloc` location is (inclusive) starting point for `pos` depth-first search
507+
- `pos` can be a `{:row :col}` map or a `[row col]` vector. The `row` and `col` values are 1-based and relative to the
508+
start of the form represented by the zipper.
509+
510+
Throws if `zloc` was not created with [position tracking](/doc/01-user-guide.adoc#position-tracking).
511+
512+
NOTE: Whitespace and comment nodes are included in the search."
500513
[zloc pos t] (rewrite-clj.zip.findz/find-tag-by-pos zloc pos t))
501514

502515
;; DO NOT EDIT FILE, automatically imported from: rewrite-clj.zip.insert

src/rewrite_clj/zip/find.clj

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,16 @@
1919

2020
;; DO NOT EDIT FILE, automatically imported from: rewrite-clj.zip.findz
2121
(defn find-last-by-pos
22-
"Return `zloc` located to the last node spanning position `pos` that satisfies predicate `p?` else `nil`.
23-
Search is depth-first from the current node.
22+
"Return `zloc` located at the last node spanning position `pos` that satisfies the predicate `p?`, else `nil`.
2423
25-
NOTE: Does not ignore whitespace/comment nodes."
24+
- `zloc` location is (inclusive) starting point for `pos` depth-first search
25+
- `pos` can be a `{:row :col}` map or a `[row col]` vector. The `row` and `col` values are 1-based and relative to the
26+
start of the form represented by the zipper.
27+
- `p?` is optional and defaults to `(constantly true)`
28+
29+
Throws if `zloc` was not created with [position tracking](/doc/01-user-guide.adoc#position-tracking).
30+
31+
NOTE: Whitespace and comment nodes are included in the search."
2632
([zloc pos] (rewrite-clj.zip.findz/find-last-by-pos zloc pos))
2733
([zloc pos p?] (rewrite-clj.zip.findz/find-last-by-pos zloc pos p?)))
2834

@@ -67,8 +73,15 @@
6773

6874
;; DO NOT EDIT FILE, automatically imported from: rewrite-clj.zip.findz
6975
(defn find-tag-by-pos
70-
"Return `zloc` located to the last node spanning position `pos` with tag `t` else `nil`.
71-
Search is depth-first from the current node."
76+
"Return `zloc` located at the last node spanning position `pos` with tag `t`, else `nil`.
77+
78+
- `zloc` location is (inclusive) starting point for `pos` depth-first search
79+
- `pos` can be a `{:row :col}` map or a `[row col]` vector. The `row` and `col` values are 1-based and relative to the
80+
start of the form represented by the zipper.
81+
82+
Throws if `zloc` was not created with [position tracking](/doc/01-user-guide.adoc#position-tracking).
83+
84+
NOTE: Whitespace and comment nodes are included in the search."
7285
[zloc pos t] (rewrite-clj.zip.findz/find-tag-by-pos zloc pos t))
7386

7487
;; DO NOT EDIT FILE, automatically imported from: rewrite-clj.zip.findz

src/rewrite_clj/zip/findz.cljc

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,14 @@
1616
(additional node)))
1717
#(= (base/tag %) t)))
1818

19+
(defn pos-as-vec [pos]
20+
(if (map? pos) [(:row pos) (:col pos)] pos))
21+
22+
(defn pos-as-map [pos]
23+
(if (map? pos) pos (zipmap [:row :col] pos)))
24+
1925
(defn- position-in-range? [zloc pos]
20-
(let [[r c] (if (map? pos) [(:row pos) (:col pos)] pos)]
26+
(let [[r c] (pos-as-vec pos)]
2127
(when (or (<= r 0) (<= c 0))
2228
(throw (ex-info "zipper row and col positions are ones-based" {:pos pos})))
2329
(let [[[zstart-row zstart-col][zend-row zend-col]] (zraw/position-span zloc)]
@@ -44,10 +50,16 @@
4450
(first))))
4551

4652
(defn find-last-by-pos
47-
"Return `zloc` located to the last node spanning position `pos` that satisfies predicate `p?` else `nil`.
48-
Search is depth-first from the current node.
53+
"Return `zloc` located at the last node spanning position `pos` that satisfies the predicate `p?`, else `nil`.
54+
55+
- `zloc` location is (inclusive) starting point for `pos` depth-first search
56+
- `pos` can be a `{:row :col}` map or a `[row col]` vector. The `row` and `col` values are 1-based and relative to the
57+
start of the form represented by the zipper.
58+
- `p?` is optional and defaults to `(constantly true)`
59+
60+
Throws if `zloc` was not created with [position tracking](/doc/01-user-guide.adoc#position-tracking).
4961
50-
NOTE: Does not ignore whitespace/comment nodes."
62+
NOTE: Whitespace and comment nodes are included in the search."
5163
([zloc pos] (find-last-by-pos zloc pos (constantly true)))
5264
([zloc pos p?]
5365
(->> zloc
@@ -102,8 +114,15 @@
102114
(find-next zloc f))))
103115

104116
(defn find-tag-by-pos
105-
"Return `zloc` located to the last node spanning position `pos` with tag `t` else `nil`.
106-
Search is depth-first from the current node."
117+
"Return `zloc` located at the last node spanning position `pos` with tag `t`, else `nil`.
118+
119+
- `zloc` location is (inclusive) starting point for `pos` depth-first search
120+
- `pos` can be a `{:row :col}` map or a `[row col]` vector. The `row` and `col` values are 1-based and relative to the
121+
start of the form represented by the zipper.
122+
123+
Throws if `zloc` was not created with [position tracking](/doc/01-user-guide.adoc#position-tracking).
124+
125+
NOTE: Whitespace and comment nodes are included in the search."
107126
([zloc pos t]
108127
(find-last-by-pos zloc pos #(= (base/tag %) t))))
109128

test/rewrite_clj/paredit_test.cljc

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,9 @@
5050
["\"\"" ""]]]]
5151
(let [{:keys [pos s]} (th/pos-and-s s)
5252
zloc (z/of-string* s {:track-position? true})]
53-
(is (= expected (-> zloc (pe/kill-at-pos pos) th/root-locmarked-string))))))
53+
(doseq [pos [pos [(:row pos) (:col pos)]]]
54+
(testing (str s " @pos " pos)
55+
(is (= expected (-> zloc (pe/kill-at-pos pos) th/root-locmarked-string))))))))
5456

5557
(deftest kill-one-at-pos-test
5658
;; for this pos fn test, ⊚ in `s` represents character row/col the the `pos`
@@ -78,7 +80,9 @@
7880
["\"foo bar ⊚do\n lorem\"" "\"foo bar \n lorem\""]]]
7981
(let [{:keys [pos s]} (th/pos-and-s s)
8082
zloc (z/of-string* s {:track-position? true})]
81-
(is (= expected (-> zloc (pe/kill-one-at-pos pos) th/root-locmarked-string))))))
83+
(doseq [pos [pos [(:row pos) (:col pos)]]]
84+
(testing (str s " @pos " pos)
85+
(is (= expected (-> zloc (pe/kill-one-at-pos pos) th/root-locmarked-string))))))))
8286

8387
(deftest slurp-forward-test
8488
(doseq [opts zipper-opts]
@@ -207,10 +211,15 @@
207211
(is (= expected (-> zloc pe/split th/root-locmarked-string)) "string after"))))))
208212

209213
(deftest split-at-pos-test
210-
(is (= "(⊚\"Hello \" \"World\")"
211-
(-> (th/of-locmarked-string "⊚(\"Hello World\")" {:track-position? true})
212-
(pe/split-at-pos {:row 1 :col 9})
213-
th/root-locmarked-string))))
214+
;; for this pos fn test, ⊚ in `s` represents character row/col the the `pos`
215+
;; ⊚ in `expected` is at zipper node granularity
216+
(doseq [[s expected]
217+
[["(\"Hello ⊚World\")" "(⊚\"Hello \" \"World\")" ]]]
218+
(let [{:keys [pos s]} (th/pos-and-s s)
219+
zloc (z/of-string* s {:track-position? true})]
220+
(doseq [pos [pos [(:row pos) (:col pos)]]]
221+
(testing (str s " @pos " pos)
222+
(is (= expected (-> zloc (pe/split-at-pos pos) th/root-locmarked-string))))))))
214223

215224
(deftest join-test
216225
(doseq [opts zipper-opts]

0 commit comments

Comments
 (0)