 
     cm))
 
-(defn start-editor-sync!
-  []
+(defn start-editor-sync! []
   ;; sync state changes to the editor
   (add-watch state :editor-updater on-state-change)
   (force-editor-sync!))
+
+(defn start-recording!
+  [key-]
+  (let [{:keys [text cm] :as editor} (get @state key-)]
+    (swap! vcr assoc
+           :changes []
+           :init-value text
+           :recording? true
+           :last-time nil)))
+
+(defn stop-recording!
+  [key-]
+  (swap! vcr assoc-in [key- :recording?] false))
+
+(defn play-recording!
+  [key-]
+  (let [cm (get-in @state [key- :cm])
+        recording (get @vcr key-)]
+    (go
+      (swap! state assoc-in [key- :text] (:init-value recording))
+      (doseq [{:keys [change selections dt]} (:changes recording)]
+        (<! (timeout dt))
+        (cond
+          change (apply-change cm change)
+          selections (apply-selections cm selections)
+          :else nil)))))


(def frame-updates (atom {}))

(defn before-change
  "Called before any change is applied to the editor."
  [cm change]

  "Custom data/methods for a CodeMirror editor."
  (cm-key [this])
  (frame-updated? [this])
  (set-frame-updated! [this value])
  (record-change! [this thing]))

;;----------------------------------------------------------------------
;; Operations
