Simplify tests

Simplify tests

--- test/asciinema_player/vt_test.cljs
+++ test/asciinema_player/vt_test.cljs
@@ -6,6 +6,18 @@
             [clojure.test.check.generators :as gen]
             [clojure.test.check.properties :as prop :include-macros true]
             [asciinema-player.vt :as vt :refer [parse make-vt feed feed-one feed-str get-params initial-saved-cursor compact-lines]]))
+
+(defn expect-lines [{lines :lines} expected]
+  (is (= (compact-lines lines) expected)))
+
+(defn expect-cursor
+  ([{{:keys [x y]} :cursor} expected-x expected-y]
+   (is (= x expected-x))
+   (is (= y expected-y)))
+  ([{{:keys [x y visible]} :cursor} expected-x expected-y expected-visible]
+   (is (= x expected-x))
+   (is (= y expected-y))
+   (is (= visible expected-visible))))

 (defn test-event [initial-state input expected-state expected-actions]
   (is (= (parse initial-state input) [expected-state expected-actions])))
@@ -422,28 +434,28 @@
                (set-fg 1))]

     (testing "printing within single line"
-      (let [{:keys [lines cursor]} (feed-str vt "ABC")]
-        (is (= lines [[[0x41 {:fg 1}] [0x42 {:fg 1}] [0x43 {:fg 1}] [0x20 {}]]
-                      [[0x20 {}] [0x20 {}] [0x20 {}] [0x20 {}]]
-                      [[0x20 {}] [0x20 {}] [0x20 {}] [0x20 {}]]]))
-        (is (= cursor {:x 3 :y 0 :visible true}))))
+      (let [vt (feed-str vt "ABC")]
+        (expect-lines vt [[["ABC" {:fg 1}] [" " {}]]
+                          [["    " {}]]
+                          [["    " {}]]])
+        (expect-cursor vt 3 0 true)))

     (testing "printing non-ASCII characters"
-      (let [{:keys [lines cursor]} (feed-str vt "ABCżÓłĆ")]
-        (is (= lines [[[0x41 {:fg 1}] [0x42 {:fg 1}] [0x43 {:fg 1}] [0x017c {:fg 1}]]
-                      [[0xd3 {:fg 1}] [0x0142 {:fg 1}] [0x0106 {:fg 1}] [0x20 {}]]
-                      [[0x20 {}] [0x20 {}] [0x20 {}] [0x20 {}]]]))
-        (is (= cursor {:x 3 :y 1 :visible true}))))
+      (let [vt (feed-str vt "ABCżÓłĆ")]
+        (expect-lines vt [[["ABCż" {:fg 1}]]
+                          [["ÓłĆ" {:fg 1}] [" " {}]]
+                          [["    " {}]]])
+        (expect-cursor vt 3 1 true)))

     (testing "printing ASCII art using special drawing character set"
-      (let [{:keys [lines cursor]} (-> vt
-                                       (feed-esc "(0") ; use drawing character set
-                                       (feed-str "abcd{|}~")
-                                       (feed-esc "(B") ; back to ASCII
-                                       (feed-str "abc"))]
-        (is (= (compact-lines lines) [[["▒␉␌␍" {:fg 1}]]
-                                      [["π≠£⋅" {:fg 1}]]
-                                      [["abc" {:fg 1}] [" " {}]]]))))
+      (let [vt (-> vt
+                   (feed-esc "(0") ; use drawing character set
+                   (feed-str "abcd{|}~")
+                   (feed-esc "(B") ; back to ASCII
+                   (feed-str "abc"))]
+        (expect-lines vt [[["▒␉␌␍" {:fg 1}]]
+                          [["π≠£⋅" {:fg 1}]]
+                          [["abc" {:fg 1}] [" " {}]]])))

     (testing "printing in insert mode"
       (let [vt (-> vt
@@ -452,253 +464,230 @@
                    (feed-csi "4h") ; enable insert mode
                    (set-fg 2)
                    (feed-str "HI"))]
-        (let [{:keys [lines cursor]} vt]
-          (is (= lines [[[0x41 {:fg 1}] [0x48 {:fg 2}] [0x49 {:fg 2}] [0x42 {:fg 1}]]
-                        [[0x20 {}] [0x20 {}] [0x20 {}] [0x20 {}]]
-                        [[0x20 {}] [0x20 {}] [0x20 {}] [0x20 {}]]]))
-          (is (= cursor {:x 3 :y 0 :visible true})))))
+        (expect-lines vt [[["A" {:fg 1}] ["HI" {:fg 2}] ["B" {:fg 1}]]
+                          [["    " {}]]
+                          [["    " {}]]])
+        (expect-cursor vt 3 0 true)))

     (testing "printing on the right edge of the line"
-      (let [vt (feed-str vt "ABCD")
-            {:keys [lines cursor]} vt]
-        (is (= lines [[[0x41 {:fg 1}] [0x42 {:fg 1}] [0x43 {:fg 1}] [0x44 {:fg 1}]]
-                      [[0x20 {}] [0x20 {}] [0x20 {}] [0x20 {}]]
-                      [[0x20 {}] [0x20 {}] [0x20 {}] [0x20 {}]]]))
-        (is (= cursor {:x 4 :y 0 :visible true}))
-        (let [vt (feed-str vt "EF")
-              {:keys [lines cursor]} vt]
-          (is (= lines [[[0x41 {:fg 1}] [0x42 {:fg 1}] [0x43 {:fg 1}] [0x44 {:fg 1}]]
-                        [[0x45 {:fg 1}] [0x46 {:fg 1}] [0x20 {}] [0x20 {}]]
-                        [[0x20 {}] [0x20 {}] [0x20 {}] [0x20 {}]]]))
-          (is (= cursor {:x 2 :y 1 :visible true})))
+      (let [vt (feed-str vt "ABCD")]
+        (expect-lines vt [[["ABCD" {:fg 1}]]
+                          [["    " {}]]
+                          [["    " {}]]])
+        (expect-cursor vt 4 0 true)
+        (let [vt (feed-str vt "EF")]
+          (expect-lines vt [[["ABCD" {:fg 1}]]
+                            [["EF" {:fg 1}] ["  " {}]]
+                            [["    " {}]]])
+          (expect-cursor vt 2 1 true))
         (let [vt (-> vt
                      (feed-csi "1;4H") ; move to the current position (in place)
-                     (feed-str "EF"))  ; next-print-wraps should have been reset above
-              {:keys [lines cursor]} vt]
-          (is (= lines [[[0x41 {:fg 1}] [0x42 {:fg 1}] [0x43 {:fg 1}] [0x45 {:fg 1}]]
-                        [[0x46 {:fg 1}] [0x20 {}] [0x20 {}] [0x20 {}]]
-                        [[0x20 {}] [0x20 {}] [0x20 {}] [0x20 {}]]]))
-          (is (= cursor {:x 1 :y 1 :visible true})))))
+                     (feed-str "EF"))] ; next-print-wraps should have been reset above
+          (expect-lines vt [[["ABCE" {:fg 1}]]
+                            [["F" {:fg 1}] ["   " {}]]
+                            [["    " {}]]])
+          (expect-cursor vt 1 1 true))))

     (testing "printing on the right edge of the line (auto-wrap off)"
       (let [vt (-> vt
                    (feed-csi "?7l") ; reset auto-wrap
-                   (feed-str "ABCDEF"))
-            {:keys [lines cursor]} vt]
-        (is (= lines [[[0x41 {:fg 1}] [0x42 {:fg 1}] [0x43 {:fg 1}] [0x46 {:fg 1}]]
-                      [[0x20 {}] [0x20 {}] [0x20 {}] [0x20 {}]]
-                      [[0x20 {}] [0x20 {}] [0x20 {}] [0x20 {}]]]))
-        (is (= cursor {:x 3 :y 0 :visible true}))))
+                   (feed-str "ABCDEF"))]
+        (expect-lines vt [[["ABCF" {:fg 1}]]
+                          [["    " {}]]
+                          [["    " {}]]])
+        (expect-cursor vt 3 0 true)))

     (testing "printing on the bottom right edge of the screen"
-      (let [vt (feed-str vt "AAAABBBBCCCC")
-            {:keys [lines cursor]} vt]
-        (is (= lines [[[0x41 {:fg 1}] [0x41 {:fg 1}] [0x41 {:fg 1}] [0x41 {:fg 1}]]
-                      [[0x42 {:fg 1}] [0x42 {:fg 1}] [0x42 {:fg 1}] [0x42 {:fg 1}]]
-                      [[0x43 {:fg 1}] [0x43 {:fg 1}] [0x43 {:fg 1}] [0x43 {:fg 1}]]]))
-        (is (= cursor {:x 4 :y 2 :visible true}))
-        (let [vt (feed-str vt "DD")
-              {:keys [lines cursor]} vt]
-          (is (= lines [[[0x42 {:fg 1}] [0x42 {:fg 1}] [0x42 {:fg 1}] [0x42 {:fg 1}]]
-                        [[0x43 {:fg 1}] [0x43 {:fg 1}] [0x43 {:fg 1}] [0x43 {:fg 1}]]
-                        [[0x44 {:fg 1}] [0x44 {:fg 1}] [0x20 {:fg 1}] [0x20 {:fg 1}]]]))
-          (is (= cursor {:x 2 :y 2 :visible true})))))
+      (let [vt (feed-str vt "AAAABBBBCCCC")]
+        (expect-lines vt [[["AAAA" {:fg 1}]]
+                          [["BBBB" {:fg 1}]]
+                          [["CCCC" {:fg 1}]]])
+        (expect-cursor vt 4 2 true)
+        (let [vt (feed-str vt "DD")]
+          (expect-lines vt [[["BBBB" {:fg 1}]]
+                            [["CCCC" {:fg 1}]]
+                            [["DD  " {:fg 1}]]])
+          (expect-cursor vt 2 2 true))))

     (testing "printing on the bottom right edge of the screen (auto-wrap off)"
       (let [vt (-> vt
                    (feed-str "AAAABBBBCC")
                    (feed-csi "?7l") ; reset auto-wrap
-                   (feed-str "DDEFGH"))
-            {:keys [lines cursor]} vt]
-        (is (= lines [[[0x41 {:fg 1}] [0x41 {:fg 1}] [0x41 {:fg 1}] [0x41 {:fg 1}]]
-                      [[0x42 {:fg 1}] [0x42 {:fg 1}] [0x42 {:fg 1}] [0x42 {:fg 1}]]
-                      [[0x43 {:fg 1}] [0x43 {:fg 1}] [0x44 {:fg 1}] [0x48 {:fg 1}]]]))
-        (is (= cursor {:x 3 :y 2 :visible true}))))))
+                   (feed-str "DDEFGH"))]
+        (expect-lines vt [[["AAAA" {:fg 1}]]
+                          [["BBBB" {:fg 1}]]
+                          [["CCDH" {:fg 1}]]])
+        (expect-cursor vt 3 2 true)))))

 (defn test-lf [f]
   (let [vt (-> (make-vt 4 7)
                (feed-str "AAAABBBBCCCCDDDDEEEEFFFFG")
                (set-bg 3))]
-    (let [{lines :lines {x :x y :y} :cursor} (-> vt (move-cursor 0 0) f)]
-      (is (= lines [[[0x41 {}] [0x41 {}] [0x41 {}] [0x41 {}]]
-                    [[0x42 {}] [0x42 {}] [0x42 {}] [0x42 {}]]
-                    [[0x43 {}] [0x43 {}] [0x43 {}] [0x43 {}]]
-                    [[0x44 {}] [0x44 {}] [0x44 {}] [0x44 {}]]
-                    [[0x45 {}] [0x45 {}] [0x45 {}] [0x45 {}]]
-                    [[0x46 {}] [0x46 {}] [0x46 {}] [0x46 {}]]
-                    [[0x47 {}] [0x20 {}] [0x20 {}] [0x20 {}]]]))
-      (is (= x 0))
-      (is (= y 1)))
-    (let [{lines :lines {x :x y :y} :cursor} (-> vt (move-cursor 1 1) f)]
-      (is (= lines [[[0x41 {}] [0x41 {}] [0x41 {}] [0x41 {}]]
-                    [[0x42 {}] [0x42 {}] [0x42 {}] [0x42 {}]]
-                    [[0x43 {}] [0x43 {}] [0x43 {}] [0x43 {}]]
-                    [[0x44 {}] [0x44 {}] [0x44 {}] [0x44 {}]]
-                    [[0x45 {}] [0x45 {}] [0x45 {}] [0x45 {}]]
-                    [[0x46 {}] [0x46 {}] [0x46 {}] [0x46 {}]]
-                    [[0x47 {}] [0x20 {}] [0x20 {}] [0x20 {}]]]))
-      (is (= x 1))
-      (is (= y 2)))
-    (let [{lines :lines {x :x y :y} :cursor} (-> vt (move-cursor 2 6) f)]
-      (is (= lines [[[0x42 {}] [0x42 {}] [0x42 {}] [0x42 {}]]
-                    [[0x43 {}] [0x43 {}] [0x43 {}] [0x43 {}]]
-                    [[0x44 {}] [0x44 {}] [0x44 {}] [0x44 {}]]
-                    [[0x45 {}] [0x45 {}] [0x45 {}] [0x45 {}]]
-                    [[0x46 {}] [0x46 {}] [0x46 {}] [0x46 {}]]
-                    [[0x47 {}] [0x20 {}] [0x20 {}] [0x20 {}]]
-                    [[0x20 {:bg 3}] [0x20 {:bg 3}] [0x20 {:bg 3}] [0x20 {:bg 3}]]]))
-      (is (= x 2))
-      (is (= y 6)))
+    (let [vt (-> vt (move-cursor 0 0) f)]
+      (expect-lines vt [[["AAAA" {}]]
+                        [["BBBB" {}]]
+                        [["CCCC" {}]]
+                        [["DDDD" {}]]
+                        [["EEEE" {}]]
+                        [["FFFF" {}]]
+                        [["G   " {}]]])
+      (expect-cursor vt 0 1))
+    (let [vt (-> vt (move-cursor 1 1) f)]
+      (expect-lines vt [[["AAAA" {}]]
+                        [["BBBB" {}]]
+                        [["CCCC" {}]]
+                        [["DDDD" {}]]
+                        [["EEEE" {}]]
+                        [["FFFF" {}]]
+                        [["G   " {}]]])
+      (expect-cursor vt 1 2))
+    (let [vt (-> vt (move-cursor 2 6) f)]
+      (expect-lines vt [[["BBBB" {}]]
+                        [["CCCC" {}]]
+                        [["DDDD" {}]]
+                        [["EEEE" {}]]
+                        [["FFFF" {}]]
+                        [["G   " {}]]
+                        [["    " {:bg 3}]]])
+      (expect-cursor vt 2 6))
     (let [vt (feed-csi vt "3;5r")] ; set scroll region 3-5
-      (let [vt (-> vt (move-cursor 2 1) f)
-            {lines :lines {x :x y :y} :cursor} vt]
-        (is (= lines [[[0x41 {}] [0x41 {}] [0x41 {}] [0x41 {}]]
-                      [[0x42 {}] [0x42 {}] [0x42 {}] [0x42 {}]]
-                      [[0x43 {}] [0x43 {}] [0x43 {}] [0x43 {}]]
-                      [[0x44 {}] [0x44 {}] [0x44 {}] [0x44 {}]]
-                      [[0x45 {}] [0x45 {}] [0x45 {}] [0x45 {}]]
-                      [[0x46 {}] [0x46 {}] [0x46 {}] [0x46 {}]]
-                      [[0x47 {}] [0x20 {}] [0x20 {}] [0x20 {}]]]))
-        (is (= x 2))
-        (is (= y 2)))
-      (let [vt (-> vt (move-cursor 2 3) f)
-            {lines :lines {x :x y :y} :cursor} vt]
-        (is (= lines [[[0x41 {}] [0x41 {}] [0x41 {}] [0x41 {}]]
-                      [[0x42 {}] [0x42 {}] [0x42 {}] [0x42 {}]]
-                      [[0x43 {}] [0x43 {}] [0x43 {}] [0x43 {}]]
-                      [[0x44 {}] [0x44 {}] [0x44 {}] [0x44 {}]]
-                      [[0x45 {}] [0x45 {}] [0x45 {}] [0x45 {}]]
-                      [[0x46 {}] [0x46 {}] [0x46 {}] [0x46 {}]]
-                      [[0x47 {}] [0x20 {}] [0x20 {}] [0x20 {}]]]))
-        (is (= x 2))
-        (is (= y 4)))
-      (let [vt (-> vt (move-cursor 2 4) f)
-            {lines :lines {x :x y :y} :cursor} vt]
-        (is (= lines [[[0x41 {}] [0x41 {}] [0x41 {}] [0x41 {}]]
-                      [[0x42 {}] [0x42 {}] [0x42 {}] [0x42 {}]]
-                      [[0x44 {}] [0x44 {}] [0x44 {}] [0x44 {}]]
-                      [[0x45 {}] [0x45 {}] [0x45 {}] [0x45 {}]]
-                      [[0x20 {:bg 3}] [0x20 {:bg 3}] [0x20 {:bg 3}] [0x20 {:bg 3}]]
-                      [[0x46 {}] [0x46 {}] [0x46 {}] [0x46 {}]]
-                      [[0x47 {}] [0x20 {}] [0x20 {}] [0x20 {}]]]))
-        (is (= x 2))
-        (is (= y 4)))
-      (let [vt (-> vt (move-cursor 2 5) f)
-            {lines :lines {x :x y :y} :cursor} vt]
-        (is (= lines [[[0x41 {}] [0x41 {}] [0x41 {}] [0x41 {}]]
-                      [[0x42 {}] [0x42 {}] [0x42 {}] [0x42 {}]]
-                      [[0x43 {}] [0x43 {}] [0x43 {}] [0x43 {}]]
-                      [[0x44 {}] [0x44 {}] [0x44 {}] [0x44 {}]]
-                      [[0x45 {}] [0x45 {}] [0x45 {}] [0x45 {}]]
-                      [[0x46 {}] [0x46 {}] [0x46 {}] [0x46 {}]]
-                      [[0x47 {}] [0x20 {}] [0x20 {}] [0x20 {}]]]))
-        (is (= x 2))
-        (is (= y 6)))
-      (let [vt (-> vt (move-cursor 2 6) f)
-            {lines :lines {x :x y :y} :cursor} vt]
-        (is (= lines [[[0x41 {}] [0x41 {}] [0x41 {}] [0x41 {}]]
-                      [[0x42 {}] [0x42 {}] [0x42 {}] [0x42 {}]]
-                      [[0x43 {}] [0x43 {}] [0x43 {}] [0x43 {}]]
-                      [[0x44 {}] [0x44 {}] [0x44 {}] [0x44 {}]]
-                      [[0x45 {}] [0x45 {}] [0x45 {}] [0x45 {}]]
-                      [[0x46 {}] [0x46 {}] [0x46 {}] [0x46 {}]]
-                      [[0x47 {}] [0x20 {}] [0x20 {}] [0x20 {}]]]))
-        (is (= x 2))
-        (is (= y 6))))
+      (let [vt (-> vt (move-cursor 2 1) f)]
+        (expect-lines vt [[["AAAA" {}]]
+                          [["BBBB" {}]]
+                          [["CCCC" {}]]
+                          [["DDDD" {}]]
+                          [["EEEE" {}]]
+                          [["FFFF" {}]]
+                          [["G   " {}]]])
+        (expect-cursor vt 2 2))
+      (let [vt (-> vt (move-cursor 2 3) f)]
+        (expect-lines vt [[["AAAA" {}]]
+                          [["BBBB" {}]]
+                          [["CCCC" {}]]
+                          [["DDDD" {}]]
+                          [["EEEE" {}]]
+                          [["FFFF" {}]]
+                          [["G   " {}]]])
+        (expect-cursor vt 2 4))
+      (let [vt (-> vt (move-cursor 2 4) f)]
+        (expect-lines vt [[["AAAA" {}]]
+                          [["BBBB" {}]]
+                          [["DDDD" {}]]
+                          [["EEEE" {}]]
+                          [["    " {:bg 3}]]
+                          [["FFFF" {}]]
+                          [["G   " {}]]])
+        (expect-cursor vt 2 4))
+      (let [vt (-> vt (move-cursor 2 5) f)]
+        (expect-lines vt [[["AAAA" {}]]
+                          [["BBBB" {}]]
+                          [["CCCC" {}]]
+                          [["DDDD" {}]]
+                          [["EEEE" {}]]
+                          [["FFFF" {}]]
+                          [["G   " {}]]])
+        (expect-cursor vt 2 6))
+      (let [vt (-> vt (move-cursor 2 6) f)]
+        (expect-lines vt [[["AAAA" {}]]
+                          [["BBBB" {}]]
+                          [["CCCC" {}]]
+                          [["DDDD" {}]]
+                          [["EEEE" {}]]
+                          [["FFFF" {}]]
+                          [["G   " {}]]])
+        (expect-cursor vt 2 6))
     (let [vt (feed-csi vt "20h") ; set new-line mode
-          vt (-> vt (move-cursor 2 1) f)
-          {{:keys [x y]} :cursor} vt]
-      (is (= x 0))
-      (is (= y 2)))))
+          vt (-> vt (move-cursor 2 1) f)]
+      (expect-cursor vt 0 2)))))

 (defn test-nel [f]
   (let [vt (-> (make-vt 4 7)
                (feed-str "AAAABBBBCCCCDDDDEEEEFFFFG")
                (set-bg 3))]
     (let [{lines :lines {x :x y :y} :cursor} (-> vt (move-cursor 0 0) f)]
-      (is (= lines [[[0x41 {}] [0x41 {}] [0x41 {}] [0x41 {}]]
-                    [[0x42 {}] [0x42 {}] [0x42 {}] [0x42 {}]]
-                    [[0x43 {}] [0x43 {}] [0x43 {}] [0x43 {}]]
-                    [[0x44 {}] [0x44 {}] [0x44 {}] [0x44 {}]]
-                    [[0x45 {}] [0x45 {}] [0x45 {}] [0x45 {}]]
-                    [[0x46 {}] [0x46 {}] [0x46 {}] [0x46 {}]]
-                    [[0x47 {}] [0x20 {}] [0x20 {}] [0x20 {}]]]))
+      (is (= (compact-lines lines) [[["AAAA" {}]]
+                                    [["BBBB" {}]]
+                                    [["CCCC" {}]]
+                                    [["DDDD" {}]]
+                                    [["EEEE" {}]]
+                                    [["FFFF" {}]]
+                                    [["G   " {}]]]))
       (is (= x 0))
       (is (= y 1)))
     (let [{lines :lines {x :x y :y} :cursor} (-> vt (move-cursor 1 1) f)]
-      (is (= lines [[[0x41 {}] [0x41 {}] [0x41 {}] [0x41 {}]]
-                    [[0x42 {}] [0x42 {}] [0x42 {}] [0x42 {}]]
-                    [[0x43 {}] [0x43 {}] [0x43 {}] [0x43 {}]]
-                    [[0x44 {}] [0x44 {}] [0x44 {}] [0x44 {}]]
-                    [[0x45 {}] [0x45 {}] [0x45 {}] [0x45 {}]]
-                    [[0x46 {}] [0x46 {}] [0x46 {}] [0x46 {}]]
-                    [[0x47 {}] [0x20 {}] [0x20 {}] [0x20 {}]]]))
+      (is (= (compact-lines lines) [[["AAAA" {}]]
+                                    [["BBBB" {}]]
+                                    [["CCCC" {}]]
+                                    [["DDDD" {}]]
+                                    [["EEEE" {}]]
+                                    [["FFFF" {}]]
+                                    [["G   " {}]]]))
       (is (= x 0))
       (is (= y 2)))
     (let [{lines :lines {x :x y :y} :cursor} (-> vt (move-cursor 2 6) f)]
-      (is (= lines [[[0x42 {}] [0x42 {}] [0x42 {}] [0x42 {}]]
-                    [[0x43 {}] [0x43 {}] [0x43 {}] [0x43 {}]]
-                    [[0x44 {}] [0x44 {}] [0x44 {}] [0x44 {}]]
-                    [[0x45 {}] [0x45 {}] [0x45 {}] [0x45 {}]]
-                    [[0x46 {}] [0x46 {}] [0x46 {}] [0x46 {}]]
-                    [[0x47 {}] [0x20 {}] [0x20 {}] [0x20 {}]]
-                    [[0x20 {:bg 3}] [0x20 {:bg 3}] [0x20 {:bg 3}] [0x20 {:bg 3}]]]))
+      (is (= (compact-lines lines) [[["BBBB" {}]]
+                                    [["CCCC" {}]]
+                                    [["DDDD" {}]]
+                                    [["EEEE" {}]]
+                                    [["FFFF" {}]]
+                                    [["G   " {}]]
+                                    [["    " {:bg 3}]]]))
       (is (= x 0))
       (is (= y 6)))
     (let [vt (feed-csi vt "3;5r")] ; set scroll region 3-5
       (let [vt (-> vt (move-cursor 2 1) f)
             {lines :lines {x :x y :y} :cursor} vt]
-        (is (= lines [[[0x41 {}] [0x41 {}] [0x41 {}] [0x41 {}]]
-                      [[0x42 {}] [0x42 {}] [0x42 {}] [0x42 {}]]
-                      [[0x43 {}] [0x43 {}] [0x43 {}] [0x43 {}]]
-                      [[0x44 {}] [0x44 {}] [0x44 {}] [0x44 {}]]
-                      [[0x45 {}] [0x45 {}] [0x45 {}] [0x45 {}]]
-                      [[0x46 {}] [0x46 {}] [0x46 {}] [0x46 {}]]
-                      [[0x47 {}] [0x20 {}] [0x20 {}] [0x20 {}]]]))
+        (is (= (compact-lines lines) [[["AAAA" {}]]
+                                      [["BBBB" {}]]
+                                      [["CCCC" {}]]
+                                      [["DDDD" {}]]
+                                      [["EEEE" {}]]
+                                      [["FFFF" {}]]
+                                      [["G   " {}]]]))
         (is (= x 0))
         (is (= y 2)))
       (let [vt (-> vt (move-cursor 2 3) f)
             {lines :lines {x :x y :y} :cursor} vt]
-        (is (= lines [[[0x41 {}] [0x41 {}] [0x41 {}] [0x41 {}]]
-                      [[0x42 {}] [0x42 {}] [0x42 {}] [0x42 {}]]
-                      [[0x43 {}] [0x43 {}] [0x43 {}] [0x43 {}]]
-                      [[0x44 {}] [0x44 {}] [0x44 {}] [0x44 {}]]
-                      [[0x45 {}] [0x45 {}] [0x45 {}] [0x45 {}]]
-                      [[0x46 {}] [0x46 {}] [0x46 {}] [0x46 {}]]
-                      [[0x47 {}] [0x20 {}] [0x20 {}] [0x20 {}]]]))
+        (is (= (compact-lines lines) [[["AAAA" {}]]
+                                      [["BBBB" {}]]
+                                      [["CCCC" {}]]
+                                      [["DDDD" {}]]
+                                      [["EEEE" {}]]
+                                      [["FFFF" {}]]
+                                      [["G   " {}]]]))
         (is (= x 0))
         (is (= y 4)))
       (let [vt (-> vt (move-cursor 2 4) f)
             {lines :lines {x :x y :y} :cursor} vt]
-        (is (= lines [[[0x41 {}] [0x41 {}] [0x41 {}] [0x41 {}]]
-                      [[0x42 {}] [0x42 {}] [0x42 {}] [0x42 {}]]
-                      [[0x44 {}] [0x44 {}] [0x44 {}] [0x44 {}]]
-                      [[0x45 {}] [0x45 {}] [0x45 {}] [0x45 {}]]
-                      [[0x20 {:bg 3}] [0x20 {:bg 3}] [0x20 {:bg 3}] [0x20 {:bg 3}]]
-                      [[0x46 {}] [0x46 {}] [0x46 {}] [0x46 {}]]
-                      [[0x47 {}] [0x20 {}] [0x20 {}] [0x20 {}]]]))
+        (is (= (compact-lines lines) [[["AAAA" {}]]
+                                      [["BBBB" {}]]
+                                      [["DDDD" {}]]
+                                      [["EEEE" {}]]
+                                      [["    " {:bg 3}]]
+                                      [["FFFF" {}]]
+                                      [["G   " {}]]]))
         (is (= x 0))
         (is (= y 4)))
       (let [vt (-> vt (move-cursor 2 5) f)
             {lines :lines {x :x y :y} :cursor} vt]
-        (is (= lines [[[0x41 {}] [0x41 {}] [0x41 {}] [0x41 {}]]
-                      [[0x42 {}] [0x42 {}] [0x42 {}] [0x42 {}]]
-                      [[0x43 {}] [0x43 {}] [0x43 {}] [0x43 {}]]
-                      [[0x44 {}] [0x44 {}] [0x44 {}] [0x44 {}]]
-                      [[0x45 {}] [0x45 {}] [0x45 {}] [0x45 {}]]
-                      [[0x46 {}] [0x46 {}] [0x46 {}] [0x46 {}]]
-                      [[0x47 {}] [0x20 {}] [0x20 {}] [0x20 {}]]]))
+        (is (= (compact-lines lines) [[["AAAA" {}]]
+                                      [["BBBB" {}]]
+                                      [["CCCC" {}]]
+                                      [["DDDD" {}]]
+                                      [["EEEE" {}]]
+                                      [["FFFF" {}]]
+                                      [["G   " {}]]]))
         (is (= x 0))
         (is (= y 6)))
       (let [vt (-> vt (move-cursor 2 6) f)
             {lines :lines {x :x y :y} :cursor} vt]
-        (is (= lines [[[0x41 {}] [0x41 {}] [0x41 {}] [0x41 {}]]
-                      [[0x42 {}] [0x42 {}] [0x42 {}] [0x42 {}]]
-                      [[0x43 {}] [0x43 {}] [0x43 {}] [0x43 {}]]
-                      [[0x44 {}] [0x44 {}] [0x44 {}] [0x44 {}]]
-                      [[0x45 {}] [0x45 {}] [0x45 {}] [0x45 {}]]
-                      [[0x46 {}] [0x46 {}] [0x46 {}] [0x46 {}]]
-                      [[0x47 {}] [0x20 {}] [0x20 {}] [0x20 {}]]]))
+        (is (= (compact-lines lines) [[["AAAA" {}]]
+                                      [["BBBB" {}]]
+                                      [["CCCC" {}]]
+                                      [["DDDD" {}]]
+                                      [["EEEE" {}]]
+                                      [["FFFF" {}]]
+                                      [["G   " {}]]]))
         (is (= x 0))
         (is (= y 6))))))

