 (defn source-compare [sources]
   (let [sources (indexed-sources sources)]
     (fn [a b] (compare (sources a) (sources b)))))
+
+;; -----------------------------------------------------------------------------
+;; Decoding
 
 (defn seg->map [seg source-map]
   (let [[gcol source line col name] seg]

             (recur (inc gline) (next lines) (assoc relseg 0 0) result))
           result)))))

(defn info->segv [info state]
  (let [segv [(:gcol info) (:source-idx state) (:line state) (:col state)]]
    (if-let [name (:name info)]
      (let [[idx state]
            (if-let [idx (get-in state [:names->idx name])]
              [idx state]
              (let [cidx (:name-idx state)]
                [cidx (-> state
                          (assoc-in [:names->idx name] cidx)
                          (assoc :name-idx (inc cidx)))]))]
        [(conj segv idx) state])
      [segv state])))

(defn prev-info->segv [info]
  (let [state (meta info)
        segv [(:gcol info) (:source-idx state) (:line state) (:col state)]]
    (if-let [name (:name info)]
      (conj segv (get (:names->idx state) name))
      segv)))

(defn encode-cols [infos state]
  (loop [infos (seq infos) state state]
    (if infos
      (let [info (first infos)
            [segv state] (info->segv info state)
            prev-info (:prev-info state)
            gline (:gline info)
            relsegv (if prev-info
                      (let [prev-segv (prev-info->segv prev-info)]
                        (if (not= gline (:gline prev-info))
                          (into [(first segv)] (map - (rest segv) (rest prev-segv)))
                          (into [] (map - segv prev-segv))))
                      segv)]
        (recur (next infos)
          (let [lines (:lines state)
                lc    (count lines)
                lines (if (> gline (dec lc))
                        (conj (into lines (repeat (dec (- gline (dec lc))) [])) [(base64-vlq/encode relsegv)])
                        (update-in lines [gline] conj (base64-vlq/encode relsegv)))]
            (-> state
                (assoc :lines lines)
                (assoc :prev-info
                  (with-meta
                    (if (:name info)
                      info
                      (assoc info :name (:name prev-info)))
                    state))))))
      state)))

(defn encode [m opts]
  (let [step (fn [state [_ lines]]
               (update-in
                 (reduce (fn [state [line cols]]
                           (reduce (fn [state [col infos]]
                                     (encode-cols infos (assoc state :col col)))
                                   (assoc state :line line)
                                   cols))
                         state lines)
                 [:source-idx] inc))
        init-state {:source-idx 0 :lines [[]]
                    :names->idx {} :name-idx 0
                    :prev-info nil}
        {:keys [names->idx lines]} (reduce step init-state m)]
    (with-out-str
      (json/pprint 
       {"version" 3
        "file" (:file opts)
        "sources" (into [] (keys m))
        "lineCount" (:lines opts)
        "mappings" (->> lines
                        (map #(string/join "," %))
                        (string/join ";"))
        "names" (into [] (map (set/map-invert names->idx)
                              (range (count names->idx))))}))))

(defn merge-source-maps
  ([cljs-map closure-map] (merge-source-maps cljs-map closure-map 0))

            [clojure.set :as set]
            [clojure.pprint :as pp]
            [cljs.source-map.base64-vlq :as base64-vlq]))

;; -----------------------------------------------------------------------------
;; Utilities

(defn indexed-sources [sources]
  (->> sources
