|
1 | 1 | (ns rewrite-clj.zip.zip-test
|
2 |
| - (:require [midje.sweet :refer :all] |
| 2 | + (:require [clojure.test.check |
| 3 | + [generators :as gen] |
| 4 | + [properties :as prop]] |
| 5 | + [midje.sweet :refer :all] |
3 | 6 | [rewrite-clj.node :as node]
|
| 7 | + [rewrite-clj.node.generators :as g] |
4 | 8 | [rewrite-clj.test-helpers :refer :all]
|
5 | 9 | [rewrite-clj.zip
|
6 | 10 | [base :as base]
|
| 11 | + [utils :as u] |
| 12 | + [whitespace :as ws] |
7 | 13 | [zip :as z]]))
|
8 | 14 |
|
9 | 15 | (fact "zipper starts with position [1 1]"
|
|
92 | 98 | ?n ?pos
|
93 | 99 | 0 [1 3]
|
94 | 100 | 1 [1 8])
|
| 101 | + |
| 102 | +(def operations |
| 103 | + {:left z/left |
| 104 | + :right z/right |
| 105 | + :up z/up |
| 106 | + :down z/down |
| 107 | + :rightmost z/rightmost |
| 108 | + :leftmost z/leftmost |
| 109 | + :insert-right #(z/insert-right % (node/newline-node "\n")) |
| 110 | + :insert-left #(z/insert-left % (node/whitespace-node " ")) |
| 111 | + :replace #(z/replace % (node/token-node 'RR)) |
| 112 | + :next #(some-> % z/next (dissoc :end?)) |
| 113 | + :prev z/prev |
| 114 | + :remove z/remove |
| 115 | + :remove-left u/remove-left |
| 116 | + :remove-right u/remove-right |
| 117 | + :remove-and-move-left u/remove-and-move-left |
| 118 | + :remove-and-move-right u/remove-and-move-right}) |
| 119 | + |
| 120 | +(defn apply-operations |
| 121 | + "Apply a sequence of operations to `zloc`, rejecting any operations which |
| 122 | + either throw or make `zloc` nil. Note: we have to verify that zipping back |
| 123 | + up to the root doesn't fail, also." |
| 124 | + [zloc [op & ops]] |
| 125 | + (if-not op |
| 126 | + zloc |
| 127 | + (recur (or (try |
| 128 | + (let [zloc' ((operations op) zloc)] |
| 129 | + (z/root zloc') |
| 130 | + zloc') |
| 131 | + (catch Throwable t |
| 132 | + nil)) |
| 133 | + zloc) |
| 134 | + ops))) |
| 135 | + |
| 136 | +(defn char-at-position |
| 137 | + [s [row col]] |
| 138 | + (loop [[c & cs] (seq s) |
| 139 | + [cur-row cur-col] [1 1]] |
| 140 | + (cond |
| 141 | + (= [row col] [cur-row cur-col]) |
| 142 | + c |
| 143 | + |
| 144 | + (< (compare [row col] [cur-row cur-col]) 0) |
| 145 | + nil |
| 146 | + |
| 147 | + :else |
| 148 | + (recur cs (if (= c \newline) |
| 149 | + [(inc cur-row) 1] |
| 150 | + [cur-row (inc cur-col)]))))) |
| 151 | + |
| 152 | +(defn char-here |
| 153 | + [zloc] |
| 154 | + (cond |
| 155 | + (z/end? zloc) |
| 156 | + nil |
| 157 | + |
| 158 | + (= "" (node/string (z/node zloc))) |
| 159 | + (recur (z/next zloc)) |
| 160 | + |
| 161 | + :else |
| 162 | + (first (node/string (z/node zloc))))) |
| 163 | + |
| 164 | +(property "zipper position always matches row and column in root-string" |
| 165 | + (prop/for-all [node (g/node) |
| 166 | + operations (gen/vector (gen/elements (keys operations)) 1 8)] |
| 167 | + (let [zloc (apply-operations (base/edn* node) operations)] |
| 168 | + (= (char-here zloc) |
| 169 | + (char-at-position (base/root-string zloc) (z/position zloc)))))) |
0 commit comments