@@ -718,89 +707,89 @@
                (feed-str "AAAABBBBCCCCDDDDEEEEFFFFG")
                (set-bg 3))]
     (let [{lines :lines {x :x y :y} :cursor} (-> vt (move-cursor 0 6) f)]
-      (is (= lines [[[0x41 {}] [0x41 {}] [0x41 {}] [0x41 {}]]
-                    [[0x42 {}] [0x42 {}] [0x42 {}] [0x42 {}]]
-                    [[0x43 {}] [0x43 {}] [0x43 {}] [0x43 {}]]
-                    [[0x44 {}] [0x44 {}] [0x44 {}] [0x44 {}]]
-                    [[0x45 {}] [0x45 {}] [0x45 {}] [0x45 {}]]
-                    [[0x46 {}] [0x46 {}] [0x46 {}] [0x46 {}]]
-                    [[0x47 {}] [0x20 {}] [0x20 {}] [0x20 {}]]]))
+      (is (= (compact-lines lines) [[["AAAA" {}]]
+                                    [["BBBB" {}]]
+                                    [["CCCC" {}]]
+                                    [["DDDD" {}]]
+                                    [["EEEE" {}]]
+                                    [["FFFF" {}]]
+                                    [["G   " {}]]]))
       (is (= x 0))
       (is (= y 5)))
     (let [{lines :lines {x :x y :y} :cursor} (-> vt (move-cursor 1 5) f)]
-      (is (= lines [[[0x41 {}] [0x41 {}] [0x41 {}] [0x41 {}]]
-                    [[0x42 {}] [0x42 {}] [0x42 {}] [0x42 {}]]
-                    [[0x43 {}] [0x43 {}] [0x43 {}] [0x43 {}]]
-                    [[0x44 {}] [0x44 {}] [0x44 {}] [0x44 {}]]
-                    [[0x45 {}] [0x45 {}] [0x45 {}] [0x45 {}]]
-                    [[0x46 {}] [0x46 {}] [0x46 {}] [0x46 {}]]
-                    [[0x47 {}] [0x20 {}] [0x20 {}] [0x20 {}]]]))
+      (is (= (compact-lines lines) [[["AAAA" {}]]
+                                    [["BBBB" {}]]
+                                    [["CCCC" {}]]
+                                    [["DDDD" {}]]
+                                    [["EEEE" {}]]
+                                    [["FFFF" {}]]
+                                    [["G   " {}]]]))
       (is (= x 1))
       (is (= y 4)))
     (let [{lines :lines {x :x y :y} :cursor} (-> vt (move-cursor 2 0) f)]
-      (is (= lines [[[0x20 {:bg 3}] [0x20 {:bg 3}] [0x20 {:bg 3}] [0x20 {:bg 3}]]
-                    [[0x41 {}] [0x41 {}] [0x41 {}] [0x41 {}]]
-                    [[0x42 {}] [0x42 {}] [0x42 {}] [0x42 {}]]
-                    [[0x43 {}] [0x43 {}] [0x43 {}] [0x43 {}]]
-                    [[0x44 {}] [0x44 {}] [0x44 {}] [0x44 {}]]
-                    [[0x45 {}] [0x45 {}] [0x45 {}] [0x45 {}]]
-                    [[0x46 {}] [0x46 {}] [0x46 {}] [0x46 {}]]]))
+      (is (= (compact-lines lines) [[["    " {:bg 3}]]
+                                    [["AAAA" {}]]
+                                    [["BBBB" {}]]
+                                    [["CCCC" {}]]
+                                    [["DDDD" {}]]
+                                    [["EEEE" {}]]
+                                    [["FFFF" {}]]]))
       (is (= x 2))
       (is (= y 0)))
     (let [vt (feed-csi vt "3;5r")] ; set scroll region 3-5
       (let [vt (-> vt (move-cursor 2 5) f)
             {lines :lines {x :x y :y} :cursor} vt]
-        (is (= lines [[[0x41 {}] [0x41 {}] [0x41 {}] [0x41 {}]]
-                      [[0x42 {}] [0x42 {}] [0x42 {}] [0x42 {}]]
-                      [[0x43 {}] [0x43 {}] [0x43 {}] [0x43 {}]]
-                      [[0x44 {}] [0x44 {}] [0x44 {}] [0x44 {}]]
-                      [[0x45 {}] [0x45 {}] [0x45 {}] [0x45 {}]]
-                      [[0x46 {}] [0x46 {}] [0x46 {}] [0x46 {}]]
-                      [[0x47 {}] [0x20 {}] [0x20 {}] [0x20 {}]]]))
+        (is (= (compact-lines lines) [[["AAAA" {}]]
+                                      [["BBBB" {}]]
+                                      [["CCCC" {}]]
+                                      [["DDDD" {}]]
+                                      [["EEEE" {}]]
+                                      [["FFFF" {}]]
+                                      [["G   " {}]]]))
         (is (= x 2))
         (is (= y 4)))
       (let [vt (-> vt (move-cursor 2 3) f)
             {lines :lines {x :x y :y} :cursor} vt]
-        (is (= lines [[[0x41 {}] [0x41 {}] [0x41 {}] [0x41 {}]]
-                      [[0x42 {}] [0x42 {}] [0x42 {}] [0x42 {}]]
-                      [[0x43 {}] [0x43 {}] [0x43 {}] [0x43 {}]]
-                      [[0x44 {}] [0x44 {}] [0x44 {}] [0x44 {}]]
-                      [[0x45 {}] [0x45 {}] [0x45 {}] [0x45 {}]]
-                      [[0x46 {}] [0x46 {}] [0x46 {}] [0x46 {}]]
-                      [[0x47 {}] [0x20 {}] [0x20 {}] [0x20 {}]]]))
+        (is (= (compact-lines lines) [[["AAAA" {}]]
+                                      [["BBBB" {}]]
+                                      [["CCCC" {}]]
+                                      [["DDDD" {}]]
+                                      [["EEEE" {}]]
+                                      [["FFFF" {}]]
+                                      [["G   " {}]]]))
         (is (= x 2))
         (is (= y 2)))
       (let [vt (-> vt (move-cursor 2 2) f)
             {lines :lines {x :x y :y} :cursor} vt]
-        (is (= lines [[[0x41 {}] [0x41 {}] [0x41 {}] [0x41 {}]]
-                      [[0x42 {}] [0x42 {}] [0x42 {}] [0x42 {}]]
-                      [[0x20 {:bg 3}] [0x20 {:bg 3}] [0x20 {:bg 3}] [0x20 {:bg 3}]]
-                      [[0x43 {}] [0x43 {}] [0x43 {}] [0x43 {}]]
-                      [[0x44 {}] [0x44 {}] [0x44 {}] [0x44 {}]]
-                      [[0x46 {}] [0x46 {}] [0x46 {}] [0x46 {}]]
-                      [[0x47 {}] [0x20 {}] [0x20 {}] [0x20 {}]]]))
+        (is (= (compact-lines lines) [[["AAAA" {}]]
+                                      [["BBBB" {}]]
+                                      [["    " {:bg 3}]]
+                                      [["CCCC" {}]]
+                                      [["DDDD" {}]]
+                                      [["FFFF" {}]]
+                                      [["G   " {}]]]))
         (is (= x 2))
         (is (= y 2)))
       (let [vt (-> vt (move-cursor 2 1) f)
             {lines :lines {x :x y :y} :cursor} vt]
-        (is (= lines [[[0x41 {}] [0x41 {}] [0x41 {}] [0x41 {}]]
-                      [[0x42 {}] [0x42 {}] [0x42 {}] [0x42 {}]]
-                      [[0x43 {}] [0x43 {}] [0x43 {}] [0x43 {}]]
-                      [[0x44 {}] [0x44 {}] [0x44 {}] [0x44 {}]]
-                      [[0x45 {}] [0x45 {}] [0x45 {}] [0x45 {}]]
-                      [[0x46 {}] [0x46 {}] [0x46 {}] [0x46 {}]]
-                      [[0x47 {}] [0x20 {}] [0x20 {}] [0x20 {}]]]))
+        (is (= (compact-lines lines) [[["AAAA" {}]]
+                                      [["BBBB" {}]]
+                                      [["CCCC" {}]]
+                                      [["DDDD" {}]]
+                                      [["EEEE" {}]]
+                                      [["FFFF" {}]]
+                                      [["G   " {}]]]))
         (is (= x 2))
         (is (= y 0)))
       (let [vt (-> vt (move-cursor 2 0) f)
             {lines :lines {x :x y :y} :cursor} vt]
-        (is (= lines [[[0x41 {}] [0x41 {}] [0x41 {}] [0x41 {}]]
-                      [[0x42 {}] [0x42 {}] [0x42 {}] [0x42 {}]]
-                      [[0x43 {}] [0x43 {}] [0x43 {}] [0x43 {}]]
-                      [[0x44 {}] [0x44 {}] [0x44 {}] [0x44 {}]]
-                      [[0x45 {}] [0x45 {}] [0x45 {}] [0x45 {}]]
-                      [[0x46 {}] [0x46 {}] [0x46 {}] [0x46 {}]]
-                      [[0x47 {}] [0x20 {}] [0x20 {}] [0x20 {}]]]))
+        (is (= (compact-lines lines) [[["AAAA" {}]]
+                                      [["BBBB" {}]]
+                                      [["CCCC" {}]]
+                                      [["DDDD" {}]]
+                                      [["EEEE" {}]]
+                                      [["FFFF" {}]]
+                                      [["G   " {}]]]))
         (is (= x 2))
         (is (= y 0))))))

