|
6 | 6 | [rewrite-clj.node :as nd]
|
7 | 7 | [rewrite-clj.zip :as z]
|
8 | 8 | [rewrite-clj.zip.findz :as fz]
|
| 9 | + [rewrite-clj.zip.removez :as rz] |
9 | 10 | [rewrite-clj.zip.whitespace :as ws]))
|
10 | 11 |
|
11 | 12 | #?(:clj (set! *warn-on-reflection* true))
|
|
146 | 147 | zloc))
|
147 | 148 |
|
148 | 149 | (defn- find-word-bounds
|
149 |
| - [v col] |
150 |
| - (when (<= col (count v)) |
151 |
| - [(->> (seq v) |
| 150 | + "Return `[start-col end-col]` of word spanning 1-based `col` in `s`. |
| 151 | + Else nil if `col` is not in a word." |
| 152 | + [s col] |
| 153 | + (when (and (> col 0) |
| 154 | + (<= col (count s)) |
| 155 | + (not (#{\space \newline} (nth s (dec col))))) |
| 156 | + [(->> s |
152 | 157 | (take col)
|
153 | 158 | reverse
|
154 |
| - (take-while #(not (= % \space))) count (- col)) |
155 |
| - (->> (seq v) |
| 159 | + (take-while #(not (= % \space))) |
| 160 | + count |
| 161 | + (- col) |
| 162 | + inc) |
| 163 | + (->> s |
156 | 164 | (drop col)
|
157 | 165 | (take-while #(not (or (= % \space) (= % \newline))))
|
158 | 166 | count
|
159 | 167 | (+ col))]))
|
160 | 168 |
|
161 | 169 | (defn- remove-word-at
|
162 |
| - [v col] |
163 |
| - (when-let [[start end] (find-word-bounds v col)] |
164 |
| - (str (subs v 0 start) |
165 |
| - (subs v end)))) |
| 170 | + "Return `s` with word at 1-based `col` removed. |
| 171 | + If no word at `col` returns `s` unchanged" |
| 172 | + [s col] |
| 173 | + (if-let [[start end] (find-word-bounds s col)] |
| 174 | + (str (subs s 0 (dec start)) |
| 175 | + (subs s end)) |
| 176 | + s)) |
166 | 177 |
|
167 | 178 | (defn- kill-word-in-comment-node [zloc pos]
|
168 |
| - (let [col-bounds (-> zloc z/node meta :col)] |
| 179 | + (let [col-bounds (-> zloc z/position fz/pos-as-map :col)] |
169 | 180 | (-> zloc
|
170 | 181 | (z/replace (-> zloc
|
171 | 182 | z/node
|
|
174 | 185 | nd/comment-node)))))
|
175 | 186 |
|
176 | 187 | (defn- kill-word-in-string-node [zloc pos]
|
177 |
| - (let [bounds (-> zloc z/node meta) |
| 188 | + (let [bounds (-> zloc z/position fz/pos-as-map) |
178 | 189 | row-idx (- (:row pos) (:row bounds))
|
179 | 190 | col (if (= 0 row-idx)
|
180 | 191 | (- (:col pos) (:col bounds))
|
|
188 | 199 | nd/string-node)))))
|
189 | 200 |
|
190 | 201 | (defn kill-one-at-pos
|
191 |
| - "In string and comment aware kill for one node/word at `pos` in `zloc`. |
| 202 | + "Return `zloc` with node/word found at `pos` removed. |
192 | 203 |
|
193 |
| - - `zloc` location is (inclusive) starting point for `pos` depth-first search |
194 |
| - - `pos` can be a `{:row :col}` map or a `[row col]` vector. The `row` and `col` values are |
| 204 | + If `pos` is: |
| 205 | + - inside a string or comment, removes word at `pos`, if at whitespace, no-op. |
| 206 | + - otherwise removes node and moves left, or if no left node removes via [[rewrite-clj.zip/remove]]. |
| 207 | + If `pos` locates to whitespace between nodes, skips right to find node. |
| 208 | +
|
| 209 | + `zloc` location is (exclusive) starting point for `pos` search |
| 210 | + `pos` can be a `{:row :col}` map or a `[row col]` vector. The `row` and `col` values are |
195 | 211 | 1-based and relative to the start of the source code the zipper represents.
|
196 | 212 |
|
197 | 213 | Throws if `zloc` was not created with [position tracking](/doc/01-user-guide.adoc#position-tracking).
|
198 | 214 |
|
199 |
| - - `(+ |100 100) => (+ |100)` |
200 |
| - - `(for |(bar do)) => (foo)` |
| 215 | + - `(+ |100 200) => (|+ 200)` |
| 216 | + - `(foo |(bar do)) => (foo)` |
| 217 | + - `[|10 20 30]` => |[20 30]` |
201 | 218 | - `\"|hello world\" => \"| world\"`
|
202 |
| - - ` ; |hello world => ; |world`" |
| 219 | + - `; |hello world => ; |world`" |
203 | 220 | [zloc pos]
|
204 | 221 | (if-let [candidate (->> (z/find-last-by-pos zloc pos)
|
205 | 222 | (ws/skip z/right* ws/whitespace?))]
|
206 | 223 | (let [pos (fz/pos-as-map pos)
|
207 |
| - [bounds-row bounds-col] (z/position candidate) |
208 |
| - kill-in-node? (not (and (= (:row pos) bounds-row) |
209 |
| - (<= (:col pos) bounds-col)))] |
| 224 | + candidate-pos (-> candidate z/position fz/pos-as-map) |
| 225 | + kill-in-node? (not (and (= (:row pos) (:row candidate-pos)) |
| 226 | + (<= (:col pos) (:col candidate-pos))))] |
210 | 227 | (cond
|
211 | 228 | (and kill-in-node? (string-node? candidate)) (kill-word-in-string-node candidate pos)
|
212 | 229 | (and kill-in-node? (ws/comment? candidate)) (kill-word-in-comment-node candidate pos)
|
213 |
| - (not (z/leftmost? candidate)) (-> (z/remove candidate) |
214 |
| - (global-find-by-node (-> candidate z/left z/node))) |
215 |
| - :else (z/remove candidate))) |
| 230 | + :else |
| 231 | + (or (rz/remove-and-move-left candidate) |
| 232 | + (z/remove candidate)))) |
216 | 233 | zloc))
|
217 | 234 |
|
218 | 235 | (defn- find-slurpee-up [zloc f]
|
|
0 commit comments