     (:test-cases state)))
 
 (defn idempotent-check
-  [type- message result state format-text]
-  (let [post-result (format-text state result)
+  [type- message result overrides format-text]
+  (let [post-result (format-text overrides result)
         message (str type- " idempotence over " message)]
     (is (= result post-result) message)))
 

  (:require
    #?(:clj  [clojure.test :refer [is deftest]]
       :cljs [cljs.test :refer-macros [is deftest]])
    [clojure.string :as string :refer [split-lines]]
    [parinfer.format.infer :as infer]
    [parinfer.format.prep :as prep]))

#?(:cljs (def fs (js/require "fs")))

(defn error-msg
  [line-no msg]
  (str "error at test-case line #" line-no ": " msg))

(defmulti parse-test-line
  (fn [state [line-no line]]
    (cond
      (= "```" line)          :end-block
      (re-find #"^```" line)  :start-block
      (:block-key state)      :in-block
      :else                   :default)))

(defmethod parse-test-line :end-block
  [{:keys [block-key test-case test-cases] :as state} [line-no line]]
  (if-not block-key
    (throw (error-msg line-no "opening block must have a name: 'in' or 'out'"))
    (let [test-case-done? (:out test-case)]
      (if test-case-done?


        (assoc state :block-key nil)))))

(defmethod parse-test-line :start-block
  [{:keys [block-key test-case test-cases] :as state} [file-line-no line]]
  (if block-key
    (throw (error-msg file-line-no "must close previous block before starting new one"))
    (let [block-name (second (re-find #"^```(.*)$" line))
          block-key (keyword block-name)]
      (cond

        (not (#{:in :out} block-key))
        (throw (error-msg file-line-no (str "block name " (pr-str block-name) "must be either 'in' or 'out'")))

        (and (= :in block-key) (:in test-case))
        (throw (error-msg file-line-no (str "there is already an 'in' block for this test case.")))

        (and (= :out block-key) (not (:in test-case)))
        (throw (error-msg file-line-no (str "must include an 'in' block before an 'out' block.")))

        :else
        (-> state
            (assoc :block-key block-key)
            (assoc-in [:test-case block-key] {:file-line-no file-line-no
                                              :lines []}))))))

(defmethod parse-test-line :inside-block
  [{:keys [block-key test-case test-cases] :as state} [file-line-no line]]
  (let [cursor-x (.indexOf line "|")
        cursor-line (when (and (= :in block-key)
                               (not= -1 cursor-x))
                      (dec (- file-line-no (:file-line-no (:in test-case)))))
        line (string/replace line "|" "")]
    (-> state
        (update-in [:test-case block-key :lines] conj line)
        (update-in [:test-case block-key :cursor-x] #(or % cursor-x))
        (update-in [:test-case block-key :cursor-line] #(or % cursor-line)))))

