              (= (.getValue cm) (join "\n" (.-text change))))
     (.cancel change)))
 
+(defn parse-pos
+  [pos]
+  {:line (.-line pos)
+   :ch (.-ch pos)})
+
+(defn parse-change
+  [change]
+  (js/console.log "change object:" change)
+  {:from (parse-pos (.-from change))
+   :to (parse-pos (.-to change))
+   :text (seq (.-text change))
+   :origin (.-origin change)})
+
+(defn apply-change
+  [cm {:keys [text from to origin]}]
+  (.replaceRange cm
+     (js->clj text)
+     (js->clj from)
+     (js->clj to)
+     origin))
+
+(defn parse-selections
+  [selections]
+  selections)
+
+(defn apply-selections
+  [cm selections]
+  )
+
 (defn on-change
   "Called after any change is applied to the editor."
   [cm change]
   (when (not= "setValue" (.-origin change))
+    (record-change! cm {:change (parse-change change)})
     (fix-text! cm)
     (update-cursor! cm change)
     (set-frame-updated! cm true)))


    cm))

(defn start-editor-sync!
  []
  ;; sync state changes to the editor
  (add-watch state :editor-updater on-state-change)
  (force-editor-sync!))

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

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