@@ -902,9 +891,9 @@
                  (move-cursor 2 1)
                  (feed-esc "#8"))
           {lines :lines {x :x y :y} :cursor} vt]
-      (is (= lines [[[0x45 {}] [0x45 {}] [0x45 {}] [0x45 {}]]
-                    [[0x45 {}] [0x45 {}] [0x45 {}] [0x45 {}]]
-                    [[0x45 {}] [0x45 {}] [0x45 {}] [0x45 {}]]]))
+      (is (= (compact-lines lines) [[["EEEE" {}]]
+                                    [["EEEE" {}]]
+                                    [["EEEE" {}]]]))
       (is (= x 2))
       (is (= y 1))))

@@ -1214,21 +1203,21 @@
                  (set-bg 3)
                  (move-cursor 1 1))]
       (let [{lines :lines {x :x y :y} :cursor} (feed-csi vt "J")]
-        (is (= lines [[[0x41 {}] [0x42 {}] [0x43 {}] [0x44 {}]]
-                      [[0x45 {}] [0x20 {:bg 3}] [0x20 {:bg 3}] [0x20 {:bg 3}]]
-                      [[0x20 {:bg 3}] [0x20 {:bg 3}] [0x20 {:bg 3}] [0x20 {:bg 3}]]]))
+        (is (= (compact-lines lines) [[["ABCD" {}]]
+                                      [["E" {}] ["   " {:bg 3}]]
+                                      [["    " {:bg 3}]]]))
         (is (= x 1))
         (is (= y 1)))
       (let [{lines :lines {x :x y :y} :cursor} (feed-csi vt "1J")]
-        (is (= lines [[[0x20 {:bg 3}] [0x20 {:bg 3}] [0x20 {:bg 3}] [0x20 {:bg 3}]]
-                      [[0x20 {:bg 3}] [0x20 {:bg 3}] [0x47 {}] [0x48 {}]]
-                      [[0x49 {}] [0x4a {}] [0x20 {}] [0x20 {}]]]))
+        (is (= (compact-lines lines) [[["    " {:bg 3}]]
+                                      [["  " {:bg 3}] ["GH" {}]]
+                                      [["IJ  " {}]]]))
         (is (= x 1))
         (is (= y 1)))
       (let [{lines :lines {x :x y :y} :cursor} (feed-csi vt "2J")]
-        (is (= lines [[[0x20 {:bg 3}] [0x20 {:bg 3}] [0x20 {:bg 3}] [0x20 {:bg 3}]]
-                      [[0x20 {:bg 3}] [0x20 {:bg 3}] [0x20 {:bg 3}] [0x20 {:bg 3}]]
-                      [[0x20 {:bg 3}] [0x20 {:bg 3}] [0x20 {:bg 3}] [0x20 {:bg 3}]]]))
+        (is (= (compact-lines lines) [[["    " {:bg 3}]]
+                                      [["    " {:bg 3}]]
+                                      [["    " {:bg 3}]]]))
         (is (= x 1))
         (is (= y 1)))))

