   (:require [cljs.js :as cljs]
             [cljs.tagged-literals :as tags]
             [cljs.tools.reader :as r]
+            [cljs.tools.reader.reader-types :as rt]
             [cljs.analyzer :as ana]
             [cljs.env :as env]
             [cljs.repl :as repl]
             [cljs.pprint :refer [pprint]]
+            [clojure.string :as s]
             [replumb.common :as common]
             [replumb.doc-maps :as docs]
             [replumb.load :as load]

      require-macros (process-require opts cb data :require-macros (rest expression-form))
      import (process-require opts cb data :import (rest expression-form))
      doc (process-doc opts cb data env argument)
      source (call-back! opts cb data (common/error-keyword-not-supported "source" ex-info-data)) ;; (println (fetch-source (get-var env argument)))
      pst (process-pst opts cb data argument)
      load-file (call-back! opts cb data (common/error-keyword-not-supported "load-file" ex-info-data))))) ;; (process-load-file argument opts)


                                (common/wrap-error error)
                                (common/wrap-success nil)))))))))))))

(defn fetch-source
  [{:keys [verbose read-file-fn!]} var paths-to-try cb]
  (load/read-files-and-callback! verbose
                                 paths-to-try
                                 read-file-fn!
                                 (fn [result]
                                   (let [source (:source result)
                                         rdr (rt/source-logging-push-back-reader source)]
                                     (dotimes [_ (dec (:line var))] (rt/read-line rdr))
                                     (-> (r/read {:read-cond :allow :features #{:cljs}} rdr)
                                         meta 
                                         :source
                                         common/wrap-success
                                         cb)))))

(defn filenames-to-try-from-symbol
  [sym src-paths]
  (let [without-extension (s/replace (s/replace (name sym) #"\." "/") #"-" "_")
        files (map #(str without-extension %) [".clj" ".cljc" ".cljs"])]
    (for [file files src-path src-paths]
      (str (common/normalize-path src-path) file))))

(defn process-source
  [opts cb data env sym]
  (let [var (get-var opts env sym)
        call-back (partial call-back! (merge opts {:no-pr-str-on-value true}) cb data)]
    (if-let [filepath (or (:file var) (:file (:meta var)))]
      (let [src-paths (:src-paths opts)
            ; see discussion here: https://github.com/ScalaConsultants/replumb/issues/17#issuecomment-163832028
            paths-to-try (if (symbol? filepath)
                           (filenames-to-try-from-symbol filepath src-paths)
                           (map #(str (common/normalize-path %) filepath) src-paths))]
        (fetch-source opts var paths-to-try call-back))
      (call-back nil))))

(defn process-repl-special
  [opts cb data expression-form]
  (let [env (assoc (ana/empty-env) :context :expr