@@ -1550,9 +1539,9 @@
                 {:keys [lines] {:keys [x y]} :cursor} vt]
             (is (= x 2))
             (is (= y 1))
-            (is (= lines [[[0x20 {:bg 2}] [0x20 {:bg 2}] [0x20 {:bg 2}] [0x20 {:bg 2}]]
-                          [[0x20 {:bg 2}] [0x20 {:bg 2}] [0x20 {:bg 2}] [0x20 {:bg 2}]]
-                          [[0x20 {:bg 2}] [0x20 {:bg 2}] [0x20 {:bg 2}] [0x20 {:bg 2}]]]))))
+            (is (= (compact-lines lines) [[["    " {:bg 2}]]
+                                          [["    " {:bg 2}]]
+                                          [["    " {:bg 2}]]]))))
         (testing "when in alternate buffer"
           (let [vt (-> vt
                        (feed-csi cseq)
@@ -1561,9 +1550,9 @@
                 {:keys [lines] {:keys [x y]} :cursor} vt]
             (is (= x 2))
             (is (= y 1))
-            (is (= lines [[[0x41 {}] [0x42 {}] [0x43 {}] [0x20 {}]]
-                          [[0x44 {}] [0x45 {}] [0x20 {}] [0x20 {}]]
-                          [[0x20 {}] [0x20 {}] [0x20 {}] [0x20 {}]]])))))))
+            (is (= (compact-lines lines) [[["ABC " {}]]
+                                          [["DE  " {}]]
+                                          [["    " {}]]])))))))

   (testing "CSI ?1049h (DECSM)" ; save cursor and switch to alternate buffer
     (let [vt (make-vt 4 3)]
@@ -1575,9 +1564,9 @@
               {:keys [lines] {:keys [x y]} :cursor} vt]
           (is (= x 2))
           (is (= y 1))
-          (is (= lines [[[0x20 {:bg 2}] [0x20 {:bg 2}] [0x20 {:bg 2}] [0x20 {:bg 2}]]
-                        [[0x20 {:bg 2}] [0x20 {:bg 2}] [0x20 {:bg 2}] [0x20 {:bg 2}]]
-                        [[0x20 {:bg 2}] [0x20 {:bg 2}] [0x20 {:bg 2}] [0x20 {:bg 2}]]]))))
+          (is (= (compact-lines lines) [[["    " {:bg 2}]]
+                                        [["    " {:bg 2}]]
+                                        [["    " {:bg 2}]]]))))
       (testing "when in alternate buffer"
         (let [vt (-> vt
                      (feed-csi "?1049h")
@@ -1586,9 +1575,9 @@
               {:keys [lines] {:keys [x y]} :cursor} vt]
           (is (= x 2))
           (is (= y 1))
-          (is (= lines [[[0x41 {}] [0x42 {}] [0x43 {}] [0x20 {}]]
-                        [[0x44 {}] [0x45 {}] [0x20 {}] [0x20 {}]]
-                        [[0x20 {}] [0x20 {}] [0x20 {}] [0x20 {}]]]))))))
+          (is (= (compact-lines lines) [[["ABC " {}]]
+                                        [["DE  " {}]]
+                                        [["    " {}]]]))))))

   (testing "CSI ?h (DECSM)" ; set multiple modes
     (let [vt (-> (make-vt 80 24)
@@ -1641,9 +1630,9 @@
                 {:keys [lines] {:keys [x y]} :cursor} vt]
             (is (= x 2))
             (is (= y 1))
-            (is (= lines [[[0x41 {}] [0x42 {}] [0x43 {}] [0x20 {}]]
-                          [[0x44 {}] [0x45 {}] [0x20 {}] [0x20 {}]]
-                          [[0x20 {}] [0x20 {}] [0x20 {}] [0x20 {}]]]))))
+            (is (= (compact-lines lines) [[["ABC " {}]]
+                                          [["DE  " {}]]
+                                          [["    " {}]]]))))
         (testing "when in alternate buffer"
           (let [vt (-> vt
                        (feed-str "ABC\n\rDE")
@@ -1654,9 +1643,9 @@
                 {:keys [lines] {:keys [x y]} :cursor} vt]
             (is (= x 1))
             (is (= y 2))
-            (is (= lines [[[0x41 {}] [0x42 {}] [0x43 {}] [0x20 {}]]
-                          [[0x44 {}] [0x45 {}] [0x20 {}] [0x20 {}]]
-                          [[0x20 {}] [0x20 {}] [0x20 {}] [0x20 {}]]])))))))
+            (is (= (compact-lines lines) [[["ABC " {}]]
+                                          [["DE  " {}]]
+                                          [["    " {}]]])))))))

   (testing "CSI ?1049l (DECRM)" ; switch back to primary buffer and restore cursor
     (let [vt (make-vt 4 3)]
@@ -1667,9 +1656,9 @@
               {:keys [lines] {:keys [x y]} :cursor} vt]
           (is (= x 0))
           (is (= y 0))
-          (is (= lines [[[0x41 {}] [0x42 {}] [0x43 {}] [0x20 {}]]
-                        [[0x44 {}] [0x45 {}] [0x20 {}] [0x20 {}]]
-                        [[0x20 {}] [0x20 {}] [0x20 {}] [0x20 {}]]]))))
+          (is (= (compact-lines lines) [[["ABC " {}]]
+                                        [["DE  " {}]]
+                                        [["    " {}]]]))))
       (testing "when in alternate buffer"
         (let [vt (-> vt
                      (feed-str "ABC\n\rDE")
@@ -1681,9 +1670,9 @@
               {:keys [lines] {:keys [x y]} :cursor} vt]
           (is (= x 2))
           (is (= y 1))
-          (is (= lines [[[0x41 {}] [0x42 {}] [0x43 {}] [0x20 {}]]
-                        [[0x44 {}] [0x45 {}] [0x20 {}] [0x20 {}]]
-                        [[0x20 {}] [0x20 {}] [0x20 {}] [0x20 {}]]]))))))
+          (is (= (compact-lines lines) [[["ABC " {}]]
+                                        [["DE  " {}]]
+                                        [["    " {}]]]))))))

   (testing "CSI ?l (DECRM)" ; reset multiple modes
     (let [vt (make-vt 80 24)]
@@ -1751,10 +1740,10 @@
                  (set-fg 1)
                  (feed-esc "7") ; save cursor
                  (feed-csi "!p"))] ; soft reset
-      (is (= (:lines vt) [[[0x41 {}] [0x42 {}] [0x43 {}] [0x44 {}]]
-                          [[0x45 {}] [0x46 {}] [0x47 {}] [0x48 {}]]
-                          [[0x49 {}] [0x20 {}] [0x20 {}] [0x20 {}]]
-                          [[0x20 {}] [0x20 {}] [0x20 {}] [0x20 {}]]]))
+      (is (= (compact-lines (:lines vt)) [[["ABCD" {}]]
+                                          [["EFGH" {}]]
+                                          [["I   " {}]]
+                                          [["    " {}]]]))
       (is (= (:cursor vt) {:x 2 :y 2 :visible true}))
       (is (= (:char-attrs vt) {}))
       (is (= (:insert-mode vt) false))


Add introspection query for enum values

Add introspection query for enum values

--- test/graphql_clj/executor_test.clj
+++ test/graphql_clj/executor_test.clj
@@ -477,3 +477,112 @@
           result (executor/execute nil mutation-schema (constantly nil) validated {"emails" ["this@that.com"]})]
       (println "result:" result)
       (is (not (:errors result))))))
+
+(def test-introspection-query "query IntrospectionQuery {
+    __schema {
+      queryType { name }
+      mutationType { name }
+      types {
+        ...FullType
+      }
+      directives {
+        name
+        description
+        locations
+        args {
+          ...InputValue
+        }
+      }
+    }
+  }
+
+  fragment FullType on __Type {
+    kind
+    name
+    description
+    fields(includeDeprecated: true) {
+      name
+      description
+      args {
+        ...InputValue
+      }
+      type {
+        ...TypeRef
+      }
+      isDeprecated
+      deprecationReason
+    }
+    inputFields {
+      ...InputValue
+    }
+    interfaces {
+      ...TypeRef
+    }
+    enumValues(includeDeprecated: true) {
+      name
+      description
+      isDeprecated
+      deprecationReason
+    }
+    possibleTypes {
+      ...TypeRef
+    }
+  }
+
+  fragment InputValue on __InputValue {
+    name
+    description
+    type { ...TypeRef }
+    defaultValue
+  }
+
+  fragment TypeRef on __Type {
+    kind
+    name
+    ofType {
+      kind
+      name
+      ofType {
+        kind
+        name
+        ofType {
+          kind
+          name
+          ofType {
+            kind
+            name
+            ofType {
+              kind
+              name
+              ofType {
+                kind
+                name
+                ofType {
+                  kind
+                  name
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }")
+
+(deftest introspection-query
+  (testing "introspection query"
+    (let [validated-query (->> test-introspection-query
+                               parser/parse-query-document
+                               (qv/validate-query (peek valid-starwars-schema)))
+          result (executor/execute nil valid-starwars-schema (constantly nil) validated-query nil)]
+      (is (nil? (:errors result)))
+      (is (not (nil? (:data result))))
+      (is (not (nil? (get-in result [:data "__schema"]))))
+      (let [types (get-in result [:data "__schema" "types"])
+            episode-type (filter #(= 'Episode (get % "name")) types)]
+        (is (not (nil? types)))
+        (println "episode-type:" episode-type)
+        (is (= 1 (count episode-type)))
+        (is (= 3 (count (get (first episode-type) "enumValues" -1)))))
+      ;; (clojure.pprint/pprint result)
+      )))


Upgrade to new kws.

Upgrade to new kws.

--- test/onyx/peer/monitoring_test.clj
+++ test/onyx/peer/monitoring_test.clj
@@ -26,7 +26,7 @@

 (def catalog
   [{:onyx/name :in
-    :onyx/ident :core.async/read-from-chan
+    :onyx/plugin :onyx.plugin.core-async/input
     :onyx/type :input
     :onyx/medium :core.async
     :onyx/batch-size batch-size
@@ -39,7 +39,7 @@
     :onyx/batch-size batch-size}

    {:onyx/name :out
-    :onyx/ident :core.async/write-to-chan
+    :onyx/plugin :onyx.plugin.core-async/output
     :onyx/type :output
     :onyx/medium :core.async
     :onyx/batch-size batch-size


Add passing RFC 4180 compliant implementation of read-csv

--- src/testdouble/cljs/csv.cljs
+++ src/testdouble/cljs/csv.cljs
@@ -11,6 +11,9 @@

 (defn- write-data [data separator newline quote?]
   (str/join newline (map #(seperate % separator quote?) data)))
+
+(defn- conj-in [coll index x]
+  (assoc coll index (conj (nth coll index) x)))

 (def ^:private newlines
   {:lf "\n" :cr+lf "\r\n"})
@@ -49,6 +52,101 @@
   [data & options]
   (let [{:keys [separator newline] :or {separator "," newline :lf}} options]
     (if-let [newline-char (get newlines newline)]
-      (->> (str/split data newline-char)
-           (map #(str/split % separator)))
+      (let [data-length (count data)]
+        (loop [index 0
+               state :in-field
+               in-quoted-field false
+               field-buffer nil
+               rows nil]
+          (let [last-row-index (- (count rows) 1)]
+            (if (< index data-length)
+              (let [char (nth data index)
+                    next-char (if (< index (- data-length 1))
+                                (nth data (+ index 1))
+                                nil)
+                    str-char (str char)]
+                (case state
+                  :in-field
+                  (cond
+                    (= str-char "\"")
+                    (if in-quoted-field
+                      (if (= (str next-char) "\"")
+                        (recur (+ index 2)
+                               :in-field
+                               true
+                               (str field-buffer char)
+                               rows)
+                        (recur (+ index 1) :in-field false field-buffer rows))
+                      (recur (+ index 1) :in-field true field-buffer rows))
+
+                    (= str-char separator)
+                    (if in-quoted-field
+                      (recur (+ index 1)
+                             :in-field
+                             in-quoted-field
+                             (str field-buffer char)
+                             rows)
+                      (recur (+ index 1)
+                             :end-field
+                             in-quoted-field
+                             ""
+                             (conj-in rows last-row-index field-buffer)))
+
+                    (= str-char "\r")
+                    (if (and (= newline :cr+lf) (not in-quoted-field))
+                      (recur (+ index 1)
+                             :in-field
+                             in-quoted-field
+                             field-buffer
+                             rows)
+                      (recur (+ index 1)
+                             :in-field
+                             in-quoted-field
+                             (str field-buffer char)
+                             rows))
+
+                    (= str-char "\n")
+                    (if in-quoted-field
+                      (recur (+ index 1)
+                             :in-field
+                             in-quoted-field
+                             (str field-buffer char)
+                             rows)
+                      (recur (+ index 1)
+                             :end-line
+                             in-quoted-field
+                             ""
+                             (conj-in rows last-row-index field-buffer)))
+
+                    :else
+                    (recur (+ index 1)
+                           :in-field
+                           in-quoted-field
+                           (str field-buffer char)
+                           (if (> (count rows) 0)
+                             rows
+                             (conj (or rows []) []))))
+
+                  :end-field
+                  (case str-char
+                    "\""
+                    (recur (+ index 1) :in-field true field-buffer rows)
+
+                    (recur (+ index 1) :in-field in-quoted-field str-char rows))
+
+                  :end-line
+                  (case str-char
+                    "\""
+                    (recur (+ index 1)
+                           :in-field
+                           true
+                           field-buffer
+                           (conj (or rows []) []))
+
+                    (recur (+ index 1)
+                           :in-field
+                           in-quoted-field
+                           (str field-buffer char)
+                           (conj (or rows []) [])))))
+              (conj-in rows last-row-index field-buffer)))))
       (throw (js/Error. newline-error-message)))))


Length is always +1 to current index :-)

--- src/trustroots/handlers.cljs
+++ src/trustroots/handlers.cljs
@@ -126,8 +126,7 @@
    (let [navigator (get-in db [:services :navigator])]
      (.push navigator (clj->js {:index (-> navigator
                                            (.getCurrentRoutes)
-                                           (.-length)
-                                           (+ 1))
+                                           (.-length))
                                 :name (str value)})))
    (assoc-in db [:page] value)))


[#1077] Parse dates in filters properly

[#1077] Parse dates in filters properly

Also renamed double dollar quote function.

--- backend/src/akvo/lumen/lib/aggregation/filter.clj
+++ backend/src/akvo/lumen/lib/aggregation/filter.clj
@@ -21,19 +21,20 @@
                         (take 10)
                         (apply str))))

-(defn $ize [v]
+(defn dollar-quote
+  [v]
   (let [tag (random-tag)]
     (format "$%s$%s$%s$" tag v tag)))

 (defn parse-number [s]
   (try
-    ($ize (Double/parseDouble s))
+    (dollar-quote (Double/parseDouble s))
     (catch NumberFormatException e
       (invalid-filter "Not a number" {:string s}))))

 (defn parse-date [s]
   (try
-    (java.sql.Timestamp. (/ s 1000))
+    (java.sql.Timestamp. (* s 1000))
     (catch NumberFormatException e
       (invalid-filter "Not a timestamp" {:string s}))))

@@ -77,7 +78,7 @@
       "text" (format "coalesce(%1$s, '') %2$s %3$s"
                      column-name
                      op
-                     ($ize value))
+                     (dollar-quote value))
       (invalid-filter "Type not supported" {:type column-type}))))

 (defmethod filter-sql "isEmpty"


Add with-reflection benchmarks

Add with-reflection benchmarks

--- benchmarks/caesium/crypto/secretbox_benchmark.clj
+++ benchmarks/caesium/crypto/secretbox_benchmark.clj
@@ -14,26 +14,41 @@

 (deftest ^:benchmark to-buf!-benchmarks
   (let [sizes (map (partial bit-shift-left 1) [6 8 10 12 20 24])]
-    (println "secretbox to-buf! macros vs fn vs no casts with direct bufs")
+    (println "secretbox to-buf! with direct bufs")
     (println "these bufs already exist, so there is no allocation")
     (doseq [[size msg] (map (juxt identity random-direct-byte-buf) sizes)
             f [s/secretbox-easy-to-direct-byte-bufs-with-macros!
                s/secretbox-easy-to-direct-byte-bufs!
-               s/secretbox-easy-to-byte-bufs-nocast!]]
+               s/secretbox-easy-to-byte-bufs-nocast!
+               s/secretbox-easy-refl!]]
       (println f (fmt-bytes size))
       (let [key (random-direct-byte-buf s/keybytes)
             nonce (random-direct-byte-buf s/noncebytes)
             out (ByteBuffer/allocateDirect (+ s/macbytes size))]
         (bench (f out msg nonce key))))

-    (println "secretbox to-buf! macros vs fn vs no casts with indirect bufs")
+    (println "secretbox to-buf! with indirect bufs")
     (println "these bufs already exist, so there is no allocation")
     (doseq [[size msg] (map (juxt identity random-indirect-byte-buf) sizes)
             f [s/secretbox-easy-to-indirect-byte-bufs-with-macros!
                s/secretbox-easy-to-indirect-byte-bufs!
-               s/secretbox-easy-to-byte-bufs-nocast!]]
+               s/secretbox-easy-to-byte-bufs-nocast!
+               s/secretbox-easy-refl!]]
       (println f (fmt-bytes size))
       (let [key (random-indirect-byte-buf s/keybytes)
             nonce (random-indirect-byte-buf s/noncebytes)
             out (ByteBuffer/allocate (+ s/macbytes size))]
+        (bench (f out msg nonce key))))
+
+    (println "secretbox to-buf! with byte arrays")
+    (println "these bufs already exist, so there is no allocation")
+    (doseq [[size msg] (map (juxt identity randombytes) sizes)
+            f [s/secretbox-easy-to-indirect-byte-bufs-with-macros!
+               s/secretbox-easy-to-indirect-byte-bufs!
+               s/secretbox-easy-to-byte-bufs-nocast!
+               s/secretbox-easy-refl!]]
+      (println f (fmt-bytes size))
+      (let [key (randombytes s/keybytes)
+            nonce (randombytes s/noncebytes)
+            out (randombytes (+ s/macbytes size))]
         (bench (f out msg nonce key))))))


clojure.string/replace's signature has changed

Previously, the callback function was passed several arguments: the
entire match followed by the backreferences. Now the callback is passed
the same elements in a vector as the sole argument. This makes the
ClojureScript implementation match the Clojure implementation.

--- src-cljs/frontend/utils/docs.cljs
+++ src-cljs/frontend/utils/docs.cljs
@@ -67,26 +67,26 @@

 (defn replace-variables [html]
   (string/replace html #"\{\{\s*([^\s]*)\s*(?:\|\s*([\w-]*)\s*)?\}\}"
-                  (fn [s m1 m2]
-                    (let [[name & path] (string/split m1 #"\.")
+                  (fn [[match var-name-and-path filter-name]]
+                    (let [[name & path] (string/split var-name-and-path #"\.")
                           var (case name
                                 "versions" (aget js/window "CI" "Versions")
                                 "api_data" (aget js/window "circle_api_data")
                                 nil)
                           val (when var (apply aget var path))
-                          filter (case m2
+                          filter (case filter-name
                                    "code-list" code-list-filter
                                    "api-endpoint" api-endpoint-filter
                                    identity)]
-                      ;; Fall back to the full string if it doesn't match here.
+                      ;; Fall back to the matched string if it we don't have a value for it.
                       (if-not val
-                        s
+                        match
                         (filter (utils/js->clj-kw val)))))))

 (defn replace-asset-paths [html]
   (string/replace html #"\(asset:/(/.*?)\)"
-                  (fn [s match]
-                    (str "(" (stefon/asset-path match) ")"))))
+                  (fn [[_ asset]]
+                    (str "(" (stefon/asset-path asset) ")"))))

 (defn render-markdown [input]
   (when input


complete included correctly now

complete included correctly now

--- dot/lein/profiles.clj
+++ dot/lein/profiles.clj
@@ -4,7 +4,6 @@
             [lein-ritz "0.7.0"]
             [com.palletops/pallet-lein "0.6.0-beta.7"]]
   :dependencies [[ritz/ritz-nrepl-middleware "0.7.0"]
-                 [clojure-complete "0.2.2"]
                  [slamhound "1.3.3"]
                  [javert "0.2.0-SNAPSHOT"]]
   :repl-options {:nrepl-middleware


remove unused symbol

remove unused symbol

--- src/uswitch/lambada/core.clj
+++ src/uswitch/lambada/core.clj
@@ -7,8 +7,7 @@
   [name args & body]
   (assert (= (count args) 3) "lambda function must have exactly three args")
   (let [prefix (gensym)
-        handleRequestMethod (symbol (str prefix "handleRequest"))
-        invokeMethod (symbol (str prefix "invoke"))]
+        handleRequestMethod (symbol (str prefix "handleRequest"))]
     `(do
        (gen-class
         :name   ~name


add Varnish-Logs = "vignette" header to get varnish access logs

--- src/vignette/http/routes.clj
+++ src/vignette/http/routes.clj
@@ -67,7 +67,8 @@
     (let [response (handler request)]
       (reduce (fn [response [h v]]
                 (header response h v))
-              response {"X-Served-By" hostname
+              response {"Varnish-Logs" "vignette"
+                        "X-Served-By" hostname
                         "X-Cache" "ORIGIN"
                         "X-Cache-Hits" "ORIGIN"}))))


Use log statement rather than printlns

Use log statement rather than printlns

--- src/cljc/robinson/dungeons/temple.cljc
+++ src/cljc/robinson/dungeons/temple.cljc
@@ -6,7 +6,7 @@
             [robinson.lineofsight :as rlos]
             [clojure.math.combinatorics :as combo]
             [algotools.algos.graph :as graph]
-            [taoensso.timbre :as timbre]
+            [taoensso.timbre :as log]
             algotools.data.union-find
             clojure.set))

@@ -21,9 +21,9 @@
 (defn canvas
   "Create a blank grid using `nil` for cell values."
   [width height]
-  (vec (repeat height (vec (repeat width nil)))))
-
-(defn find-point-relation [[start-x start-y] [end-x end-y]]
+  (vec (repeat height (vec (repeat width {:type :empty})))))
+
+(defn find-point-relation [width height [start-x start-y] [end-x end-y]]
   "  top
     \\    /
      \\  /
@@ -32,8 +32,8 @@
      /  \\
     /    \\
     bottom"
-  (let [left-bottom  (> (- end-y start-y) (- end-x start-x))
-        bottom-right (> (- end-y start-y) (* -1 (- end-x start-x)))]
+  (let [left-bottom  (> (- end-y start-y) (* (/ height width) (- end-x start-x)))
+        bottom-right (> (- end-y start-y) (* -1 (/ height width) (- end-x start-x)))]
     (cond
       (and left-bottom bottom-right)
         :bottom
@@ -48,7 +48,7 @@
 (defn find-door
   "Takes a room and returns an [x y] of a door on the edge of the room."
   [[x-min y-min x-max y-max] start end]
-  (let [side         (find-point-relation start end)]
+  (let [side         (find-point-relation (- x-max x-min) (- y-max y-min) start end)]
     ;(println "find-door" start end side)
     (rand-nth (case side
                 :left
@@ -258,17 +258,17 @@
                                     (< (+ (* x1 1000) y1) (+ (* x2 1000) y2))
                                     ;; don't connect any rooms that are already connected
                                     (not-any? (fn [room-center-pair]
-                                                (println "room-center-pair" room-center-pair)
+                                                (log/debug "room-center-pair" room-center-pair)
                                                 (or (= room-center-pair
                                                        [room-center-1 room-center-2])
                                                     (= room-center-pair
                                                        [room-center-2 room-center-1])))
                                               g)))]
                    [room-center-1 room-center-2]))]
-    #_(println "all extra edges" (reduce (fn [edges [[x1 y1] [x2 y2]]]
-                                         (conj edges [[x1 y1] [x2 y2] (rc/chebyshev-distance (rc/xy->pos x1 y1) (rc/xy->pos x2 y2))]))
-                                       []
-                                       edges))
+    (log/debug "all extra edges" (reduce (fn [edges [[x1 y1] [x2 y2]]]
+                                           (conj edges [[x1 y1] [x2 y2] (rc/chebyshev-distance (rc/xy->pos x1 y1) (rc/xy->pos x2 y2))]))
+                                         []
+                                         edges))
     (take 5 edges)))

 (defn find-junction-rooms [edges]
@@ -281,7 +281,7 @@
                        edges)
        junctions (keys (into {} (filter (fn [[_ connections]] (> connections 2))
                                         counts)))]
-    #_(println "junctions" junctions)
+    (log/debug "junctions" junctions)
     (set (take 2 junctions))))

 (defn vertical-or-horizontally-aligned?
@@ -293,7 +293,7 @@
         *
         ******x"
   [[x1 y1] [x2 y2]]
-  #_(println "horizontal-s-segment")
+  (log/debug "horizontal-s-segment")
   (let [mid-x (int (/ (+ x1 x2) 2))]
     (concat (map #(vector % y1)    (range* x1 mid-x))
             (map #(vector mid-x %) (range* y1 y2))
@@ -308,7 +308,7 @@
           *
           x"
   [[x1 y1] [x2 y2]]
-  #_(println "vertical-s-segment")
+  (log/debug "vertical-s-segment")
   (let [mid-y (int (/ (+ y1 y2) 2))]
     (concat (map #(vector x1 %)    (range* y1 mid-y))
             (map #(vector % mid-y) (range* x1 x2))
@@ -320,7 +320,7 @@
      *
      *****x"
   [[x1 y1] [x2 y2]]
-  #_(println "vertical-corner-segment")
+  (log/debug "vertical-corner-segment")
   (concat (map #(vector x1 %) (range* y1 y2))
           (map #(vector % y2) (range* x1 x2))))

@@ -330,7 +330,7 @@
           *
           x"
   [[x1 y1] [x2 y2]]
-  #_(println "horizontal-corner-segment")
+  (log/debug "horizontal-corner-segment")
   (concat (map #(vector x1 %) (range* y1 y2))
           (map #(vector % y2) (range* x1 x2))))

@@ -353,7 +353,7 @@
   [from from-type to to-type]
   {:pre [(contains? #{:vertical :horizontal} from-type)
          (contains? #{:vertical :horizontal} to-type)]}
-  #_(println "multi-part-segment" from-type to-type)
+  (log/debug "multi-part-segment" from-type to-type)
   (cond
     (= from-type to-type :horizontal)
       (vertical-s-segment from to)
@@ -375,12 +375,12 @@
         door-xy-2         (if (contains? junction-room-centers end)
                             end
                             (find-door end-room-bounds end start))]
-    ;(println "start" start)
-    ;(println "start-room-bounds" start-room-bounds)
-    ;(println "end" end)
-    ;(println "end-room-bounds"end-room-bounds)
-    ;(println "door-1" door-xy-1)
-    ;(println "door-2" door-xy-2)
+    (log/debug "start" start)
+    (log/debug "start-room-bounds" start-room-bounds)
+    (log/debug "end" end)
+    (log/debug "end-room-bounds"end-room-bounds)
+    (log/debug "door-1" door-xy-1)
+    (log/debug "door-2" door-xy-2)
     (cond
       (vertical-or-horizontally-aligned? door-xy-1 door-xy-2)
         (rlos/line-segment door-xy-1 door-xy-2)
@@ -401,7 +401,7 @@
   "When merging cells, given their types, determine
    the type of the resulting cell."
   [cell1 cell2]
-  ;(println "merging cells" cell1 "," cell2)
+  (log/debug "merging cells" cell1 "," cell2)
   (let [cell1-type (get cell1 :type)
         cell2-type (get cell2 :type)]
     (cond
@@ -418,9 +418,9 @@
         (rand-nth [:close-door :open-door :corridor :moss-corridor :white-corridor])
       (every? #{:corridor :moss-corridor :white-corridor} [cell1-type cell2-type])
         cell1-type
-      (= cell1-type :nil)
+      (= cell1-type :empty)
         cell2-type
-      (= cell2-type :nil)
+      (= cell2-type :empty)
         cell1-type
       (= cell1-type cell2-type)
         cell1-type
@@ -448,12 +448,28 @@
   [[x1 y1 x2 y2]]
   [(int (/ (+ x1 x2) 2))
    (int (/ (+ y1 y2) 2))])
+
+(defn make-npcs [cells level]
+  (let [monster-probabilities (partition 2 (level->monster-probabilities level))]
+  (log/info "monster-probabilities" monster-probabilities)
+  (reduce (fn [npcs [_ x y]]
+            (conj npcs (assoc (mg/id->monster (rr/rand-weighted-nth monster-probabilities))
+                              :pos (rc/xy->pos x y))))
+          (if (= level 3)
+            (make-boss-npcs cells (rand-nth [:eels :giant-rat :giant-lizard]))
+            [])
+          (take 10
+            (shuffle (filter (fn [[{cell-type :type} _ _]]
+                               (= cell-type :deck))
+                             (rw/with-xy cells)))))))
+

 (defn random-place
   "Create a grid of random rooms with corridors connecting them and doors
    where corridors connect to rooms."
-  [width height level]
-  (let [num-rooms 19
+  [level]
+  (let [width 80
+        height 23
         min-width 3
         min-height 3
         max-width 10
@@ -487,18 +503,18 @@
         junction-rooms (find-junction-rooms g)
         ;; merge room cells to canvas, skipping junction rooms
         cells        (reduce (fn [cells room-bound]
-                               (println "room-bound" room-bound)
+                               (log/debug "room-bound" room-bound)
                                (if (contains? junction-rooms (room-bounds-to-center room-bound))
                                  cells
                                  (let [room-cellsxy (apply room-to-cellsxy room-bound)]
-                                   (println "room-cellsxy" room-cellsxy)
+                                   (log/debug "room-cellsxy" room-cellsxy)
                                    (apply merge-with-canvas cells room-cellsxy))))
                              (canvas width height)
                              room-bounds)
         ;; reduce over g, merging corridor cells to canvas
         cells        (reduce (fn [cells [start goal]]
                                (let [points (make-corridor-points cells room-centers-to-room-bounds junction-rooms start goal)]
-                                 (println "corridor points" points)
+                                 (log/debug "corridor points" points)
                                  (apply merge-with-canvas cells (points-to-corridor points))))
                              cells
                              g)
@@ -509,12 +525,19 @@
                                                            (rc/xy->pos upstairs-x upstairs-y)
                                                            (/ (min width height) 2.0)))
                                                        (clojure.set/difference (set room-centers) junction-rooms)))
-        cells        (-> cells
-                       (assoc-in [upstairs-y upstairs-x :type] :up-stairs)
-                       (assoc-in [downstairs-y downstairs-x :type] :down-stairs))]
+        cells        (as-> cells cells
+                       ;; only add up-stairs to levels > 0
+                       ;; ie: temple merged into island should not have up-stairs.
+                       (if (pos? level)
+                         (assoc-in cells [upstairs-y upstairs-x :type] :up-stairs)
+                         cells)
+                       (update-in cells [downstairs-y downstairs-x] (fn [cell]
+                                                                      (assoc cell :type :down-stairs
+                                                                                :dest-type :temple
+                                                                                :gen-args [(inc level)]))))]
     ;(println "fcg" fcg)
-    (println "g" g)
-    (println "more-edges" more-edges)
+    (log/debug "g" g)
+    (log/debug "more-edges" more-edges)
     ;(println (vec room-bounds))
     ;(println (vec rooms))
     {:cells cells
@@ -593,7 +616,7 @@

 (defn merge-cells
   [cells]
-  (let [temple-place (random-place 80 25 0)]
+  (let [temple-place (random-place 0)]
     (mapv (fn [line temple-line y]
             (mapv (fn [cell temple-cell x]
                    (let [cell-type (get cell :type)
@@ -606,7 +629,9 @@
                                   :short-grass
                                 :white-corridor
                                   :gravel)}
-                       (or temple-cell cell))))
+                       (if (= (get temple-cell :type) :empty)
+                         cell
+                         temple-cell))))
                   line
                   temple-line
                   (range)))
@@ -618,5 +643,5 @@
   "Generate a random grid and print it out."
   [& args]
   (println "generating...")
-  (print-cells (get (random-place 80 25 0) :cells)))
-
+  (print-cells (get (random-place 0) :cells)))
+


correct typo

correct typo

--- src/cljs/clj_money/views/accounts.cljs
+++ src/cljs/clj_money/views/accounts.cljs
@@ -280,7 +280,7 @@
      "New"
      (util/space)
      [:span.caret]]
-    [:ui.dropdown-menu
+    [:ul.dropdown-menu
      [:li
       [:a {:href "#"
            :on-click #(new-transaction context :simple)}


Use set to keep track of clients

Use set to keep track of clients

--- src/adzerk/boot_reload/server.clj
+++ src/adzerk/boot_reload/server.clj
@@ -8,7 +8,7 @@
    [java.io IOException]))

 (def options (atom {:open-file nil}))
-(def clients (atom {}))
+(def clients (atom #{}))
 (def stop-fn (atom nil))

 (defn set-options [opts]
@@ -28,14 +28,14 @@
                                   ""))})))

 (defn send-visual! [messages]
-  (doseq [[channel _] @clients]
+  (doseq [channel @clients]
     (http/send! channel (pr-str (merge {:type :visual}
                                        messages)))))

 (defn send-changed!
   ([changed] (send-changed! {} changed))
   ([opts changed]
-   (doseq [[channel _] @clients]
+   (doseq [channel @clients]
      (http/send! channel
                  (pr-str {:type :reload
                           :files (map #(web-path opts %) changed)})))))
@@ -52,8 +52,8 @@
           (util/fail "There was a problem running open-file command: %s\n" cmd))))))

 (defn connect! [channel]
-  (swap! clients assoc channel {})
-  (http/on-close channel (fn [_] (swap! clients dissoc channel)))
+  (swap! clients conj channel)
+  (http/on-close channel (fn [_] (swap! clients disj channel)))
   (http/on-receive channel #(handle-message channel (read-string %))))

 (defn handler [request]


Events has timestamp now

Events has timestamp now

--- src/amindblowingworld/history.clj
+++ src/amindblowingworld/history.clj
@@ -5,4 +5,4 @@

 (defn record-event [msg pos]
   (println "Event: " msg " at: " pos)
-  (swap! events conj {:msg msg :pos pos}))+  (swap! events conj {:msg msg :pos pos :timestamp (.getTime (java.util.Date.))}))


The *jure check needs to be case-insensitive. Thanks to kencausey.

--- src/leiningen/new.clj
+++ src/leiningen/new.clj
@@ -44,7 +44,7 @@
   ([project-name]
      (leiningen.new/new project-name (name (symbol project-name))))
   ([project-name project-dir]
-     (when (re-find #"(?<!clo)jure" project-name)
+     (when (re-find #"(?i)(?<!clo)jure" project-name)
        (throw (IllegalArgumentException. "*jure names are no longer allowed.")))
      (let [project-name (symbol project-name)
            group-id (namespace project-name)


Stray println snuck in.

Stray println snuck in.

--- src/leiningen/new.clj
+++ src/leiningen/new.clj
@@ -8,7 +8,6 @@
         [clojure.contrib.str-utils :only [str-join]]))

 (defn new [project-name & [project-dir]]
-  (println project-name project-dir)
   (let [project-name (symbol project-name)
         group-id (namespace project-name)
         artifact-id (name project-name)


add fixed-header-and-drawer-component

add fixed-header-and-drawer-component

--- app/src/cljs/app/app.cljs
+++ app/src/cljs/app/app.cljs
@@ -1,6 +1,28 @@
-(ns app.app)
+(ns app.app
+  (:require [cljsjs.material]
+            [reagent.core :as reagent]))
+
+(defn fixed-header-and-drawer-component [content]
+  [:div.mdl-layout.mdl-js-layout.mdl-layout--fixed-drawer.mdl-layout--fixed-header
+   [:header.mdl-layout__header
+    [:div.mdl-layout__header-row
+     [:div.mdl-layout-spacer]]]
+   [:div.mdl-layout__drawer
+    [:span.mdl-layout-title "Resume"]
+    [:nav.mdl-navigation
+     [:a.mdl-navigation__link {:href "#"} "About"]]]
+   [:main.mdl-layout__content
+    [:div.page-content
+     content]]])
+
+(defn some-component []
+  [:div
+   [fixed-header-and-drawer-component
+    [:h3 "This is your app"]]])
+
+
+

 (defn init []
-  (let [c (.. js/document (createElement "DIV"))]
-    (aset c "innerHTML" "
i'm dynamically created
")
-    (.. js/document (getElementById "container") (appendChild c))))
+  (reagent/render-component [some-component]
+                            (.getElementById js/document "container")))


environment variables aren't numbers, but strings

--- src/mimic/handler.clj
+++ src/mimic/handler.clj
@@ -25,4 +25,6 @@
       (wrap-defaults site-defaults)))

 (defn -main []
-  (run-jetty app {:port (or (env :port) 3000)}))
+  (run-jetty app {:port
+                  (or (-> :port env read-string
+                          3000))}))


remove /nimbus prefix from storage path (nimbus-storage-stormdist-root)

--- src/clj/backtype/storm/config.clj
+++ src/clj/backtype/storm/config.clj
@@ -82,7 +82,7 @@

 (defn nimbus-storage-stormdist-root
   ([]
-    (str "/nimbus/stormdist"))
+    (str "/stormdist"))
   ([storm-id]
     (str (nimbus-storage-stormdist-root) "/" storm-id)))


Remove no-longer-used transient-all-select|transform

--- src/clj/com/rpl/specter/impl.cljx
+++ src/clj/com/rpl/specter/impl.cljx
@@ -778,26 +778,6 @@
     (let [res (next-fn [])]
       (reduce conj! structure res))))

-#+clj
-(defn transient-all-select
-  [structure next-fn]
-  (into [] (r/mapcat #(next-fn (nth structure %))
-                     (range (count structure)))))
-
-#+cljs
-(defn transient-all-select
-  [structure next-fn]
-  (into []
-        (r/mapcat #(next-fn (nth structure %)))
-        (range (count structure))))
-
-(defn transient-all-transform!
-  [structure next-fn]
-  (reduce (fn [structure i]
-            (assoc! structure i (next-fn (nth structure i))))
-          structure
-          (range (count structure))))
-
 (defn extract-basic-filter-fn [path]
   (cond (fn? path)
         path


some namespace stuff

some namespace stuff

--- src/clj/introclojure/exercice.clj
+++ src/clj/introclojure/exercice.clj
@@ -136,6 +136,7 @@
            (binding [*ns* (create-ns (symbol "exercices"))]
              (use 'clojure.core)
              (use 'workshop.index)
+             (use 'workshop.do-things)
              (eval ~f))}
         (catch Exception e# {:err e#})))]
      (assoc r# :out (str out-w#))))
@@ -146,7 +147,11 @@

 (defn reload-exercices []
-  (load "/workshop/index"))
+  (try
+  (load "/workshop/index")
+  (load "/workshop/do-things")
+    (catch Exception e nil)))
+

 (defn eval-exercice


Add glyphicons for adding and removin quantities

--- src/cljs/decktouch/card-list.cljs
+++ src/cljs/decktouch/card-list.cljs
@@ -17,7 +17,9 @@
          :data-trigger "hover"
          :data-content (reagent/render-component-to-string [card-img image-link])
          :onClick (fn [] (reset! card-display/url image-link))}
-         (str (get card "name"))]]))
+        [:small [:span.glyphicon.glyphicon-plus-sign]]
+        [:span (str " " (get card "quantity") " x " (get card "name") "  ")]
+        [:small [:span.glyphicon.glyphicon-remove]]]]))

 (defn card-in-list-did-mount [card-id]
     (.popover (js/$ (str "#" card-id))))
@@ -43,7 +45,7 @@
     (if (not-empty filtered-cards-by-type)
       [:div
         [:p type]
-        [:ul
+        [:ul.list-unstyled
           (for [card (filter-cards-by-type cards type)]
                ^{:key (get card "imageName")} [card-in-list-component card])]])))