Skip to content

Instantly share code, notes, and snippets.

@shaunlebron
Created December 15, 2018 04:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shaunlebron/791da3a0f8f1ce66e033ab74c6743070 to your computer and use it in GitHub Desktop.
Save shaunlebron/791da3a0f8f1ce66e033ab74c6743070 to your computer and use it in GitHub Desktop.
parindent on figwheel-main
diff --git a/dev/user.clj b/dev/user.clj
index 63a1ebe..7a0b0b4 100644
--- a/dev/user.clj
+++ b/dev/user.clj
@@ -1,23 +1,23 @@
(ns user
(:require [figwheel.server.ring]
- [figwheel.main.schema.config]
- [figwheel.main.api :as api]
- [clojure.string :as string]))
+ [figwheel.main.schema.config]
+ [figwheel.main.api :as api]
+ [clojure.string :as string]))
(defn strip-leading-whitspace [s]
(string/join "\n"
- (map
- #(string/replace % #"^\s\s(.*)" "$1")
- (string/split-lines s))))
+ (map
+ #(string/replace % #"^\s\s(.*)" "$1")
+ (string/split-lines s))))
(def doc-string #(-> % resolve meta :doc strip-leading-whitspace))
(def args #(-> % resolve meta :arglists))
(defn sym->markdown-doc [sym]
(str
- "## `" sym "`\n\n"
- "Args: `"(pr-str (args sym)) "`\n\n"
- (doc-string sym) "\n\n"))
+ "## `" sym "`\n\n"
+ "Args: `"(pr-str (args sym)) "`\n\n"
+ (doc-string sym) "\n\n"))
(defn api-docs []
(let [syms ['figwheel.main.api/start
diff --git a/docs-cljs/figwheel_main_docs/main.cljs b/docs-cljs/figwheel_main_docs/main.cljs
index 31ef847..fbcec5a 100644
--- a/docs-cljs/figwheel_main_docs/main.cljs
+++ b/docs-cljs/figwheel_main_docs/main.cljs
@@ -1,9 +1,9 @@
(ns figwheel-main-docs.main
(:require [goog.dom :as dom]
- [goog.dom.classlist :as cl]
- [goog.string :as gstring]
- [goog.fx.css3 :as fxcss3]
- [goog.style :as style]))
+ [goog.dom.classlist :as cl]
+ [goog.string :as gstring]
+ [goog.fx.css3 :as fxcss3]
+ [goog.style :as style]))
(defn itemable->coll [itemable]
(map #(.item itemable %) (range (.-length itemable))))
@@ -105,7 +105,7 @@
#_(insert-options-toc)
#_(log (create-toc (->> (get-main-headers)
- (map extract-heading)
+ (map extract-heading)
- (map create-toc-link))))
+ (map create-toc-link))))
diff --git a/src/figwheel/main.cljc b/src/figwheel/main.cljc
index 36e0426..2a854d4 100644
--- a/src/figwheel/main.cljc
+++ b/src/figwheel/main.cljc
@@ -1,32 +1,32 @@
(ns figwheel.main
#?(:clj
- (:require
- [cljs.analyzer :as ana]
- [cljs.analyzer.api :as ana-api]
- [cljs.build.api :as bapi]
- [cljs.cli :as cli]
- [cljs.env]
- [cljs.main :as cm]
- [cljs.repl]
- [cljs.repl.figwheel]
- [cljs.util]
- [clojure.java.io :as io]
- [clojure.pprint :refer [pprint]]
- [clojure.string :as string]
- [clojure.edn :as edn]
- [clojure.tools.reader.edn :as redn]
- [clojure.tools.reader.reader-types :as rtypes]
- [figwheel.core :as fw-core]
- [figwheel.main.ansi-party :as ansip]
- [figwheel.main.logging :as log]
- [figwheel.main.util :as fw-util]
- [figwheel.main.watching :as fww]
- [figwheel.main.helper :as helper]
- [figwheel.main.npm :as npm]
- [figwheel.main.async-result :as async-result]
- [figwheel.main.testing :as testing]
- [figwheel.repl :as fw-repl]
- [figwheel.tools.exceptions :as fig-ex]))
+ (:require
+ [cljs.analyzer :as ana]
+ [cljs.analyzer.api :as ana-api]
+ [cljs.build.api :as bapi]
+ [cljs.cli :as cli]
+ [cljs.env]
+ [cljs.main :as cm]
+ [cljs.repl]
+ [cljs.repl.figwheel]
+ [cljs.util]
+ [clojure.java.io :as io]
+ [clojure.pprint :refer [pprint]]
+ [clojure.string :as string]
+ [clojure.edn :as edn]
+ [clojure.tools.reader.edn :as redn]
+ [clojure.tools.reader.reader-types :as rtypes]
+ [figwheel.core :as fw-core]
+ [figwheel.main.ansi-party :as ansip]
+ [figwheel.main.logging :as log]
+ [figwheel.main.util :as fw-util]
+ [figwheel.main.watching :as fww]
+ [figwheel.main.helper :as helper]
+ [figwheel.main.npm :as npm]
+ [figwheel.main.async-result :as async-result]
+ [figwheel.main.testing :as testing]
+ [figwheel.repl :as fw-repl]
+ [figwheel.tools.exceptions :as fig-ex]))
#?(:clj
(:import
[java.io StringReader]
@@ -40,199 +40,199 @@
#?(:clj
(do
-(def ^:dynamic *base-config*)
-(def ^:dynamic *config*)
-
-(def default-target-dir "target")
-
-(defonce process-unique (subs (str (java.util.UUID/randomUUID)) 0 6))
-
-(defn- time-elapsed [started-at]
- (let [elapsed-us (- (System/currentTimeMillis) started-at)]
- (with-precision 2
- (str (/ (double elapsed-us) 1000) " seconds"))))
-
-(defn- wrap-with-build-logging [build-fn]
- (fn [id? & args]
- (let [started-at (System/currentTimeMillis)
- {:keys [output-to output-dir]} (second args)]
- ;; print start message
- (log/info (str "Compiling build"
- (when id? (str " " id?))
- " to \""
- (or output-to output-dir)
- "\""))
- (try
- (let [warnings (volatile! [])
- out *out*
- warning-fn (fn [warning-type env extra]
- (when (get cljs.analyzer/*cljs-warnings* warning-type)
- (let [warn {:warning-type warning-type
- :env env
- :extra extra
- :path ana/*cljs-file*}]
- (binding [*out* out]
- (if (<= (count @warnings) 2)
- (log/cljs-syntax-warning warn)
- (binding [log/*syntax-error-style* :concise]
- (log/cljs-syntax-warning warn))))
- (vswap! warnings conj warn))))]
- (binding [cljs.analyzer/*cljs-warning-handlers*
- (conj (remove #{cljs.analyzer/default-warning-handler}
- cljs.analyzer/*cljs-warning-handlers*)
- warning-fn)]
- (apply build-fn args)))
- (log/succeed (str "Successfully compiled build"
- (when id? (str " " id?))
- " to \""
- (or output-to output-dir)
- "\" in " (time-elapsed started-at) "."))
- (catch Throwable e
- (log/failure (str
- "Failed to compile build" (when id? (str " " id?))
- " in " (time-elapsed started-at) "."))
- (log/syntax-exception e)
- (throw e))))))
-
-(declare resolve-fn-var)
-
-(defn run-hooks [hooks & args]
- (when (not-empty hooks)
- (doseq [h hooks]
- (apply h args))))
-
-(defn- wrap-with-build-hooks [build-fn]
- (fn [& args]
- (run-hooks (::pre-build-hooks *config*) *config*)
- (apply build-fn args)
- (run-hooks (::post-build-hooks *config*) *config*)))
-
-(def build-cljs
- (-> bapi/build wrap-with-build-logging wrap-with-build-hooks))
-
-(def fig-core-build
- (-> figwheel.core/build wrap-with-build-logging wrap-with-build-hooks))
-
-;; TODO the word config is soo abused in this namespace that it's hard to
-;; know what and argument is supposed to be
-(defn config->reload-config [config]
- (select-keys config [:reload-clj-files :wait-time-ms :hawk-options]))
-
-(defn watch-build [id paths inputs opts cenv & [reload-config]]
- (when-let [inputs (not-empty (if (coll? inputs) inputs [inputs]))]
- (let [build-inputs (if (coll? inputs) (apply bapi/inputs inputs) inputs)
- ;; the build-fn needs to be passed in before here?
- build-fn (if (some #{'figwheel.core} (:preloads opts))
- #(fig-core-build id build-inputs opts cenv %)
- (fn [files] (build-cljs id build-inputs opts cenv)))]
- (log/info "Watching paths:" (pr-str paths) "to compile build -" id)
- (log/debug "Build Inputs:" (pr-str inputs))
- (binding [fww/*hawk-options* (:hawk-options reload-config nil)]
- (fww/add-watch!
- [::autobuild id]
- (merge
- {::watch-info (merge
- (:extra-info reload-config)
- {:id id
- :paths paths
- :inputs inputs
- :options opts
- :compiler-env cenv
- :reload-config reload-config})}
- {:paths paths
- :filter (fww/suffix-filter #{"cljc" "cljs" "js" "clj"})
- :handler (fww/throttle
- (:wait-time-ms reload-config 50)
- (bound-fn [evts]
- (binding [cljs.env/*compiler* cenv]
- (let [files (mapv (comp #(.getCanonicalPath %) :file) evts)]
- (try
- (when-let [clj-files
- (->> evts
- (filter
- (partial
- (fww/suffix-filter
- (set
- (cond
- (coll? (:reload-clj-files reload-config))
- (mapv name (:reload-clj-files reload-config))
- (false? (:reload-clj-files reload-config)) []
- :else ["clj" "cljc"]))) nil))
- (mapv (comp #(.getCanonicalPath %) :file))
- not-empty)]
- (log/debug "Reloading clj files: " (pr-str (map str clj-files)))
- (try
- (figwheel.core/reload-clj-files clj-files)
- (catch Throwable t
- (if (-> t ex-data :figwheel.core/internal)
- (log/error (.getMessage t) t)
- (do
- (log/syntax-exception t)
- (figwheel.core/notify-on-exception cenv t {})))
- ;; skip cljs reloading in this case
- (throw t))))
- (log/debug "Detected changed cljs files: " (pr-str (map str files)))
- (build-fn files)
- (catch Throwable t
- (log/error t)
- (log/debug (with-out-str (clojure.pprint/pprint (Throwable->map t))))
- false))))))}))))))
-
-
-(declare read-edn-file)
-
-(defn get-edn-file-key
- ([edn-file key] (get-edn-file-key edn-file key nil))
- ([edn-file key default]
- (try (get (read-string (slurp edn-file)) key default)
- (catch Throwable t default))))
-
-(def validate-config!*
- (when (try
- (require 'clojure.spec.alpha)
- (require 'expound.alpha)
- (require 'expound.ansi)
- (require 'figwheel.main.schema.config)
- (require 'figwheel.main.schema.cljs-options)
- (require 'figwheel.main.schema.cli)
- true
- (catch Throwable t false))
- (resolve 'figwheel.main.schema.core/validate-config!)))
-
-(defn validate-config! [spec edn fail-msg & [succ-msg]]
- (when (and validate-config!*
- (not
- (false?
- (:validate-config
- edn
- (get-edn-file-key "figwheel-main.edn" :validate-config)))))
- (expound.ansi/with-color-when (:ansi-color-output edn true)
- (validate-config!* spec edn fail-msg))
- (when succ-msg
- (log/succeed succ-msg))))
-
-(def validate-cli!*
- (when validate-config!*
- (resolve 'figwheel.main.schema.cli/validate-cli!)))
-
-(defn validate-cli! [cli-args & [succ-msg]]
- (when (and validate-cli!*
- (get-edn-file-key "figwheel-main.edn" :validate-cli true))
- (expound.ansi/with-color-when
- (get-edn-file-key "figwheel-main.edn" :ansi-color-output true)
- (validate-cli!* cli-args "Error in command line args"))
- (when succ-msg
- (log/succeed succ-msg))))
-
-;; ----------------------------------------------------------------------------
-;; Additional cli options
-;; ----------------------------------------------------------------------------
-
-;; Help
-
-
-(def help-template
- "Usage: clojure -m figwheel.main [init-opt*] [main-opt] [arg*]
+ (def ^:dynamic *base-config*)
+ (def ^:dynamic *config*)
+
+ (def default-target-dir "target")
+
+ (defonce process-unique (subs (str (java.util.UUID/randomUUID)) 0 6))
+
+ (defn- time-elapsed [started-at]
+ (let [elapsed-us (- (System/currentTimeMillis) started-at)]
+ (with-precision 2
+ (str (/ (double elapsed-us) 1000) " seconds"))))
+
+ (defn- wrap-with-build-logging [build-fn]
+ (fn [id? & args]
+ (let [started-at (System/currentTimeMillis)
+ {:keys [output-to output-dir]} (second args)]
+ ;; print start message
+ (log/info (str "Compiling build"
+ (when id? (str " " id?))
+ " to \""
+ (or output-to output-dir)
+ "\""))
+ (try
+ (let [warnings (volatile! [])
+ out *out*
+ warning-fn (fn [warning-type env extra]
+ (when (get cljs.analyzer/*cljs-warnings* warning-type)
+ (let [warn {:warning-type warning-type
+ :env env
+ :extra extra
+ :path ana/*cljs-file*}]
+ (binding [*out* out]
+ (if (<= (count @warnings) 2)
+ (log/cljs-syntax-warning warn)
+ (binding [log/*syntax-error-style* :concise]
+ (log/cljs-syntax-warning warn))))
+ (vswap! warnings conj warn))))]
+ (binding [cljs.analyzer/*cljs-warning-handlers*
+ (conj (remove #{cljs.analyzer/default-warning-handler}
+ cljs.analyzer/*cljs-warning-handlers*)
+ warning-fn)]
+ (apply build-fn args)))
+ (log/succeed (str "Successfully compiled build"
+ (when id? (str " " id?))
+ " to \""
+ (or output-to output-dir)
+ "\" in " (time-elapsed started-at) "."))
+ (catch Throwable e
+ (log/failure (str
+ "Failed to compile build" (when id? (str " " id?))
+ " in " (time-elapsed started-at) "."))
+ (log/syntax-exception e)
+ (throw e))))))
+
+ (declare resolve-fn-var)
+
+ (defn run-hooks [hooks & args]
+ (when (not-empty hooks)
+ (doseq [h hooks]
+ (apply h args))))
+
+ (defn- wrap-with-build-hooks [build-fn]
+ (fn [& args]
+ (run-hooks (::pre-build-hooks *config*) *config*)
+ (apply build-fn args)
+ (run-hooks (::post-build-hooks *config*) *config*)))
+
+ (def build-cljs
+ (-> bapi/build wrap-with-build-logging wrap-with-build-hooks))
+
+ (def fig-core-build
+ (-> figwheel.core/build wrap-with-build-logging wrap-with-build-hooks))
+
+ ;; TODO the word config is soo abused in this namespace that it's hard to
+ ;; know what and argument is supposed to be
+ (defn config->reload-config [config]
+ (select-keys config [:reload-clj-files :wait-time-ms :hawk-options]))
+
+ (defn watch-build [id paths inputs opts cenv & [reload-config]]
+ (when-let [inputs (not-empty (if (coll? inputs) inputs [inputs]))]
+ (let [build-inputs (if (coll? inputs) (apply bapi/inputs inputs) inputs)
+ ;; the build-fn needs to be passed in before here?
+ build-fn (if (some #{'figwheel.core} (:preloads opts))
+ #(fig-core-build id build-inputs opts cenv %)
+ (fn [files] (build-cljs id build-inputs opts cenv)))]
+ (log/info "Watching paths:" (pr-str paths) "to compile build -" id)
+ (log/debug "Build Inputs:" (pr-str inputs))
+ (binding [fww/*hawk-options* (:hawk-options reload-config nil)]
+ (fww/add-watch!
+ [::autobuild id]
+ (merge
+ {::watch-info (merge
+ (:extra-info reload-config)
+ {:id id
+ :paths paths
+ :inputs inputs
+ :options opts
+ :compiler-env cenv
+ :reload-config reload-config})}
+ {:paths paths
+ :filter (fww/suffix-filter #{"cljc" "cljs" "js" "clj"})
+ :handler (fww/throttle
+ (:wait-time-ms reload-config 50)
+ (bound-fn [evts]
+ (binding [cljs.env/*compiler* cenv]
+ (let [files (mapv (comp #(.getCanonicalPath %) :file) evts)]
+ (try
+ (when-let [clj-files
+ (->> evts
+ (filter
+ (partial
+ (fww/suffix-filter
+ (set
+ (cond
+ (coll? (:reload-clj-files reload-config))
+ (mapv name (:reload-clj-files reload-config))
+ (false? (:reload-clj-files reload-config)) []
+ :else ["clj" "cljc"]))) nil))
+ (mapv (comp #(.getCanonicalPath %) :file))
+ not-empty)]
+ (log/debug "Reloading clj files: " (pr-str (map str clj-files)))
+ (try
+ (figwheel.core/reload-clj-files clj-files)
+ (catch Throwable t
+ (if (-> t ex-data :figwheel.core/internal)
+ (log/error (.getMessage t) t)
+ (do
+ (log/syntax-exception t)
+ (figwheel.core/notify-on-exception cenv t {})))
+ ;; skip cljs reloading in this case
+ (throw t))))
+ (log/debug "Detected changed cljs files: " (pr-str (map str files)))
+ (build-fn files)
+ (catch Throwable t
+ (log/error t)
+ (log/debug (with-out-str (clojure.pprint/pprint (Throwable->map t))))
+ false))))))}))))))
+
+
+ (declare read-edn-file)
+
+ (defn get-edn-file-key
+ ([edn-file key] (get-edn-file-key edn-file key nil))
+ ([edn-file key default]
+ (try (get (read-string (slurp edn-file)) key default)
+ (catch Throwable t default))))
+
+ (def validate-config!*
+ (when (try
+ (require 'clojure.spec.alpha)
+ (require 'expound.alpha)
+ (require 'expound.ansi)
+ (require 'figwheel.main.schema.config)
+ (require 'figwheel.main.schema.cljs-options)
+ (require 'figwheel.main.schema.cli)
+ true
+ (catch Throwable t false))
+ (resolve 'figwheel.main.schema.core/validate-config!)))
+
+ (defn validate-config! [spec edn fail-msg & [succ-msg]]
+ (when (and validate-config!*
+ (not
+ (false?
+ (:validate-config
+ edn
+ (get-edn-file-key "figwheel-main.edn" :validate-config)))))
+ (expound.ansi/with-color-when (:ansi-color-output edn true)
+ (validate-config!* spec edn fail-msg))
+ (when succ-msg
+ (log/succeed succ-msg))))
+
+ (def validate-cli!*
+ (when validate-config!*
+ (resolve 'figwheel.main.schema.cli/validate-cli!)))
+
+ (defn validate-cli! [cli-args & [succ-msg]]
+ (when (and validate-cli!*
+ (get-edn-file-key "figwheel-main.edn" :validate-cli true))
+ (expound.ansi/with-color-when
+ (get-edn-file-key "figwheel-main.edn" :ansi-color-output true)
+ (validate-cli!* cli-args "Error in command line args"))
+ (when succ-msg
+ (log/succeed succ-msg))))
+
+ ;; ----------------------------------------------------------------------------
+ ;; Additional cli options
+ ;; ----------------------------------------------------------------------------
+
+ ;; Help
+
+
+ (def help-template
+ "Usage: clojure -m figwheel.main [init-opt*] [main-opt] [arg*]
Common usage:
clj -m figwheel.main -b dev -r
@@ -296,1211 +296,1211 @@ options afterwards.
Paths may be absolute or relative in the filesystem or relative to
classpath. Classpath-relative paths have prefix of @ or @/")
-(defn adjust-option-docs [commands]
- (-> commands
- (update-in [:groups :cljs.cli/main&compile :pseudos]
- dissoc ["-re" "--repl-env"])
- (assoc-in [:init ["-d" "--output-dir"] :doc]
- "Set the output directory to use")
- (update-in [:init ["-w" "--watch"] :doc] str
- ". This option can be supplied multiple times.")))
-
-(defn help-str [repl-env]
- (format
- help-template
- (#'cljs.cli/options-str
- (adjust-option-docs
- (#'cljs.cli/merged-commands repl-env)))))
-
-(defn help-opt
- [repl-env _ _]
- (println (help-str repl-env)))
-
-;; safer option reading from files which prints out syntax errors
-
-(defn read-edn-file [f]
- (try (redn/read
- (rtypes/source-logging-push-back-reader (io/reader f) 1 f))
- (catch Throwable t
- (log/syntax-exception t)
- (throw
- (ex-info (str "Couldn't read the file:" f)
- {::error true} t)))))
-
-(defn read-edn-string [s & [fail-msg]]
- (try
- (redn/read
- (rtypes/source-logging-push-back-reader (io/reader (.getBytes s)) 1))
- (catch Throwable t
- (let [except-data (fig-ex/add-excerpt (fig-ex/parse-exception t) s)]
- (log/info (ansip/format-str (log/format-ex except-data)))
- (throw (ex-info (str (or fail-msg "Failed to read EDN string: ")
- (.getMessage t))
- {::error true}
- t))))))
-
-(defn read-edn-opts [str]
- (letfn [(read-rsrc [rsrc-str orig-str]
- (if-let [rsrc (io/resource rsrc-str)]
- (read-edn-string (slurp rsrc))
- (cljs.cli/missing-resource orig-str)))]
- (cond
- (string/starts-with? str "@/") (read-rsrc (subs str 2) str)
- (string/starts-with? str "@") (read-rsrc (subs str 1) str)
- :else
- (let [f (io/file str)]
- (if (.isFile f)
- (read-edn-file f)
- (cljs.cli/missing-file str))))))
-
-(defn merge-meta [m m1] (with-meta (merge m m1) (merge (meta m) (meta m1))))
-
-(defn load-edn-opts [str]
- (reduce merge-meta {} (map read-edn-opts (cljs.util/split-paths str))))
-
-(defn fallback-id [edn]
- (let [m (meta edn)]
- (cond
- (and (:id m) (not (string/blank? (str (:id m)))))
- (:id m)
- ;;(:main edn) (munge (str (:main edn)))
- :else
- (str "build-"
- (.getValue (doto (java.util.zip.CRC32.)
- (.update (.getBytes (pr-str (into (sorted-map) edn))))))))))
-
-(defn compile-opts-opt
- [cfg copts]
- (let [copts (string/trim copts)
- edn (if (or (string/starts-with? copts "{")
- (string/starts-with? copts "^"))
- (read-edn-string copts "Error reading EDN from command line flag: -co ")
- (load-edn-opts copts))
- config (meta edn)
- id
- (and edn
- (if (or (string/starts-with? copts "{")
- (string/starts-with? copts "^"))
- (and (map? edn) (fallback-id edn))
- (->>
- (cljs.util/split-paths copts)
- (filter (complement string/blank?))
- (filter #(not (.startsWith % "@")))
- (map io/file)
- (map (comp first #(string/split % #"\.") #(.getName %)))
- (string/join ""))))]
- (log/debug "Validating options passed to --compile-opts")
- (validate-config!
- :figwheel.main.schema.cljs-options/cljs-options
- edn
- (str "Configuration error in options passed to --compile-opts"))
- (cond-> cfg
- edn (update :options merge edn)
- id (update-in [::build :id] #(if-not % id %))
- config (update-in [::build :config] merge config))))
-
-(defn repl-env-opts-opt
- [cfg ropts]
- (let [ropts (string/trim ropts)
- edn (if (string/starts-with? ropts "{")
- (read-edn-string ropts "Error reading EDN from command line flag: --repl-opts ")
- (load-edn-opts ropts))]
- (update cfg :repl-env-options merge edn)))
-
-(defn figwheel-opts-opt
- [cfg ropts]
- (let [ropts (string/trim ropts)
- edn (if (string/starts-with? ropts "{")
- (read-edn-string ropts "Error reading EDN from command line flag: -fw-opts ")
- (load-edn-opts ropts))]
- (validate-config!
- :figwheel.main.schema.config/edn
- edn "Error validating figwheel options EDN provided to -fwo CLI flag")
- (update cfg ::config merge edn)))
-
-(defn print-config-opt [cfg opt]
- (assoc-in cfg [::config :pprint-config] (not (#{"false"} opt))))
-
-(defn- watch-opt
- [cfg path]
- (when-not (.exists (io/file path))
- (if (or (string/starts-with? path "-")
- (string/blank? path))
- (throw
- (ex-info
- (str "Missing watch path")
- {:cljs.main/error :invalid-arg}))
- (throw
- (ex-info
- (str "Watch path \"" path "\" does not exist")
- {:cljs.main/error :invalid-arg}))))
- (update-in cfg [::extra-config :watch-dirs] (fnil conj []) path))
-
-(defn figwheel-opt [cfg bl]
- (assoc-in cfg [::config :figwheel-core] (not= bl "false")))
-
-(defn get-build [bn]
- (let [fname (if (.contains bn (System/getProperty "path.separator"))
- bn
- (str bn ".cljs.edn"))
- build (->> (cljs.util/split-paths bn)
- (map #(str % ".cljs.edn"))
- (string/join (System/getProperty "path.separator"))
- load-edn-opts)]
- (when build
- (when-not (false? (:validate-config (meta build)))
- (when (meta build)
- (log/debug "Validating metadata in build: " fname)
- (validate-config!
+ (defn adjust-option-docs [commands]
+ (-> commands
+ (update-in [:groups :cljs.cli/main&compile :pseudos]
+ dissoc ["-re" "--repl-env"])
+ (assoc-in [:init ["-d" "--output-dir"] :doc]
+ "Set the output directory to use")
+ (update-in [:init ["-w" "--watch"] :doc] str
+ ". This option can be supplied multiple times.")))
+
+ (defn help-str [repl-env]
+ (format
+ help-template
+ (#'cljs.cli/options-str
+ (adjust-option-docs
+ (#'cljs.cli/merged-commands repl-env)))))
+
+ (defn help-opt
+ [repl-env _ _]
+ (println (help-str repl-env)))
+
+ ;; safer option reading from files which prints out syntax errors
+
+ (defn read-edn-file [f]
+ (try (redn/read
+ (rtypes/source-logging-push-back-reader (io/reader f) 1 f))
+ (catch Throwable t
+ (log/syntax-exception t)
+ (throw
+ (ex-info (str "Couldn't read the file:" f)
+ {::error true} t)))))
+
+ (defn read-edn-string [s & [fail-msg]]
+ (try
+ (redn/read
+ (rtypes/source-logging-push-back-reader (io/reader (.getBytes s)) 1))
+ (catch Throwable t
+ (let [except-data (fig-ex/add-excerpt (fig-ex/parse-exception t) s)]
+ (log/info (ansip/format-str (log/format-ex except-data)))
+ (throw (ex-info (str (or fail-msg "Failed to read EDN string: ")
+ (.getMessage t))
+ {::error true}
+ t))))))
+
+ (defn read-edn-opts [str]
+ (letfn [(read-rsrc [rsrc-str orig-str]
+ (if-let [rsrc (io/resource rsrc-str)]
+ (read-edn-string (slurp rsrc))
+ (cljs.cli/missing-resource orig-str)))]
+ (cond
+ (string/starts-with? str "@/") (read-rsrc (subs str 2) str)
+ (string/starts-with? str "@") (read-rsrc (subs str 1) str)
+ :else
+ (let [f (io/file str)]
+ (if (.isFile f)
+ (read-edn-file f)
+ (cljs.cli/missing-file str))))))
+
+ (defn merge-meta [m m1] (with-meta (merge m m1) (merge (meta m) (meta m1))))
+
+ (defn load-edn-opts [str]
+ (reduce merge-meta {} (map read-edn-opts (cljs.util/split-paths str))))
+
+ (defn fallback-id [edn]
+ (let [m (meta edn)]
+ (cond
+ (and (:id m) (not (string/blank? (str (:id m)))))
+ (:id m)
+ ;;(:main edn) (munge (str (:main edn)))
+ :else
+ (str "build-"
+ (.getValue (doto (java.util.zip.CRC32.)
+ (.update (.getBytes (pr-str (into (sorted-map) edn))))))))))
+
+ (defn compile-opts-opt
+ [cfg copts]
+ (let [copts (string/trim copts)
+ edn (if (or (string/starts-with? copts "{")
+ (string/starts-with? copts "^"))
+ (read-edn-string copts "Error reading EDN from command line flag: -co ")
+ (load-edn-opts copts))
+ config (meta edn)
+ id
+ (and edn
+ (if (or (string/starts-with? copts "{")
+ (string/starts-with? copts "^"))
+ (and (map? edn) (fallback-id edn))
+ (->>
+ (cljs.util/split-paths copts)
+ (filter (complement string/blank?))
+ (filter #(not (.startsWith % "@")))
+ (map io/file)
+ (map (comp first #(string/split % #"\.") #(.getName %)))
+ (string/join ""))))]
+ (log/debug "Validating options passed to --compile-opts")
+ (validate-config!
+ :figwheel.main.schema.cljs-options/cljs-options
+ edn
+ (str "Configuration error in options passed to --compile-opts"))
+ (cond-> cfg
+ edn (update :options merge edn)
+ id (update-in [::build :id] #(if-not % id %))
+ config (update-in [::build :config] merge config))))
+
+ (defn repl-env-opts-opt
+ [cfg ropts]
+ (let [ropts (string/trim ropts)
+ edn (if (string/starts-with? ropts "{")
+ (read-edn-string ropts "Error reading EDN from command line flag: --repl-opts ")
+ (load-edn-opts ropts))]
+ (update cfg :repl-env-options merge edn)))
+
+ (defn figwheel-opts-opt
+ [cfg ropts]
+ (let [ropts (string/trim ropts)
+ edn (if (string/starts-with? ropts "{")
+ (read-edn-string ropts "Error reading EDN from command line flag: -fw-opts ")
+ (load-edn-opts ropts))]
+ (validate-config!
:figwheel.main.schema.config/edn
- (meta build)
- (str "Configuration error in build options meta data: " fname)))
- (log/debug "Validating CLJS compile options for build:" fname)
- (validate-config!
- :figwheel.main.schema.cljs-options/cljs-options
- build
- (str "Configuration error in CLJS compile options: " fname))))
- build))
-
-(defn watch-dir-from-ns [main-ns]
- (let [source (fw-util/ns->location main-ns)]
- (when-let [f (:uri source)]
- (when (= "file" (.getScheme (.toURI f)))
- (let [res (fw-util/relativized-path-parts (.getPath f))
- end-parts (fw-util/path-parts (:relative-path source))]
- (when (= end-parts (take-last (count end-parts) res))
- (str (apply io/file (drop-last (count end-parts) res)))))))))
-
-(def default-main-repl-index-body
- (str
- "<p>Welcome to the Figwheel REPL page.</p>"
- "<p>This page is served when you launch <code>figwheel.main</code> without any command line arguments.</p>"
- "<p>This page is currently hosting your REPL and application evaluation environment. "
- "Validate the connection by typing <code>(js/alert&nbsp;\"Hello&nbsp;Figwheel!\")</code> in the REPL.</p>"))
-
-(defn get-build-with-error [bn]
- (when-not (.exists (io/file (str bn ".cljs.edn")))
- (if (or (string/starts-with? bn "-")
- (string/blank? bn))
- (throw
- (ex-info
- (str "Missing build name")
- {:cljs.main/error :invalid-arg}))
- (throw
- (ex-info
- (str "Build " (str bn ".cljs.edn") " does not exist")
- {:cljs.main/error :invalid-arg}))))
- (get-build bn))
-
-(defn build-opt [cfg bn]
- (let [bns (string/split bn #":")
- id (string/join "" bns)
- options (->> bns
- (map get-build-with-error)
- (reduce merge-meta))]
- (-> cfg
- (update :options merge options)
- (assoc ::build (cond-> {:id id}
- (meta options)
- (assoc :config (meta options)))))))
-
-(defn build-once-opt [cfg bn]
- (let [cfg (build-opt cfg bn)]
- (assoc-in cfg [::config ::build-once] true)))
-
-(defn background-build-opt [cfg bn]
- (let [{:keys [options ::build]} (build-opt {} bn)]
- (update cfg ::background-builds
- (fnil conj [])
- (assoc build :options options))))
-
-;; TODO move these down to main action section
-
-(declare default-compile)
-
-(defn build-main-opt [repl-env-fn [_ build-name & args] cfg]
- ;; serve if no other args
- (let [args (if-not (#{"-s" "-r" "--repl" "--serve"} (first args))
- (cons "-s" args)
- args)]
- (default-compile repl-env-fn
- (merge (build-opt cfg build-name)
- {:args args
- ::build-main-opt true}))))
-
-(defn build-once-main-opt [repl-env-fn [_ build-name & args] cfg]
- (default-compile repl-env-fn
- (merge (build-once-opt cfg build-name)
- {:args args})))
-
-(declare default-output-dir default-output-to)
-
-(defn make-temp-dir []
- (let [tempf (java.io.File/createTempFile "figwheel" "repl")]
- (.delete tempf)
- (.mkdirs tempf)
- (.deleteOnExit (io/file tempf))
- (fw-util/add-classpath! (.toURL tempf))
- tempf))
-
-(defn add-temp-dir [cfg]
- (let [temp-dir (make-temp-dir)
- config-with-target (assoc-in cfg [::config :target-dir] temp-dir)
- output-dir (default-output-dir config-with-target)
- output-to (default-output-to config-with-target)]
- (-> cfg
- (assoc-in [:options :output-dir] output-dir)
- (assoc-in [:options :output-to] output-to)
- (assoc-in [:options :asset-path]
- (str "/cljs-out"
- (when-let [id (-> cfg ::build :id)]
- (str "/" id)))))))
-
-(defn pwd-likely-project-root-dir? []
- (or (some #(.isFile (clojure.java.io/file %))
- ["project.clj" "deps.edn" "figwheel-main.edn"])
- (->> (seq (.listFiles (clojure.java.io/file ".")))
- (map #(.getName %))
- (some #(.endsWith % ".cljs.edn")))))
-
-(defn should-add-temp-dir? [cfg]
- (not (pwd-likely-project-root-dir?)))
-
-(defn helper-ring-app [handler html-body output-to & [force-index?]]
- (figwheel.server.ring/default-index-html
- handler
- (figwheel.server.ring/index-html (cond-> {}
- html-body (assoc :body html-body)
- output-to (assoc :output-to output-to)))
- force-index?))
-
-(defn repl-main-opt [repl-env-fn args cfg]
- (let [cfg (if (should-add-temp-dir? cfg)
- (add-temp-dir cfg)
- cfg)
- cfg (if (get-in cfg [::build :id])
- cfg
- (assoc-in cfg [::build :id] "figwheel-default-repl-build"))
- output-to (get-in cfg [:options :output-to]
- (default-output-to cfg))]
- (default-compile
- repl-env-fn
- (-> cfg
- (assoc :args args)
- (update :options (fn [opt] (merge {:main 'figwheel.repl.preload} opt)))
- (assoc-in [:options :aot-cache] true)
- (assoc-in [::config
- :ring-stack-options
- :figwheel.server.ring/dev
- :figwheel.server.ring/system-app-handler]
- #(helper/middleware
- %
- {:header "REPL Host page"
- :body (slurp (io/resource "public/com/bhauman/figwheel/helper/content/repl_welcome.html"))
- :output-to output-to}))
- (assoc-in [::config :mode] :repl)))))
-
-(declare serve update-config)
-
-(defn print-conf [cfg]
- (println "---------------------- Figwheel options ----------------------")
- (pprint (::config cfg))
- (println "---------------------- Compiler options ----------------------")
- (pprint (:options cfg)))
-
-(defn serve-main-opt [repl-env-fn args b-cfg]
- (let [{:keys [repl-env-options repl-options options] :as cfg}
- (-> b-cfg
- (assoc :args args)
- update-config)
- repl-env-options
- (update-in
- repl-env-options
- [:ring-stack-options
- :figwheel.server.ring/dev
- :figwheel.server.ring/system-app-handler]
- (fn [sah]
- (if sah
- sah
- #(helper/serve-only-middleware % {}))))
- {:keys [pprint-config]} (::config cfg)
- repl-env (apply repl-env-fn (mapcat identity repl-env-options))]
- (log/trace "Verbose config:" (with-out-str (pprint cfg)))
- (if pprint-config
- (do
- (log/info ":pprint-config true - printing config:")
- (print-conf cfg))
- (serve {:repl-env repl-env
- :repl-options repl-options
- :join? true}))))
-
-(def figwheel-commands
- {:init {["-w" "--watch"]
- {:group :cljs.cli/compile :fn watch-opt
- :arg "path"
- :doc "Continuously build, only effective with the --compile and --build main options"}
- ["-fwo" "--fw-opts"]
- {:group :cljs.cli/compile :fn figwheel-opts-opt
- :arg "edn"
- :doc (str "Options to configure figwheel.main, can be an EDN string or "
- "system-dependent path-separated list of EDN files / classpath resources. Options "
- "will be merged left to right.")}
- ["-ro" "--repl-opts"]
- {:group ::main&compile :fn repl-env-opts-opt
- :arg "edn"
- :doc (str "Options to configure the repl-env, can be an EDN string or "
- "system-dependent path-separated list of EDN files / classpath resources. Options "
- "will be merged left to right.")}
- ["-co" "--compile-opts"]
- {:group :cljs.cli/main&compile :fn compile-opts-opt
- :arg "edn"
- :doc (str "Options to configure the build, can be an EDN string or "
- "system-dependent path-separated list of EDN files / classpath resources. Options "
- "will be merged left to right. Any meta data will be merged with the figwheel-options.")}
- ;; TODO uncertain about this
- ["-fw" "--figwheel"]
- {:group :cljs.cli/compile :fn figwheel-opt
- :arg "bool"
- :doc (str "Use Figwheel to auto reload and report compile info. "
- "Only takes effect when watching is happening and the "
- "optimizations level is :none or nil."
- "Defaults to true.")}
- ["-bb" "--background-build"]
- {:group :cljs.cli/compile :fn background-build-opt
- :arg "str"
- :doc "The name of a build config to watch and build in the background."}
- ["-pc" "--print-config"]
- {:group :cljs.cli/main&compile :fn print-config-opt
- :doc "Instead of running the command print out the configuration built up by the command. Useful for debugging."}
- }
- :main {["-b" "--build"]
- {:fn build-main-opt
- :arg "string"
- :doc (str "Run a compile process. The supplied build name or a list of build names "
- "(seperated by \":\") refer to "
- "EDN files of compile options "
- "IE. If you use \"dev\" as a build name it will indicate "
- "that a \"dev.cljs.edn\" will be read for "
- "compile options. "
- "Multiple build names will merged left to right along with their metadata. "
- "The --build option will make an "
- "extra attempt to "
- "initialize a figwheel live reloading workflow. "
- "May be followed buy either --repl or --serve. "
- "If --repl follows, "
- "will launch a REPL (along with a server) after the compile completes. "
- "If --serve follows, will only start a web server according to "
- "current configuration after the compile "
- "completes.")}
- ["-bo" "--build-once"]
- {:fn build-once-main-opt
- :arg "string"
- :doc (str "Compile for the build name one time. "
- "Looks for build EDN files just like the --build command. "
- "This will not inject Figwheel or REPL functionality into your build. "
- "It will still inject devtools if you are using :optimizations :none. "
- "If --serve follows, will start a web server according to "
- "current configuration after the compile "
- "completes.")}
- ["-r" "--repl"]
- {:fn repl-main-opt
- :doc "Run a REPL"}
- ["-s" "--serve"]
- {:fn serve-main-opt
- :arg "host:port"
- :doc "Run a server based on the figwheel-main configuration options."}
- ["-h" "--help" "-?"]
- {:fn help-opt
- :doc "Print this help message and exit"}
- }})
-
-;; ----------------------------------------------------------------------------
-;; Config
-;; ----------------------------------------------------------------------------
-
-(defn default-output-dir* [target & [scope]]
- (->> (cond-> [(or target default-target-dir) "public" "cljs-out"]
- scope (conj scope))
- (apply io/file)
- (.getPath)))
-
-(defmulti default-output-dir (fn [{:keys [options]}]
- (get options :target :browser)))
-
-(defmethod default-output-dir :default [{:keys [::config ::build]}]
- (default-output-dir* (:target-dir config) (:id build)))
-
-(defmethod default-output-dir :nodejs [{:keys [::config ::build]}]
- (let [target (:target-dir config default-target-dir)
- scope (:id build)]
- (->> (cond-> [target "node"]
- scope (conj scope))
- (apply io/file)
- (.getPath))))
-
-(defn default-output-to* [target & [scope]]
- (.getPath (io/file (or target default-target-dir) "public" "cljs-out"
- (cond->> "main.js"
- scope (str scope "-")))))
-
-(defmulti default-output-to (fn [{:keys [options]}]
- (get options :target :browser)))
-
-(defmethod default-output-to :default [{:keys [::config ::build]}]
- (default-output-to* (:target-dir config) (:id build)))
-
-(defmethod default-output-to :nodejs [{:keys [::build] :as cfg}]
- (let [scope (:id build)]
- (.getPath (io/file (default-output-dir cfg)
- (cond->> "main.js"
- scope (str scope "-"))))))
-
-(defn extra-config-merge [a' b']
- (merge-with (fn [a b]
- (cond
- (and (map? a) (map? b)) (merge a b)
- (and (sequential? a)
- (sequential? b))
- (distinct (concat a b))
- (nil? b) a
- :else b))
- a' b'))
-
-(defn resolve-fn-var [prefix handler]
- (if (or (nil? handler) (var? handler))
- handler
- (let [prefix (when prefix (str prefix ": "))]
- (when (and handler (nil? (namespace (symbol handler))))
- (throw
- (ex-info
- (format "%sThe var '%s has the wrong form it must be a namespaced symbol" prefix
- (pr-str handler))
- {::error true :handler handler})))
- (let [handler-res (fw-util/require-resolve-handler-or-error handler)]
- (when (and handler (not handler-res))
- (throw (ex-info
- (format "%sWas able to load namespace '%s but unable to resolve the specific var: '%s"
- prefix
- (namespace (symbol handler))
- (str handler))
- {::error true
- :handler handler})))
- (when (map? handler-res)
- (letfn [(error [s]
- (throw (ex-info s {::error true :handler handler})))]
- (condp = (:stage handler-res)
- :bad-namespaced-symbol
- (do (log/syntax-exception (:exception handler-res))
- (error (format "%sThere was an error while trying to resolve '%s"
- prefix
- (pr-str handler))))
- :unable-to-resolve-handler-fn
- (error (format "%sWas able to load namespace '%s but unable to resolve the specific var: '%s"
- prefix
- (namespace (symbol handler))
- (str handler)))
- :unable-to-load-handler-namespace
- (do
- (log/syntax-exception (:exception handler-res))
- (error (format "%sThere was an exception while requiring the namespace '%s while trying to load the var '%s"
- prefix
- (namespace (symbol handler))
- (str handler)))))))
- handler-res))))
-
-(defn resolve-ring-handler [ring-handler]
- (resolve-fn-var "ring-handler" ring-handler))
-
-(defn process-main-config [{:keys [ring-handler] :as main-config}]
- (let [handler (resolve-ring-handler ring-handler)]
- (cond-> main-config
- handler (assoc :ring-handler handler))))
-
-(defn process-figwheel-main-edn [main-edn]
- (when main-edn
- (when-not (false? (:validate-config main-edn))
- (log/info "Validating figwheel-main.edn")
- (validate-config!
- :figwheel.main.schema.config/edn
- main-edn "Configuration error in figwheel-main.edn"
- "figwheel-main.edn is valid \\(ツ)/"))
- (process-main-config main-edn)))
-
-;; use tools reader read-string for better error messages
-#_(redn/read-string)
-(defn fetch-figwheel-main-edn [cfg]
- (when (.isFile (io/file "figwheel-main.edn"))
- (read-edn-file "figwheel-main.edn")))
-
-(defn- config-figwheel-main-edn [cfg]
- (let [config-edn (process-figwheel-main-edn
- (or (::start-figwheel-options cfg)
- (fetch-figwheel-main-edn cfg)))]
- (cond-> cfg
- config-edn (update ::config #(merge config-edn %)))))
-
-(defn- config-merge-current-build-conf [{:keys [::extra-config ::build] :as cfg}]
- (update cfg
- ::config #(extra-config-merge
- (merge-with (fn [a b] (if b b a)) %
- (process-main-config (:config build)))
- extra-config)))
-
-(defn host-port-arg? [arg]
- (and arg (re-matches #"(.*):(\d*)" arg)))
-
-(defn update-server-host-port [config [f address-port & args]]
- (if (and (#{"-s" "--serve"} f) address-port)
- (let [[_ host port] (host-port-arg? address-port)]
- (cond-> config
- (not (string/blank? host)) (assoc-in [:ring-server-options :host] host)
- (not (string/blank? port)) (assoc-in [:ring-server-options :port] (Integer/parseInt port))))
- config))
-
-;; targets options
-(defn- config-main-ns [{:keys [ns options] :as cfg}]
- (let [main-ns (if (and ns (not (#{"-r" "--repl" "-s" "--serve"} ns)))
- (symbol ns)
- (:main options))]
- (cond-> cfg
- main-ns (assoc :ns main-ns) ;; TODO not needed?
- main-ns (assoc-in [:options :main] main-ns))))
-
-(defn warn-that-dir-not-on-classpath [typ dir]
- (let [[n k] (condp = typ
- :source ["Source directory" :source-paths]
- :target ["Target directory" :resource-paths])]
- (log/warn (ansip/format-str
- [:yellow n " "
- (pr-str (str dir))
- " is not on the classpath"]))
- (log/warn "Please fix this by adding" (pr-str (str dir))
- "to your classpath\n"
- "I.E.\n"
- "For Clojure CLI Tools in your deps.edn file:\n"
- " ensure" (pr-str (str dir))
- "is in your :paths key\n\n"
- (when k
- (format
- (str "For Leiningen in your project.clj:\n"
- " add it to the %s key\n")
- (pr-str k))))))
-
-;; takes a string or file representation of a directory
-(defn- add-classpath! [dir]
- (when-not (fw-util/dir-on-classpath? dir)
- (log/warn (ansip/format-str [:yellow
- (format "Attempting to dynamically add %s to classpath!"
- (pr-str (str dir)))]))
- (fw-util/add-classpath! (->> dir
- io/file
- .getCanonicalPath
- io/file
- .toURL))))
-
-(defn- config-main-source-path-on-classpath [{:keys [options] :as cfg}]
- (when-let [main (:ns cfg)]
- (when-not (fw-util/safe-ns->location main)
- (when-let [src-dir (fw-util/find-source-dir-for-cljs-ns main)]
- (when-not (fw-util/dir-on-classpath? src-dir)
- (if (get-in cfg [::config :helpful-classpaths] true)
- (do
- (add-classpath! src-dir)
- (warn-that-dir-not-on-classpath :source src-dir))
- (log/warn (ansip/format-str
- [:yellow
- "The source directory for the main ns "
- (pr-str (str src-dir))
- " is not the classpath!"])))))))
- cfg)
-
-;; targets local config
-(defn- config-repl-serve? [{:keys [ns args] :as cfg}]
- (let [rfs #{"-r" "--repl"}
- sfs #{"-s" "--serve"}]
- (cond-> cfg
- (boolean (or (rfs ns) (rfs (first args))))
- (assoc-in [::config :mode] :repl)
- (boolean (or (sfs ns) (sfs (first args))))
- (->
- (assoc-in [::config :mode] :serve)
- (update ::config update-server-host-port args))
- (rfs (first args))
- (update :args rest)
- (sfs (first args))
- (update :args rest)
- (and (sfs (first args)) (host-port-arg? (second args)))
- (update :args rest))))
-
-;; targets local config
-(defn- config-update-watch-dirs [{:keys [options ::config] :as cfg}]
- ;; remember we have to fix this for the repl-opt fn as well
- ;; so that it understands multiple watch directories
- (update-in cfg [::config :watch-dirs]
- #(not-empty
- (distinct
- (let [ns-watch-dir (and
+ edn "Error validating figwheel options EDN provided to -fwo CLI flag")
+ (update cfg ::config merge edn)))
+
+ (defn print-config-opt [cfg opt]
+ (assoc-in cfg [::config :pprint-config] (not (#{"false"} opt))))
+
+ (defn- watch-opt
+ [cfg path]
+ (when-not (.exists (io/file path))
+ (if (or (string/starts-with? path "-")
+ (string/blank? path))
+ (throw
+ (ex-info
+ (str "Missing watch path")
+ {:cljs.main/error :invalid-arg}))
+ (throw
+ (ex-info
+ (str "Watch path \"" path "\" does not exist")
+ {:cljs.main/error :invalid-arg}))))
+ (update-in cfg [::extra-config :watch-dirs] (fnil conj []) path))
+
+ (defn figwheel-opt [cfg bl]
+ (assoc-in cfg [::config :figwheel-core] (not= bl "false")))
+
+ (defn get-build [bn]
+ (let [fname (if (.contains bn (System/getProperty "path.separator"))
+ bn
+ (str bn ".cljs.edn"))
+ build (->> (cljs.util/split-paths bn)
+ (map #(str % ".cljs.edn"))
+ (string/join (System/getProperty "path.separator"))
+ load-edn-opts)]
+ (when build
+ (when-not (false? (:validate-config (meta build)))
+ (when (meta build)
+ (log/debug "Validating metadata in build: " fname)
+ (validate-config!
+ :figwheel.main.schema.config/edn
+ (meta build)
+ (str "Configuration error in build options meta data: " fname)))
+ (log/debug "Validating CLJS compile options for build:" fname)
+ (validate-config!
+ :figwheel.main.schema.cljs-options/cljs-options
+ build
+ (str "Configuration error in CLJS compile options: " fname))))
+ build))
+
+ (defn watch-dir-from-ns [main-ns]
+ (let [source (fw-util/ns->location main-ns)]
+ (when-let [f (:uri source)]
+ (when (= "file" (.getScheme (.toURI f)))
+ (let [res (fw-util/relativized-path-parts (.getPath f))
+ end-parts (fw-util/path-parts (:relative-path source))]
+ (when (= end-parts (take-last (count end-parts) res))
+ (str (apply io/file (drop-last (count end-parts) res)))))))))
+
+ (def default-main-repl-index-body
+ (str
+ "<p>Welcome to the Figwheel REPL page.</p>"
+ "<p>This page is served when you launch <code>figwheel.main</code> without any command line arguments.</p>"
+ "<p>This page is currently hosting your REPL and application evaluation environment. "
+ "Validate the connection by typing <code>(js/alert&nbsp;\"Hello&nbsp;Figwheel!\")</code> in the REPL.</p>"))
+
+ (defn get-build-with-error [bn]
+ (when-not (.exists (io/file (str bn ".cljs.edn")))
+ (if (or (string/starts-with? bn "-")
+ (string/blank? bn))
+ (throw
+ (ex-info
+ (str "Missing build name")
+ {:cljs.main/error :invalid-arg}))
+ (throw
+ (ex-info
+ (str "Build " (str bn ".cljs.edn") " does not exist")
+ {:cljs.main/error :invalid-arg}))))
+ (get-build bn))
+
+ (defn build-opt [cfg bn]
+ (let [bns (string/split bn #":")
+ id (string/join "" bns)
+ options (->> bns
+ (map get-build-with-error)
+ (reduce merge-meta))]
+ (-> cfg
+ (update :options merge options)
+ (assoc ::build (cond-> {:id id}
+ (meta options)
+ (assoc :config (meta options)))))))
+
+ (defn build-once-opt [cfg bn]
+ (let [cfg (build-opt cfg bn)]
+ (assoc-in cfg [::config ::build-once] true)))
+
+ (defn background-build-opt [cfg bn]
+ (let [{:keys [options ::build]} (build-opt {} bn)]
+ (update cfg ::background-builds
+ (fnil conj [])
+ (assoc build :options options))))
+
+ ;; TODO move these down to main action section
+
+ (declare default-compile)
+
+ (defn build-main-opt [repl-env-fn [_ build-name & args] cfg]
+ ;; serve if no other args
+ (let [args (if-not (#{"-s" "-r" "--repl" "--serve"} (first args))
+ (cons "-s" args)
+ args)]
+ (default-compile repl-env-fn
+ (merge (build-opt cfg build-name)
+ {:args args
+ ::build-main-opt true}))))
+
+ (defn build-once-main-opt [repl-env-fn [_ build-name & args] cfg]
+ (default-compile repl-env-fn
+ (merge (build-once-opt cfg build-name)
+ {:args args})))
+
+ (declare default-output-dir default-output-to)
+
+ (defn make-temp-dir []
+ (let [tempf (java.io.File/createTempFile "figwheel" "repl")]
+ (.delete tempf)
+ (.mkdirs tempf)
+ (.deleteOnExit (io/file tempf))
+ (fw-util/add-classpath! (.toURL tempf))
+ tempf))
+
+ (defn add-temp-dir [cfg]
+ (let [temp-dir (make-temp-dir)
+ config-with-target (assoc-in cfg [::config :target-dir] temp-dir)
+ output-dir (default-output-dir config-with-target)
+ output-to (default-output-to config-with-target)]
+ (-> cfg
+ (assoc-in [:options :output-dir] output-dir)
+ (assoc-in [:options :output-to] output-to)
+ (assoc-in [:options :asset-path]
+ (str "/cljs-out"
+ (when-let [id (-> cfg ::build :id)]
+ (str "/" id)))))))
+
+ (defn pwd-likely-project-root-dir? []
+ (or (some #(.isFile (clojure.java.io/file %))
+ ["project.clj" "deps.edn" "figwheel-main.edn"])
+ (->> (seq (.listFiles (clojure.java.io/file ".")))
+ (map #(.getName %))
+ (some #(.endsWith % ".cljs.edn")))))
+
+ (defn should-add-temp-dir? [cfg]
+ (not (pwd-likely-project-root-dir?)))
+
+ (defn helper-ring-app [handler html-body output-to & [force-index?]]
+ (figwheel.server.ring/default-index-html
+ handler
+ (figwheel.server.ring/index-html (cond-> {}
+ html-body (assoc :body html-body)
+ output-to (assoc :output-to output-to)))
+ force-index?))
+
+ (defn repl-main-opt [repl-env-fn args cfg]
+ (let [cfg (if (should-add-temp-dir? cfg)
+ (add-temp-dir cfg)
+ cfg)
+ cfg (if (get-in cfg [::build :id])
+ cfg
+ (assoc-in cfg [::build :id] "figwheel-default-repl-build"))
+ output-to (get-in cfg [:options :output-to]
+ (default-output-to cfg))]
+ (default-compile
+ repl-env-fn
+ (-> cfg
+ (assoc :args args)
+ (update :options (fn [opt] (merge {:main 'figwheel.repl.preload} opt)))
+ (assoc-in [:options :aot-cache] true)
+ (assoc-in [::config
+ :ring-stack-options
+ :figwheel.server.ring/dev
+ :figwheel.server.ring/system-app-handler]
+ #(helper/middleware
+ %
+ {:header "REPL Host page"
+ :body (slurp (io/resource "public/com/bhauman/figwheel/helper/content/repl_welcome.html"))
+ :output-to output-to}))
+ (assoc-in [::config :mode] :repl)))))
+
+ (declare serve update-config)
+
+ (defn print-conf [cfg]
+ (println "---------------------- Figwheel options ----------------------")
+ (pprint (::config cfg))
+ (println "---------------------- Compiler options ----------------------")
+ (pprint (:options cfg)))
+
+ (defn serve-main-opt [repl-env-fn args b-cfg]
+ (let [{:keys [repl-env-options repl-options options] :as cfg}
+ (-> b-cfg
+ (assoc :args args)
+ update-config)
+ repl-env-options
+ (update-in
+ repl-env-options
+ [:ring-stack-options
+ :figwheel.server.ring/dev
+ :figwheel.server.ring/system-app-handler]
+ (fn [sah]
+ (if sah
+ sah
+ #(helper/serve-only-middleware % {}))))
+ {:keys [pprint-config]} (::config cfg)
+ repl-env (apply repl-env-fn (mapcat identity repl-env-options))]
+ (log/trace "Verbose config:" (with-out-str (pprint cfg)))
+ (if pprint-config
+ (do
+ (log/info ":pprint-config true - printing config:")
+ (print-conf cfg))
+ (serve {:repl-env repl-env
+ :repl-options repl-options
+ :join? true}))))
+
+ (def figwheel-commands
+ {:init {["-w" "--watch"]
+ {:group :cljs.cli/compile :fn watch-opt
+ :arg "path"
+ :doc "Continuously build, only effective with the --compile and --build main options"}
+ ["-fwo" "--fw-opts"]
+ {:group :cljs.cli/compile :fn figwheel-opts-opt
+ :arg "edn"
+ :doc (str "Options to configure figwheel.main, can be an EDN string or "
+ "system-dependent path-separated list of EDN files / classpath resources. Options "
+ "will be merged left to right.")}
+ ["-ro" "--repl-opts"]
+ {:group ::main&compile :fn repl-env-opts-opt
+ :arg "edn"
+ :doc (str "Options to configure the repl-env, can be an EDN string or "
+ "system-dependent path-separated list of EDN files / classpath resources. Options "
+ "will be merged left to right.")}
+ ["-co" "--compile-opts"]
+ {:group :cljs.cli/main&compile :fn compile-opts-opt
+ :arg "edn"
+ :doc (str "Options to configure the build, can be an EDN string or "
+ "system-dependent path-separated list of EDN files / classpath resources. Options "
+ "will be merged left to right. Any meta data will be merged with the figwheel-options.")}
+ ;; TODO uncertain about this
+ ["-fw" "--figwheel"]
+ {:group :cljs.cli/compile :fn figwheel-opt
+ :arg "bool"
+ :doc (str "Use Figwheel to auto reload and report compile info. "
+ "Only takes effect when watching is happening and the "
+ "optimizations level is :none or nil."
+ "Defaults to true.")}
+ ["-bb" "--background-build"]
+ {:group :cljs.cli/compile :fn background-build-opt
+ :arg "str"
+ :doc "The name of a build config to watch and build in the background."}
+ ["-pc" "--print-config"]
+ {:group :cljs.cli/main&compile :fn print-config-opt
+ :doc "Instead of running the command print out the configuration built up by the command. Useful for debugging."}
+ }
+ :main {["-b" "--build"]
+ {:fn build-main-opt
+ :arg "string"
+ :doc (str "Run a compile process. The supplied build name or a list of build names "
+ "(seperated by \":\") refer to "
+ "EDN files of compile options "
+ "IE. If you use \"dev\" as a build name it will indicate "
+ "that a \"dev.cljs.edn\" will be read for "
+ "compile options. "
+ "Multiple build names will merged left to right along with their metadata. "
+ "The --build option will make an "
+ "extra attempt to "
+ "initialize a figwheel live reloading workflow. "
+ "May be followed buy either --repl or --serve. "
+ "If --repl follows, "
+ "will launch a REPL (along with a server) after the compile completes. "
+ "If --serve follows, will only start a web server according to "
+ "current configuration after the compile "
+ "completes.")}
+ ["-bo" "--build-once"]
+ {:fn build-once-main-opt
+ :arg "string"
+ :doc (str "Compile for the build name one time. "
+ "Looks for build EDN files just like the --build command. "
+ "This will not inject Figwheel or REPL functionality into your build. "
+ "It will still inject devtools if you are using :optimizations :none. "
+ "If --serve follows, will start a web server according to "
+ "current configuration after the compile "
+ "completes.")}
+ ["-r" "--repl"]
+ {:fn repl-main-opt
+ :doc "Run a REPL"}
+ ["-s" "--serve"]
+ {:fn serve-main-opt
+ :arg "host:port"
+ :doc "Run a server based on the figwheel-main configuration options."}
+ ["-h" "--help" "-?"]
+ {:fn help-opt
+ :doc "Print this help message and exit"}
+ }})
+
+ ;; ----------------------------------------------------------------------------
+ ;; Config
+ ;; ----------------------------------------------------------------------------
+
+ (defn default-output-dir* [target & [scope]]
+ (->> (cond-> [(or target default-target-dir) "public" "cljs-out"]
+ scope (conj scope))
+ (apply io/file)
+ (.getPath)))
+
+ (defmulti default-output-dir (fn [{:keys [options]}]
+ (get options :target :browser)))
+
+ (defmethod default-output-dir :default [{:keys [::config ::build]}]
+ (default-output-dir* (:target-dir config) (:id build)))
+
+ (defmethod default-output-dir :nodejs [{:keys [::config ::build]}]
+ (let [target (:target-dir config default-target-dir)
+ scope (:id build)]
+ (->> (cond-> [target "node"]
+ scope (conj scope))
+ (apply io/file)
+ (.getPath))))
+
+ (defn default-output-to* [target & [scope]]
+ (.getPath (io/file (or target default-target-dir) "public" "cljs-out"
+ (cond->> "main.js"
+ scope (str scope "-")))))
+
+ (defmulti default-output-to (fn [{:keys [options]}]
+ (get options :target :browser)))
+
+ (defmethod default-output-to :default [{:keys [::config ::build]}]
+ (default-output-to* (:target-dir config) (:id build)))
+
+ (defmethod default-output-to :nodejs [{:keys [::build] :as cfg}]
+ (let [scope (:id build)]
+ (.getPath (io/file (default-output-dir cfg)
+ (cond->> "main.js"
+ scope (str scope "-"))))))
+
+ (defn extra-config-merge [a' b']
+ (merge-with (fn [a b]
+ (cond
+ (and (map? a) (map? b)) (merge a b)
+ (and (sequential? a)
+ (sequential? b))
+ (distinct (concat a b))
+ (nil? b) a
+ :else b))
+ a' b'))
+
+ (defn resolve-fn-var [prefix handler]
+ (if (or (nil? handler) (var? handler))
+ handler
+ (let [prefix (when prefix (str prefix ": "))]
+ (when (and handler (nil? (namespace (symbol handler))))
+ (throw
+ (ex-info
+ (format "%sThe var '%s has the wrong form it must be a namespaced symbol" prefix
+ (pr-str handler))
+ {::error true :handler handler})))
+ (let [handler-res (fw-util/require-resolve-handler-or-error handler)]
+ (when (and handler (not handler-res))
+ (throw (ex-info
+ (format "%sWas able to load namespace '%s but unable to resolve the specific var: '%s"
+ prefix
+ (namespace (symbol handler))
+ (str handler))
+ {::error true
+ :handler handler})))
+ (when (map? handler-res)
+ (letfn [(error [s]
+ (throw (ex-info s {::error true :handler handler})))]
+ (condp = (:stage handler-res)
+ :bad-namespaced-symbol
+ (do (log/syntax-exception (:exception handler-res))
+ (error (format "%sThere was an error while trying to resolve '%s"
+ prefix
+ (pr-str handler))))
+ :unable-to-resolve-handler-fn
+ (error (format "%sWas able to load namespace '%s but unable to resolve the specific var: '%s"
+ prefix
+ (namespace (symbol handler))
+ (str handler)))
+ :unable-to-load-handler-namespace
+ (do
+ (log/syntax-exception (:exception handler-res))
+ (error (format "%sThere was an exception while requiring the namespace '%s while trying to load the var '%s"
+ prefix
+ (namespace (symbol handler))
+ (str handler)))))))
+ handler-res))))
+
+ (defn resolve-ring-handler [ring-handler]
+ (resolve-fn-var "ring-handler" ring-handler))
+
+ (defn process-main-config [{:keys [ring-handler] :as main-config}]
+ (let [handler (resolve-ring-handler ring-handler)]
+ (cond-> main-config
+ handler (assoc :ring-handler handler))))
+
+ (defn process-figwheel-main-edn [main-edn]
+ (when main-edn
+ (when-not (false? (:validate-config main-edn))
+ (log/info "Validating figwheel-main.edn")
+ (validate-config!
+ :figwheel.main.schema.config/edn
+ main-edn "Configuration error in figwheel-main.edn"
+ "figwheel-main.edn is valid \\(ツ)/"))
+ (process-main-config main-edn)))
+
+ ;; use tools reader read-string for better error messages
+ #_(redn/read-string)
+ (defn fetch-figwheel-main-edn [cfg]
+ (when (.isFile (io/file "figwheel-main.edn"))
+ (read-edn-file "figwheel-main.edn")))
+
+ (defn- config-figwheel-main-edn [cfg]
+ (let [config-edn (process-figwheel-main-edn
+ (or (::start-figwheel-options cfg)
+ (fetch-figwheel-main-edn cfg)))]
+ (cond-> cfg
+ config-edn (update ::config #(merge config-edn %)))))
+
+ (defn- config-merge-current-build-conf [{:keys [::extra-config ::build] :as cfg}]
+ (update cfg
+ ::config #(extra-config-merge
+ (merge-with (fn [a b] (if b b a)) %
+ (process-main-config (:config build)))
+ extra-config)))
+
+ (defn host-port-arg? [arg]
+ (and arg (re-matches #"(.*):(\d*)" arg)))
+
+ (defn update-server-host-port [config [f address-port & args]]
+ (if (and (#{"-s" "--serve"} f) address-port)
+ (let [[_ host port] (host-port-arg? address-port)]
+ (cond-> config
+ (not (string/blank? host)) (assoc-in [:ring-server-options :host] host)
+ (not (string/blank? port)) (assoc-in [:ring-server-options :port] (Integer/parseInt port))))
+ config))
+
+ ;; targets options
+ (defn- config-main-ns [{:keys [ns options] :as cfg}]
+ (let [main-ns (if (and ns (not (#{"-r" "--repl" "-s" "--serve"} ns)))
+ (symbol ns)
+ (:main options))]
+ (cond-> cfg
+ main-ns (assoc :ns main-ns) ;; TODO not needed?
+ main-ns (assoc-in [:options :main] main-ns))))
+
+ (defn warn-that-dir-not-on-classpath [typ dir]
+ (let [[n k] (condp = typ
+ :source ["Source directory" :source-paths]
+ :target ["Target directory" :resource-paths])]
+ (log/warn (ansip/format-str
+ [:yellow n " "
+ (pr-str (str dir))
+ " is not on the classpath"]))
+ (log/warn "Please fix this by adding" (pr-str (str dir))
+ "to your classpath\n"
+ "I.E.\n"
+ "For Clojure CLI Tools in your deps.edn file:\n"
+ " ensure" (pr-str (str dir))
+ "is in your :paths key\n\n"
+ (when k
+ (format
+ (str "For Leiningen in your project.clj:\n"
+ " add it to the %s key\n")
+ (pr-str k))))))
+
+ ;; takes a string or file representation of a directory
+ (defn- add-classpath! [dir]
+ (when-not (fw-util/dir-on-classpath? dir)
+ (log/warn (ansip/format-str [:yellow
+ (format "Attempting to dynamically add %s to classpath!"
+ (pr-str (str dir)))]))
+ (fw-util/add-classpath! (->> dir
+ io/file
+ .getCanonicalPath
+ io/file
+ .toURL))))
+
+ (defn- config-main-source-path-on-classpath [{:keys [options] :as cfg}]
+ (when-let [main (:ns cfg)]
+ (when-not (fw-util/safe-ns->location main)
+ (when-let [src-dir (fw-util/find-source-dir-for-cljs-ns main)]
+ (when-not (fw-util/dir-on-classpath? src-dir)
+ (if (get-in cfg [::config :helpful-classpaths] true)
+ (do
+ (add-classpath! src-dir)
+ (warn-that-dir-not-on-classpath :source src-dir))
+ (log/warn (ansip/format-str
+ [:yellow
+ "The source directory for the main ns "
+ (pr-str (str src-dir))
+ " is not the classpath!"])))))))
+ cfg)
+
+ ;; targets local config
+ (defn- config-repl-serve? [{:keys [ns args] :as cfg}]
+ (let [rfs #{"-r" "--repl"}
+ sfs #{"-s" "--serve"}]
+ (cond-> cfg
+ (boolean (or (rfs ns) (rfs (first args))))
+ (assoc-in [::config :mode] :repl)
+ (boolean (or (sfs ns) (sfs (first args))))
+ (->
+ (assoc-in [::config :mode] :serve)
+ (update ::config update-server-host-port args))
+ (rfs (first args))
+ (update :args rest)
+ (sfs (first args))
+ (update :args rest)
+ (and (sfs (first args)) (host-port-arg? (second args)))
+ (update :args rest))))
+
+ ;; targets local config
+ (defn- config-update-watch-dirs [{:keys [options ::config] :as cfg}]
+ ;; remember we have to fix this for the repl-opt fn as well
+ ;; so that it understands multiple watch directories
+ (update-in cfg [::config :watch-dirs]
+ #(not-empty
+ (distinct
+ (let [ns-watch-dir (and
(#{:repl :serve} (:mode config))
(not (::build-once config))
(not (:watch options))
(empty? %)
(:main options)
(watch-dir-from-ns (:main options)))]
- (cond-> %
- (:watch options) (conj (:watch options))
- ns-watch-dir (conj ns-watch-dir)))))))
-
-(defn- config-ensure-watch-dirs-on-classpath [{:keys [::config] :as cfg}]
- (doseq [src-dir (:watch-dirs config)]
- (when-not (fw-util/dir-on-current-classpath? src-dir)
- (log/warn (ansip/format-str
- [:yellow
- "The watch directory "
- (pr-str (str src-dir))
- " is not on the classpath! A watch directory is must "
- "on the classpath and point to the root directory of your namespace "
- "source tree. A general all encompassing watch directory will not work."]))
- (when (get config :helpful-classpaths true)
- (add-classpath! src-dir)
- (warn-that-dir-not-on-classpath :source src-dir)))) cfg)
-
-;; needs local config
-(defn figwheel-mode? [{:keys [::config options]}]
- (and (:figwheel-core config true)
- (and (#{:repl :serve} (:mode config))
- (not (::build-once config))
- (not-empty (:watch-dirs config)))
- (= :none (:optimizations options :none))))
-
-(defn repl-connection? [{:keys [::config options] :as cfg}]
- (or (and (#{:repl :serve} (:mode config))
- (not (::build-once config))
- (= :none (:optimizations options :none)))
- (figwheel-mode? cfg)))
-
-;; TODO this is a no-op right now
-(defn prep-client-config [config]
- (let [cl-config (select-keys config [])]
- cl-config))
-
-;; targets options needs local config
-(defn- config-figwheel-mode? [{:keys [::config options] :as cfg}]
- (cond-> cfg
- ;; check for a main??
- (figwheel-mode? cfg)
- (->
- (update ::initializers (fnil conj []) #(figwheel.core/start*))
- (update-in [:options :preloads]
- (fn [p]
- (vec (distinct
- (concat p '[figwheel.core figwheel.main]))))))
- (false? (:heads-up-display config))
- (update-in [:options :closure-defines] assoc 'figwheel.core/heads-up-display false)
- (true? (:load-warninged-code config))
- (update-in [:options :closure-defines] assoc 'figwheel.core/load-warninged-code true)))
-
-(defn- modules-output-to [{:keys [options ::config ::build] :as cfg}]
- (if (not-empty (:modules options))
- (update-in
- cfg [:options :modules]
- #(->> %
- (map (fn [[k v]]
- (if-not (:output-to v)
- [k (assoc v :output-to
- (string/replace
- (default-output-to cfg)
- "main.js" ;; brittle
- (str (name k) ".js")))]
- [k v])))
- (into {})))
- cfg))
-
-;; targets options
-;; TODO needs to consider case where one or the other is specified???
-(defn- config-default-dirs [{:keys [options ::config ::build] :as cfg}]
- (cond-> cfg
- (and (nil? (:output-to options)) (not (:modules options)))
- (assoc-in [:options :output-to] (default-output-to cfg))
- (:modules options)
- modules-output-to
- (nil? (:output-dir options))
- (assoc-in [:options :output-dir] (default-output-dir cfg))))
-
-(defn figure-default-asset-path [{:keys [figwheel-options options ::config ::build] :as cfg}]
- (if (= :nodejs (:target options))
- (:output-dir options)
- (let [{:keys [output-dir]} options]
- ;; TODO could discover the resource root if there is only one
- ;; or if ONLY static file serving can probably do something with that
- ;; as well
- ;; UNTIL THEN if you have configured your static resources no default asset-path
- (when-not (contains? (:ring-stack-options figwheel-options) :static)
- (let [parts (fw-util/relativized-path-parts (or output-dir
- (default-output-dir cfg)))]
- (when-let [asset-path
- (->> parts
- (split-with (complement #{"public"}))
- last
- rest
- not-empty)]
- (str "/" (string/join "/" asset-path))))))))
-
-;; targets options
-(defn- config-default-asset-path [{:keys [options] :as cfg}]
- (cond-> cfg
- (nil? (:asset-path options))
- (assoc-in [:options :asset-path] (figure-default-asset-path cfg))))
-
-;; targets options
-(defn- config-default-aot-cache-false [{:keys [options] :as cfg}]
- (cond-> cfg
- (not (contains? options :aot-cache))
- (assoc-in [:options :aot-cache] false)))
-
-(defn config-clean [cfg]
- (update cfg :options dissoc :watch))
-
-;; TODO create connection
-
-(let [localhost (promise)]
- ;; this call takes a very long time to complete so lets get in in parallel
- (doto (Thread. #(deliver localhost (try (java.net.InetAddress/getLocalHost)
- (catch Throwable e
- nil))))
- (.setDaemon true)
- (.start))
- (defn fill-connect-url-template [url host server-port]
- (cond-> url
- (.contains url "[[config-hostname]]")
- (string/replace "[[config-hostname]]" (or host "localhost"))
-
- (.contains url "[[server-hostname]]")
- (string/replace "[[server-hostname]]" (or (some-> @localhost
- .getHostName)
- "localhost"))
-
- (.contains url "[[server-ip]]")
- (string/replace "[[server-ip]]" (or (some-> @localhost
- .getHostAddress)
- "127.0.0.1"))
-
- (.contains url "[[server-port]]")
- (string/replace "[[server-port]]" (str server-port)))))
-
-(defn add-to-query [uri query-map]
- (let [[pre query] (string/split uri #"\?")]
- (str pre
- (when (or query (not-empty query-map))
- (str "?"
- (string/join "&"
- (map (fn [[k v]]
- (str (name k)
- "="
- (java.net.URLEncoder/encode (str v) "UTF-8")))
- query-map))
- (when (not (string/blank? query))
- (str "&" query)))))))
-
-#_(add-to-query "ws://localhost:9500/figwheel-connect?hey=5" {:ab 'ab})
-
-(defn config-connect-url [{:keys [::config repl-env-options] :as cfg} connect-id]
- (let [port (get-in config [:ring-server-options :port] figwheel.repl/default-port)
- host (get-in config [:ring-server-options :host] "localhost")
- connect-url
- (fill-connect-url-template
- (:connect-url config "ws://[[config-hostname]]:[[server-port]]/figwheel-connect")
- host
- port)]
- (add-to-query connect-url connect-id)))
-
-#_(config-connect-url {} {:abb 1})
-
-(defn config-repl-connect [{:keys [::config options ::build] :as cfg}]
- (let [connect-id (:connect-id config
- (cond-> {:fwprocess process-unique}
- (:id build) (assoc :fwbuild (:id build))))
- conn-url (config-connect-url cfg connect-id)
- conn? (repl-connection? cfg)]
- (cond-> cfg
- conn?
- (update-in [:options :closure-defines] assoc 'figwheel.repl/connect-url conn-url)
- conn?
- (update-in [:options :preloads]
- (fn [p]
- (vec (distinct
- (concat p '[figwheel.repl.preload])))))
- conn?
- (update-in [:options :repl-requires] into '[[cljs.repl :refer-macros [source doc find-doc apropos dir pst]]
- [cljs.pprint :refer [pprint] :refer-macros [pp]]
- [figwheel.main :refer-macros [stop-builds start-builds build-once reset clean status]]
- [figwheel.repl :refer-macros [conns focus]]])
- (and conn? (:client-print-to config))
- (update-in [:options :closure-defines] assoc
- 'figwheel.repl/print-output
- (string/join "," (distinct (map name (:client-print-to config)))))
- (and conn? (:client-log-level config))
- (update-in [:options :closure-defines] assoc
- 'figwheel.repl/client-log-level
- (name (:client-log-level config)))
- (and conn? (not-empty (:watch-dirs config)))
- (update-in [:repl-options :analyze-path] (comp vec concat) (:watch-dirs config))
- (and conn? (not-empty connect-id))
- (assoc-in [:repl-env-options :connection-filter]
- (let [kys (keys connect-id)]
- (fn [{:keys [query]}]
- (if (not (:fwprocess query))
- (= (:fwbuild query)
- (:fwbuild connect-id))
- (= (select-keys query kys)
- connect-id))))))))
-
-(defn config-cljs-devtools [{:keys [::config options] :as cfg}]
- (if (and
- (nil? (:target options))
- (= :none (:optimizations options :none))
- (:cljs-devtools config true)
- (try (bapi/ns->location 'devtools.preload) (catch Throwable t false)))
- (update-in cfg
- [:options :preloads]
- (fn [p]
- (vec (distinct
- (concat p '[devtools.preload])))))
- cfg))
-
-(defn config-open-file-command [{:keys [::config options] :as cfg}]
- (if-let [setup (and (:open-file-command config)
- (repl-connection? cfg)
- (fw-util/require-resolve-var 'figwheel.main.editor/setup))]
- (-> cfg
- (update ::initializers (fnil conj []) #(setup (:open-file-command config)))
- (update-in [:options :preloads]
- (fn [p] (vec (distinct (conj p 'figwheel.main.editor))))))
- cfg))
-
-(defn config-eval-back [{:keys [::config options] :as cfg}]
- (if-let [setup (and (repl-connection? cfg)
- (fw-util/require-resolve-var 'figwheel.main.evalback/setup))]
- (-> cfg
- (update ::initializers (fnil conj []) #(setup))
- (update-in [:options :preloads]
- (fn [p] (vec (distinct (concat p '[figwheel.main.evalback #_figwheel.main.testing]))))))
- cfg))
-
-(defn watch-css [css-dirs]
- (when-let [css-dirs (not-empty css-dirs)]
- (when-let [start-css (fw-util/require-resolve-var 'figwheel.main.css-reload/start*)]
- (start-css css-dirs))))
-
-(defn config-watch-css [{:keys [::config options] :as cfg}]
- (cond-> cfg
- (and (not-empty (:css-dirs config))
- (repl-connection? cfg))
- (->
- (update ::initializers (fnil conj []) #(watch-css (:css-dirs config)))
- (update-in [:options :preloads]
- (fn [p] (vec (distinct (conj p 'figwheel.main.css-reload))))))))
-
-(defn get-repl-options [{:keys [options args inits repl-options] :as cfg}]
- (assoc (merge (dissoc options :main)
- repl-options)
- :inits
- (into
- [{:type :init-forms
- :forms (when-not (empty? args)
- [`(set! *command-line-args* (list ~@args))])}]
- inits)))
-
-(defn get-repl-env-options [{:keys [repl-env-options ::config options] :as cfg}]
- (let [repl-options (get-repl-options cfg)]
- (merge
- (select-keys config
- [:ring-server
- :ring-server-options
- :ring-stack
- :ring-stack-options
- :ring-handler
- :cljsjs-resources
- :launch-node
- :inspect-node
- :node-command
- :broadcast
- :open-url
- :launch-js
- :repl-eval-timeout])
- repl-env-options ;; from command line
- (select-keys options [:output-to :output-dir :target]))))
-
-(defn config-finalize-repl-options [cfg]
- (let [repl-options (get-repl-options cfg)
- repl-env-options (get-repl-env-options cfg)]
- (assoc cfg
- :repl-options repl-options
- :repl-env-options repl-env-options)))
-
-(defn config-set-log-level! [{:keys [::config] :as cfg}]
- (when-let [log-level (:log-level config)]
- (log/set-level log-level))
- cfg)
-
-(defn config-ansi-color-output! [{:keys [::config] :as cfg}]
- (when (some? (:ansi-color-output config))
- (alter-var-root #'ansip/*use-color* (fn [_] (:ansi-color-output config))))
- cfg)
-
-(defn config-log-syntax-error-style! [{:keys [::config] :as cfg}]
- (when (some? (:log-syntax-error-style config))
- (alter-var-root #'log/*syntax-error-style* (fn [_] (:log-syntax-error-style config))))
- cfg)
-
-(defn- config-warn-resource-directory-not-on-classpath [{:keys [::config options] :as cfg}]
- ;; this could check for other directories than resources
- ;; but this is mainly to help newcomers
- (when (and (nil? (:target options))
- (or (and (::build-once config)
- (#{:serve} (:mode config)))
- (#{:repl :serve} (:mode config)))
- (.isFile (io/file "resources/public/index.html"))
- (not (fw-util/dir-on-classpath? "resources")))
- (log/warn (ansip/format-str
- [:yellow "A \"resources/public/index.html\" exists but the \"resources\" directory is not on the classpath\n"
- " the default server will not be able to find your index.html"])))
- cfg)
-
-(defn config-pre-post-hooks [{:keys [::config] :as cfg}]
- (cond-> cfg
- (not-empty (:pre-build-hooks config))
- (update ::pre-build-hooks concat
- (doall
- (keep (partial resolve-fn-var "pre-build-hook-fn")
- (:pre-build-hooks config))))
- (not-empty (:post-build-hooks config))
- (update ::post-build-hooks concat
- (doall
- (keep (partial resolve-fn-var "post-build-hook-fn")
- (:post-build-hooks config))))))
-
-(defn alter-output-to [nm {:keys [output-to output-dir] :as opts}]
- (cond
- output-to
- (let [f (io/file output-to)
- fname (string/replace (.getName f) #"\.js$" "")]
- (assoc opts :output-to
- (str (io/file (.getParent f) (str fname "-" nm ".js")))))
- output-dir
- (assoc opts :output-to (str (io/file output-dir (str "main-" nm ".js"))))
- :else nil))
-
-(defn merge-extra-key-with [m extra-m f k]
- (if-let [value (get extra-m k)]
- (let [act-key (keyword (string/replace (name k) #"^extra-" "")) ]
- (update m act-key f value))
- m))
-
-(defn merge-extra-cljs-options
- "Merges ClojureScript options that are collections if they are
- prepended with :extra."
- [opts extra-opts]
- (let [coll-keys [:extra-foreign-libs
- :extra-externs
- :extra-preloads
- :extra-closure-extra-annotations]
- map-keys [:extra-modules
- :extra-npm-deps
- :extra-closure-defines
- :extra-closure-warnings]]
- (as-> (merge opts extra-opts) opts
- (apply dissoc opts
- (concat coll-keys map-keys
- [:extra-warnings]))
- (merge-extra-key-with opts extra-opts (fn [x y]
- (merge (if (boolean? x) {} x) y)) :extra-warnings)
- (reduce #(merge-extra-key-with %1 extra-opts (comp vec concat) %2) opts coll-keys)
- (reduce #(merge-extra-key-with %1 extra-opts merge %2) opts map-keys))))
-
-(defn extra-main-options [nm em-options options]
- ;; need to remove modules so that we get a funcitioning independent main endpoint
- (merge-extra-cljs-options
- (dissoc (alter-output-to (name nm) options) :modules)
- em-options))
-
-(defn- compile-resource-helper [res opts]
- (let [parts (-> res
- (string/replace #"\.cljs$" ".js")
- (string/split #"/"))]
- (when-not (.exists (apply io/file (:output-dir opts) parts))
- (cljs.closure/-compile (io/resource res)
- (assoc opts
- :output-file
- (str (apply io/file parts)))))))
-
-(defn extra-main-fn [nm em-options options]
- ;; TODO modules??
- (let [opts (extra-main-options nm em-options options)]
- (fn [_]
- (log/info (format "Outputting main file: %s" (:output-to opts "main.js")))
- (let [switch-to-node? (and (= :nodejs (:target em-options)) (not= :nodejs (:target options)))
- ;; fix asset-path for nodejs to output-dir if the original options are not nodejs
- ;; and if the asset path isn't set in the extra-main options
- opts (if (and switch-to-node? (not (:asset-path em-options)))
- (assoc opts :asset-path (:output-dir opts))
- opts)]
- (cljs.closure/output-main-file
- (cljs.closure/add-implicit-options
- opts))
- (when switch-to-node?
- (compile-resource-helper "cljs/nodejs.cljs" opts)
- (compile-resource-helper "cljs/nodejscli.cljs" opts)
- (spit (io/file (:output-dir opts) "cljs_deps.js")
- (str "goog.addDependency(\"../cljs/nodejs.js\", ['cljs.nodejs'], []);\n"
- "goog.addDependency(\"../cljs/nodejscli.js\", ['cljs.nodejscli'], ['goog.object', 'cljs.nodejs']);\n")
- :append true)
- (cljs.closure/output-bootstrap opts))))))
-
-(defn config-extra-mains [{:keys [::config options] :as cfg}]
- (let [{:keys [extra-main-files]} config]
- (if (and (not-empty extra-main-files)
- (= :none (:optimizations options :none)))
- (update cfg ::post-build-hooks
- concat (map (fn [[k v]]
- (extra-main-fn k v options))
- extra-main-files))
- cfg)))
-
-(defn expand-build-inputs [{:keys [watch-dirs build-inputs] :as config} {:keys [main] :as options}]
- (doall
- (distinct
- (mapcat
- (fn [x]
+ (cond-> %
+ (:watch options) (conj (:watch options))
+ ns-watch-dir (conj ns-watch-dir)))))))
+
+ (defn- config-ensure-watch-dirs-on-classpath [{:keys [::config] :as cfg}]
+ (doseq [src-dir (:watch-dirs config)]
+ (when-not (fw-util/dir-on-current-classpath? src-dir)
+ (log/warn (ansip/format-str
+ [:yellow
+ "The watch directory "
+ (pr-str (str src-dir))
+ " is not on the classpath! A watch directory is must "
+ "on the classpath and point to the root directory of your namespace "
+ "source tree. A general all encompassing watch directory will not work."]))
+ (when (get config :helpful-classpaths true)
+ (add-classpath! src-dir)
+ (warn-that-dir-not-on-classpath :source src-dir)))) cfg)
+
+ ;; needs local config
+ (defn figwheel-mode? [{:keys [::config options]}]
+ (and (:figwheel-core config true)
+ (and (#{:repl :serve} (:mode config))
+ (not (::build-once config))
+ (not-empty (:watch-dirs config)))
+ (= :none (:optimizations options :none))))
+
+ (defn repl-connection? [{:keys [::config options] :as cfg}]
+ (or (and (#{:repl :serve} (:mode config))
+ (not (::build-once config))
+ (= :none (:optimizations options :none)))
+ (figwheel-mode? cfg)))
+
+ ;; TODO this is a no-op right now
+ (defn prep-client-config [config]
+ (let [cl-config (select-keys config [])]
+ cl-config))
+
+ ;; targets options needs local config
+ (defn- config-figwheel-mode? [{:keys [::config options] :as cfg}]
+ (cond-> cfg
+ ;; check for a main??
+ (figwheel-mode? cfg)
+ (->
+ (update ::initializers (fnil conj []) #(figwheel.core/start*))
+ (update-in [:options :preloads]
+ (fn [p]
+ (vec (distinct
+ (concat p '[figwheel.core figwheel.main]))))))
+ (false? (:heads-up-display config))
+ (update-in [:options :closure-defines] assoc 'figwheel.core/heads-up-display false)
+ (true? (:load-warninged-code config))
+ (update-in [:options :closure-defines] assoc 'figwheel.core/load-warninged-code true)))
+
+ (defn- modules-output-to [{:keys [options ::config ::build] :as cfg}]
+ (if (not-empty (:modules options))
+ (update-in
+ cfg [:options :modules]
+ #(->> %
+ (map (fn [[k v]]
+ (if-not (:output-to v)
+ [k (assoc v :output-to
+ (string/replace
+ (default-output-to cfg)
+ "main.js" ;; brittle
+ (str (name k) ".js")))]
+ [k v])))
+ (into {})))
+ cfg))
+
+ ;; targets options
+ ;; TODO needs to consider case where one or the other is specified???
+ (defn- config-default-dirs [{:keys [options ::config ::build] :as cfg}]
+ (cond-> cfg
+ (and (nil? (:output-to options)) (not (:modules options)))
+ (assoc-in [:options :output-to] (default-output-to cfg))
+ (:modules options)
+ modules-output-to
+ (nil? (:output-dir options))
+ (assoc-in [:options :output-dir] (default-output-dir cfg))))
+
+ (defn figure-default-asset-path [{:keys [figwheel-options options ::config ::build] :as cfg}]
+ (if (= :nodejs (:target options))
+ (:output-dir options)
+ (let [{:keys [output-dir]} options]
+ ;; TODO could discover the resource root if there is only one
+ ;; or if ONLY static file serving can probably do something with that
+ ;; as well
+ ;; UNTIL THEN if you have configured your static resources no default asset-path
+ (when-not (contains? (:ring-stack-options figwheel-options) :static)
+ (let [parts (fw-util/relativized-path-parts (or output-dir
+ (default-output-dir cfg)))]
+ (when-let [asset-path
+ (->> parts
+ (split-with (complement #{"public"}))
+ last
+ rest
+ not-empty)]
+ (str "/" (string/join "/" asset-path))))))))
+
+ ;; targets options
+ (defn- config-default-asset-path [{:keys [options] :as cfg}]
+ (cond-> cfg
+ (nil? (:asset-path options))
+ (assoc-in [:options :asset-path] (figure-default-asset-path cfg))))
+
+ ;; targets options
+ (defn- config-default-aot-cache-false [{:keys [options] :as cfg}]
+ (cond-> cfg
+ (not (contains? options :aot-cache))
+ (assoc-in [:options :aot-cache] false)))
+
+ (defn config-clean [cfg]
+ (update cfg :options dissoc :watch))
+
+ ;; TODO create connection
+
+ (let [localhost (promise)]
+ ;; this call takes a very long time to complete so lets get in in parallel
+ (doto (Thread. #(deliver localhost (try (java.net.InetAddress/getLocalHost)
+ (catch Throwable e
+ nil))))
+ (.setDaemon true)
+ (.start))
+ (defn fill-connect-url-template [url host server-port]
+ (cond-> url
+ (.contains url "[[config-hostname]]")
+ (string/replace "[[config-hostname]]" (or host "localhost"))
+
+ (.contains url "[[server-hostname]]")
+ (string/replace "[[server-hostname]]" (or (some-> @localhost
+ .getHostName)
+ "localhost"))
+
+ (.contains url "[[server-ip]]")
+ (string/replace "[[server-ip]]" (or (some-> @localhost
+ .getHostAddress)
+ "127.0.0.1"))
+
+ (.contains url "[[server-port]]")
+ (string/replace "[[server-port]]" (str server-port)))))
+
+ (defn add-to-query [uri query-map]
+ (let [[pre query] (string/split uri #"\?")]
+ (str pre
+ (when (or query (not-empty query-map))
+ (str "?"
+ (string/join "&"
+ (map (fn [[k v]]
+ (str (name k)
+ "="
+ (java.net.URLEncoder/encode (str v) "UTF-8")))
+ query-map))
+ (when (not (string/blank? query))
+ (str "&" query)))))))
+
+ #_(add-to-query "ws://localhost:9500/figwheel-connect?hey=5" {:ab 'ab})
+
+ (defn config-connect-url [{:keys [::config repl-env-options] :as cfg} connect-id]
+ (let [port (get-in config [:ring-server-options :port] figwheel.repl/default-port)
+ host (get-in config [:ring-server-options :host] "localhost")
+ connect-url
+ (fill-connect-url-template
+ (:connect-url config "ws://[[config-hostname]]:[[server-port]]/figwheel-connect")
+ host
+ port)]
+ (add-to-query connect-url connect-id)))
+
+ #_(config-connect-url {} {:abb 1})
+
+ (defn config-repl-connect [{:keys [::config options ::build] :as cfg}]
+ (let [connect-id (:connect-id config
+ (cond-> {:fwprocess process-unique}
+ (:id build) (assoc :fwbuild (:id build))))
+ conn-url (config-connect-url cfg connect-id)
+ conn? (repl-connection? cfg)]
+ (cond-> cfg
+ conn?
+ (update-in [:options :closure-defines] assoc 'figwheel.repl/connect-url conn-url)
+ conn?
+ (update-in [:options :preloads]
+ (fn [p]
+ (vec (distinct
+ (concat p '[figwheel.repl.preload])))))
+ conn?
+ (update-in [:options :repl-requires] into '[[cljs.repl :refer-macros [source doc find-doc apropos dir pst]]
+ [cljs.pprint :refer [pprint] :refer-macros [pp]]
+ [figwheel.main :refer-macros [stop-builds start-builds build-once reset clean status]]
+ [figwheel.repl :refer-macros [conns focus]]])
+ (and conn? (:client-print-to config))
+ (update-in [:options :closure-defines] assoc
+ 'figwheel.repl/print-output
+ (string/join "," (distinct (map name (:client-print-to config)))))
+ (and conn? (:client-log-level config))
+ (update-in [:options :closure-defines] assoc
+ 'figwheel.repl/client-log-level
+ (name (:client-log-level config)))
+ (and conn? (not-empty (:watch-dirs config)))
+ (update-in [:repl-options :analyze-path] (comp vec concat) (:watch-dirs config))
+ (and conn? (not-empty connect-id))
+ (assoc-in [:repl-env-options :connection-filter]
+ (let [kys (keys connect-id)]
+ (fn [{:keys [query]}]
+ (if (not (:fwprocess query))
+ (= (:fwbuild query)
+ (:fwbuild connect-id))
+ (= (select-keys query kys)
+ connect-id))))))))
+
+ (defn config-cljs-devtools [{:keys [::config options] :as cfg}]
+ (if (and
+ (nil? (:target options))
+ (= :none (:optimizations options :none))
+ (:cljs-devtools config true)
+ (try (bapi/ns->location 'devtools.preload) (catch Throwable t false)))
+ (update-in cfg
+ [:options :preloads]
+ (fn [p]
+ (vec (distinct
+ (concat p '[devtools.preload])))))
+ cfg))
+
+ (defn config-open-file-command [{:keys [::config options] :as cfg}]
+ (if-let [setup (and (:open-file-command config)
+ (repl-connection? cfg)
+ (fw-util/require-resolve-var 'figwheel.main.editor/setup))]
+ (-> cfg
+ (update ::initializers (fnil conj []) #(setup (:open-file-command config)))
+ (update-in [:options :preloads]
+ (fn [p] (vec (distinct (conj p 'figwheel.main.editor))))))
+ cfg))
+
+ (defn config-eval-back [{:keys [::config options] :as cfg}]
+ (if-let [setup (and (repl-connection? cfg)
+ (fw-util/require-resolve-var 'figwheel.main.evalback/setup))]
+ (-> cfg
+ (update ::initializers (fnil conj []) #(setup))
+ (update-in [:options :preloads]
+ (fn [p] (vec (distinct (concat p '[figwheel.main.evalback #_figwheel.main.testing]))))))
+ cfg))
+
+ (defn watch-css [css-dirs]
+ (when-let [css-dirs (not-empty css-dirs)]
+ (when-let [start-css (fw-util/require-resolve-var 'figwheel.main.css-reload/start*)]
+ (start-css css-dirs))))
+
+ (defn config-watch-css [{:keys [::config options] :as cfg}]
+ (cond-> cfg
+ (and (not-empty (:css-dirs config))
+ (repl-connection? cfg))
+ (->
+ (update ::initializers (fnil conj []) #(watch-css (:css-dirs config)))
+ (update-in [:options :preloads]
+ (fn [p] (vec (distinct (conj p 'figwheel.main.css-reload))))))))
+
+ (defn get-repl-options [{:keys [options args inits repl-options] :as cfg}]
+ (assoc (merge (dissoc options :main)
+ repl-options)
+ :inits
+ (into
+ [{:type :init-forms
+ :forms (when-not (empty? args)
+ [`(set! *command-line-args* (list ~@args))])}]
+ inits)))
+
+ (defn get-repl-env-options [{:keys [repl-env-options ::config options] :as cfg}]
+ (let [repl-options (get-repl-options cfg)]
+ (merge
+ (select-keys config
+ [:ring-server
+ :ring-server-options
+ :ring-stack
+ :ring-stack-options
+ :ring-handler
+ :cljsjs-resources
+ :launch-node
+ :inspect-node
+ :node-command
+ :broadcast
+ :open-url
+ :launch-js
+ :repl-eval-timeout])
+ repl-env-options ;; from command line
+ (select-keys options [:output-to :output-dir :target]))))
+
+ (defn config-finalize-repl-options [cfg]
+ (let [repl-options (get-repl-options cfg)
+ repl-env-options (get-repl-env-options cfg)]
+ (assoc cfg
+ :repl-options repl-options
+ :repl-env-options repl-env-options)))
+
+ (defn config-set-log-level! [{:keys [::config] :as cfg}]
+ (when-let [log-level (:log-level config)]
+ (log/set-level log-level))
+ cfg)
+
+ (defn config-ansi-color-output! [{:keys [::config] :as cfg}]
+ (when (some? (:ansi-color-output config))
+ (alter-var-root #'ansip/*use-color* (fn [_] (:ansi-color-output config))))
+ cfg)
+
+ (defn config-log-syntax-error-style! [{:keys [::config] :as cfg}]
+ (when (some? (:log-syntax-error-style config))
+ (alter-var-root #'log/*syntax-error-style* (fn [_] (:log-syntax-error-style config))))
+ cfg)
+
+ (defn- config-warn-resource-directory-not-on-classpath [{:keys [::config options] :as cfg}]
+ ;; this could check for other directories than resources
+ ;; but this is mainly to help newcomers
+ (when (and (nil? (:target options))
+ (or (and (::build-once config)
+ (#{:serve} (:mode config)))
+ (#{:repl :serve} (:mode config)))
+ (.isFile (io/file "resources/public/index.html"))
+ (not (fw-util/dir-on-classpath? "resources")))
+ (log/warn (ansip/format-str
+ [:yellow "A \"resources/public/index.html\" exists but the \"resources\" directory is not on the classpath\n"
+ " the default server will not be able to find your index.html"])))
+ cfg)
+
+ (defn config-pre-post-hooks [{:keys [::config] :as cfg}]
+ (cond-> cfg
+ (not-empty (:pre-build-hooks config))
+ (update ::pre-build-hooks concat
+ (doall
+ (keep (partial resolve-fn-var "pre-build-hook-fn")
+ (:pre-build-hooks config))))
+ (not-empty (:post-build-hooks config))
+ (update ::post-build-hooks concat
+ (doall
+ (keep (partial resolve-fn-var "post-build-hook-fn")
+ (:post-build-hooks config))))))
+
+ (defn alter-output-to [nm {:keys [output-to output-dir] :as opts}]
(cond
- (= x :main)
- (when-let [{:keys [uri]} (and main (fw-util/ns->location (symbol main)))]
- [uri])
- (symbol? x)
- (when-let [{:keys [uri]} (fw-util/ns->location x)]
- [uri])
- (= x :watch-dirs)
- watch-dirs
- :else [x]))
- build-inputs))))
-
-(defn config->inputs [{:keys [watch-dirs mode build-inputs ::build-once] :as config} options]
- (if (not-empty build-inputs)
- (expand-build-inputs config options)
- (if-let [inputs (and (not build-once)
- (= :none (:optimizations options :none))
- (not-empty watch-dirs))]
- inputs
- (let [source (when (:main options)
- (:uri (fw-util/ns->location (symbol (:main options)))))]
- (cond
- source [source]
- (not-empty watch-dirs) watch-dirs)))))
-
-(defn config-build-inputs [{:keys [options ::config] :as cfg}]
- (if-let [inputs (not-empty (config->inputs config options))]
- (update-in cfg [::config ::build-inputs] (comp vec distinct concat) inputs)
- cfg))
-
-(defn config-compile-is-build-once [{:keys [args] :as cfg}]
- (cond-> cfg
- (and (= (set (keys cfg)) #{:args :ns})
- (not (#{"-r" "--repl" "-s" "--serve"} (first args))))
- (assoc-in [::config ::build-once] true)))
-
-(defn update-config [cfg]
- (->> cfg
- config-compile-is-build-once
- config-figwheel-main-edn
- config-merge-current-build-conf
- config-ansi-color-output!
- config-set-log-level!
- config-log-syntax-error-style!
- config-repl-serve?
- config-main-ns
- config-main-source-path-on-classpath
-
- config-update-watch-dirs
- config-ensure-watch-dirs-on-classpath
- config-figwheel-mode?
- config-default-dirs
- config-default-asset-path
- config-default-aot-cache-false
- npm/config
- testing/plugin
- config-pre-post-hooks
- config-repl-connect
- config-cljs-devtools
- config-open-file-command
- #_config-eval-back
- config-watch-css
- config-finalize-repl-options
- config-extra-mains
- config-build-inputs
- config-clean
- config-warn-resource-directory-not-on-classpath))
-
-;; ----------------------------------------------------------------------------
-;; Main action
-;; ----------------------------------------------------------------------------
-
-(defn build [{:keys [watch-dirs mode ::build-once ::build-inputs] :as config}
- options cenv]
- (let [id (:id (::build *config*) "unknown")]
- (assert (not-empty build-inputs) "Should have at least one build input!")
- (build-cljs id (apply bapi/inputs build-inputs) options cenv)
- ;; are we watching?
- (when-let [paths (and (not build-once)
- (= :none (:optimizations options :none))
- (not-empty watch-dirs))]
- (watch-build id paths build-inputs options cenv (config->reload-config config)))))
-
-(defn log-server-start [repl-env]
- (let [host (get-in repl-env [:ring-server-options :host] "localhost")
- port (get-in repl-env [:ring-server-options :port] figwheel.repl/default-port)
- scheme (if (get-in repl-env [:ring-server-options :ssl?])
- "https" "http")]
- (log/info (str "Starting Server at " scheme "://" host ":" port ))))
-
-(defn start-file-logger []
- (when-let [log-fname (and (bound? #'*config*) (get-in *config* [::config :log-file]))]
- (log/info "Redirecting log ouput to file:" log-fname)
- (io/make-parents log-fname)
- (log/switch-to-file-handler! log-fname)))
-
-;; ------------------------------
-;; REPL
-;; ------------------------------
-
-(defn repl-api-docs []
- (let [dvars (filter (comp :cljs-repl-api meta) (vals (ns-publics 'figwheel.main)))]
- (string/join
- "\n"
- (map (fn [{:keys [ns name arglists doc]}]
- (str "--------------------------------------------------------------------------------\n"
- "(" ns "/" name
- (when-let [args (not-empty (first arglists))]
- (str " " (pr-str args)))
- ")\n " doc))
- (map meta dvars)))))
-
-#_(println (repl-api-docs))
-
-(defn bound-var? [sym]
- (when-let [v (resolve sym)]
- (thread-bound? v)))
-
-(defn in-nrepl? []
- (or
- (bound-var? 'nrepl.middleware.interruptible-eval/*msg*)
- (bound-var? 'clojure.tools.nrepl.middleware.interruptible-eval/*msg*)))
-
-(defn nrepl-repl [repl-env repl-options]
- (if-let [piggie-repl (or (and (bound-var? 'cider.piggieback/*cljs-repl-env*)
- (resolve 'cider.piggieback/cljs-repl))
- (and (bound-var? 'cemerick.piggieback/*cljs-repl-env*)
- (resolve 'cemerick.piggieback/cljs-repl)))]
- (apply piggie-repl repl-env (mapcat identity repl-options))
- (throw (ex-info "Failed to launch Figwheel CLJS REPL: nREPL connection found but unable to load piggieback.
+ output-to
+ (let [f (io/file output-to)
+ fname (string/replace (.getName f) #"\.js$" "")]
+ (assoc opts :output-to
+ (str (io/file (.getParent f) (str fname "-" nm ".js")))))
+ output-dir
+ (assoc opts :output-to (str (io/file output-dir (str "main-" nm ".js"))))
+ :else nil))
+
+ (defn merge-extra-key-with [m extra-m f k]
+ (if-let [value (get extra-m k)]
+ (let [act-key (keyword (string/replace (name k) #"^extra-" "")) ]
+ (update m act-key f value))
+ m))
+
+ (defn merge-extra-cljs-options
+ "Merges ClojureScript options that are collections if they are
+ prepended with :extra."
+ [opts extra-opts]
+ (let [coll-keys [:extra-foreign-libs
+ :extra-externs
+ :extra-preloads
+ :extra-closure-extra-annotations]
+ map-keys [:extra-modules
+ :extra-npm-deps
+ :extra-closure-defines
+ :extra-closure-warnings]]
+ (as-> (merge opts extra-opts) opts
+ (apply dissoc opts
+ (concat coll-keys map-keys
+ [:extra-warnings]))
+ (merge-extra-key-with opts extra-opts (fn [x y]
+ (merge (if (boolean? x) {} x) y)) :extra-warnings)
+ (reduce #(merge-extra-key-with %1 extra-opts (comp vec concat) %2) opts coll-keys)
+ (reduce #(merge-extra-key-with %1 extra-opts merge %2) opts map-keys))))
+
+ (defn extra-main-options [nm em-options options]
+ ;; need to remove modules so that we get a funcitioning independent main endpoint
+ (merge-extra-cljs-options
+ (dissoc (alter-output-to (name nm) options) :modules)
+ em-options))
+
+ (defn- compile-resource-helper [res opts]
+ (let [parts (-> res
+ (string/replace #"\.cljs$" ".js")
+ (string/split #"/"))]
+ (when-not (.exists (apply io/file (:output-dir opts) parts))
+ (cljs.closure/-compile (io/resource res)
+ (assoc opts
+ :output-file
+ (str (apply io/file parts)))))))
+
+ (defn extra-main-fn [nm em-options options]
+ ;; TODO modules??
+ (let [opts (extra-main-options nm em-options options)]
+ (fn [_]
+ (log/info (format "Outputting main file: %s" (:output-to opts "main.js")))
+ (let [switch-to-node? (and (= :nodejs (:target em-options)) (not= :nodejs (:target options)))
+ ;; fix asset-path for nodejs to output-dir if the original options are not nodejs
+ ;; and if the asset path isn't set in the extra-main options
+ opts (if (and switch-to-node? (not (:asset-path em-options)))
+ (assoc opts :asset-path (:output-dir opts))
+ opts)]
+ (cljs.closure/output-main-file
+ (cljs.closure/add-implicit-options
+ opts))
+ (when switch-to-node?
+ (compile-resource-helper "cljs/nodejs.cljs" opts)
+ (compile-resource-helper "cljs/nodejscli.cljs" opts)
+ (spit (io/file (:output-dir opts) "cljs_deps.js")
+ (str "goog.addDependency(\"../cljs/nodejs.js\", ['cljs.nodejs'], []);\n"
+ "goog.addDependency(\"../cljs/nodejscli.js\", ['cljs.nodejscli'], ['goog.object', 'cljs.nodejs']);\n")
+ :append true)
+ (cljs.closure/output-bootstrap opts))))))
+
+ (defn config-extra-mains [{:keys [::config options] :as cfg}]
+ (let [{:keys [extra-main-files]} config]
+ (if (and (not-empty extra-main-files)
+ (= :none (:optimizations options :none)))
+ (update cfg ::post-build-hooks
+ concat (map (fn [[k v]]
+ (extra-main-fn k v options))
+ extra-main-files))
+ cfg)))
+
+ (defn expand-build-inputs [{:keys [watch-dirs build-inputs] :as config} {:keys [main] :as options}]
+ (doall
+ (distinct
+ (mapcat
+ (fn [x]
+ (cond
+ (= x :main)
+ (when-let [{:keys [uri]} (and main (fw-util/ns->location (symbol main)))]
+ [uri])
+ (symbol? x)
+ (when-let [{:keys [uri]} (fw-util/ns->location x)]
+ [uri])
+ (= x :watch-dirs)
+ watch-dirs
+ :else [x]))
+ build-inputs))))
+
+ (defn config->inputs [{:keys [watch-dirs mode build-inputs ::build-once] :as config} options]
+ (if (not-empty build-inputs)
+ (expand-build-inputs config options)
+ (if-let [inputs (and (not build-once)
+ (= :none (:optimizations options :none))
+ (not-empty watch-dirs))]
+ inputs
+ (let [source (when (:main options)
+ (:uri (fw-util/ns->location (symbol (:main options)))))]
+ (cond
+ source [source]
+ (not-empty watch-dirs) watch-dirs)))))
+
+ (defn config-build-inputs [{:keys [options ::config] :as cfg}]
+ (if-let [inputs (not-empty (config->inputs config options))]
+ (update-in cfg [::config ::build-inputs] (comp vec distinct concat) inputs)
+ cfg))
+
+ (defn config-compile-is-build-once [{:keys [args] :as cfg}]
+ (cond-> cfg
+ (and (= (set (keys cfg)) #{:args :ns})
+ (not (#{"-r" "--repl" "-s" "--serve"} (first args))))
+ (assoc-in [::config ::build-once] true)))
+
+ (defn update-config [cfg]
+ (->> cfg
+ config-compile-is-build-once
+ config-figwheel-main-edn
+ config-merge-current-build-conf
+ config-ansi-color-output!
+ config-set-log-level!
+ config-log-syntax-error-style!
+ config-repl-serve?
+ config-main-ns
+ config-main-source-path-on-classpath
+
+ config-update-watch-dirs
+ config-ensure-watch-dirs-on-classpath
+ config-figwheel-mode?
+ config-default-dirs
+ config-default-asset-path
+ config-default-aot-cache-false
+ npm/config
+ testing/plugin
+ config-pre-post-hooks
+ config-repl-connect
+ config-cljs-devtools
+ config-open-file-command
+ #_config-eval-back
+ config-watch-css
+ config-finalize-repl-options
+ config-extra-mains
+ config-build-inputs
+ config-clean
+ config-warn-resource-directory-not-on-classpath))
+
+ ;; ----------------------------------------------------------------------------
+ ;; Main action
+ ;; ----------------------------------------------------------------------------
+
+ (defn build [{:keys [watch-dirs mode ::build-once ::build-inputs] :as config}
+ options cenv]
+ (let [id (:id (::build *config*) "unknown")]
+ (assert (not-empty build-inputs) "Should have at least one build input!")
+ (build-cljs id (apply bapi/inputs build-inputs) options cenv)
+ ;; are we watching?
+ (when-let [paths (and (not build-once)
+ (= :none (:optimizations options :none))
+ (not-empty watch-dirs))]
+ (watch-build id paths build-inputs options cenv (config->reload-config config)))))
+
+ (defn log-server-start [repl-env]
+ (let [host (get-in repl-env [:ring-server-options :host] "localhost")
+ port (get-in repl-env [:ring-server-options :port] figwheel.repl/default-port)
+ scheme (if (get-in repl-env [:ring-server-options :ssl?])
+ "https" "http")]
+ (log/info (str "Starting Server at " scheme "://" host ":" port ))))
+
+ (defn start-file-logger []
+ (when-let [log-fname (and (bound? #'*config*) (get-in *config* [::config :log-file]))]
+ (log/info "Redirecting log ouput to file:" log-fname)
+ (io/make-parents log-fname)
+ (log/switch-to-file-handler! log-fname)))
+
+ ;; ------------------------------
+ ;; REPL
+ ;; ------------------------------
+
+ (defn repl-api-docs []
+ (let [dvars (filter (comp :cljs-repl-api meta) (vals (ns-publics 'figwheel.main)))]
+ (string/join
+ "\n"
+ (map (fn [{:keys [ns name arglists doc]}]
+ (str "--------------------------------------------------------------------------------\n"
+ "(" ns "/" name
+ (when-let [args (not-empty (first arglists))]
+ (str " " (pr-str args)))
+ ")\n " doc))
+ (map meta dvars)))))
+
+ #_(println (repl-api-docs))
+
+ (defn bound-var? [sym]
+ (when-let [v (resolve sym)]
+ (thread-bound? v)))
+
+ (defn in-nrepl? []
+ (or
+ (bound-var? 'nrepl.middleware.interruptible-eval/*msg*)
+ (bound-var? 'clojure.tools.nrepl.middleware.interruptible-eval/*msg*)))
+
+ (defn nrepl-repl [repl-env repl-options]
+ (if-let [piggie-repl (or (and (bound-var? 'cider.piggieback/*cljs-repl-env*)
+ (resolve 'cider.piggieback/cljs-repl))
+ (and (bound-var? 'cemerick.piggieback/*cljs-repl-env*)
+ (resolve 'cemerick.piggieback/cljs-repl)))]
+ (apply piggie-repl repl-env (mapcat identity repl-options))
+ (throw (ex-info "Failed to launch Figwheel CLJS REPL: nREPL connection found but unable to load piggieback.
This is commonly caused by
A) not providing piggieback as a dependency and/or
B) not adding piggieback middleware into your nrepl middleware chain.
@@ -1508,32 +1508,32 @@ Please see the documentation for piggieback here https://github.com/clojure-emac
Note: Cider will inject this config into your project.clj.
This can cause confusion when your are not using Cider."
- {::error :no-cljs-nrepl-middleware}))))
-
-(defn repl-caught [err repl-env repl-options]
- (let [root-source-info (some-> err ex-data :root-source-info)]
- (if (and (instance? clojure.lang.IExceptionInfo err)
- (#{:js-eval-error :js-eval-exception} (:type (ex-data err))))
- (try
- (cljs.repl/repl-caught err repl-env repl-options)
- (catch Throwable e
- (let [{:keys [value stacktrace] :as data} (ex-data err)]
- (when value
- (println value))
- (when stacktrace
- (println stacktrace))
- (log/debug (with-out-str (pprint data))))))
- (let [except-data (fig-ex/add-excerpt (fig-ex/parse-exception err))]
- ;; TODO strange ANSI color error when printing this inside rebel-readline
- (println (binding [ansip/*use-color* (if (resolve 'rebel-readline.cljs.repl/repl*)
- false
- ansip/*use-color*)]
- (ansip/format-str (log/format-ex except-data))))
- (log/debug (with-out-str (clojure.pprint/pprint (Throwable->map err))))
- (flush)))))
-
-(def repl-header
- (str "Figwheel Main Controls:
+ {::error :no-cljs-nrepl-middleware}))))
+
+ (defn repl-caught [err repl-env repl-options]
+ (let [root-source-info (some-> err ex-data :root-source-info)]
+ (if (and (instance? clojure.lang.IExceptionInfo err)
+ (#{:js-eval-error :js-eval-exception} (:type (ex-data err))))
+ (try
+ (cljs.repl/repl-caught err repl-env repl-options)
+ (catch Throwable e
+ (let [{:keys [value stacktrace] :as data} (ex-data err)]
+ (when value
+ (println value))
+ (when stacktrace
+ (println stacktrace))
+ (log/debug (with-out-str (pprint data))))))
+ (let [except-data (fig-ex/add-excerpt (fig-ex/parse-exception err))]
+ ;; TODO strange ANSI color error when printing this inside rebel-readline
+ (println (binding [ansip/*use-color* (if (resolve 'rebel-readline.cljs.repl/repl*)
+ false
+ ansip/*use-color*)]
+ (ansip/format-str (log/format-ex except-data))))
+ (log/debug (with-out-str (clojure.pprint/pprint (Throwable->map err))))
+ (flush)))))
+
+ (def repl-header
+ (str "Figwheel Main Controls:
(figwheel.main/stop-builds id ...) ;; stops Figwheel autobuilder for ids
(figwheel.main/start-builds id ...) ;; starts autobuilder focused on ids
(figwheel.main/reset) ;; stops, cleans, reloads config, and starts autobuilder
@@ -1548,678 +1548,678 @@ In the cljs.user ns, controls can be called without ns ie. (conns) instead of (f
Exit: :cljs/quit
Results: Stored in vars *1, *2, *3, *e holds last exception object"))
-(defn repl [repl-env repl-options]
- (binding [cljs.analyzer/*cljs-warning-handlers*
- (conj (remove #{cljs.analyzer/default-warning-handler}
- cljs.analyzer/*cljs-warning-handlers*)
- (fn [warning-type env extra]
- (when (get cljs.analyzer/*cljs-warnings* warning-type)
- ;; warnings happen during compile so we must
- ;; output to *err* but when rebel readline is
- ;; available we will use the the root value of
- ;; out which is bound to a special printer this
- ;; is a bit tricky, its best just to handle
- ;; *err* correctly in rebel-readline
- (binding [*out*
- (if (some-> (resolve 'rebel-readline.jline-api/*line-reader*)
- deref)
- (.getRawRoot #'*out*)
- *err*)]
- (->> {:warning-type warning-type
- :env env
- :extra extra
- :path ana/*cljs-file*}
- figwheel.core/warning-info
- (fig-ex/root-source->file-excerpt (:root-source-info env))
- log/format-ex
- ansip/format-str
- string/trim-newline
- println)
- (flush)))))]
- (let [repl-options (-> repl-options
- (assoc :caught (:caught repl-options repl-caught)))]
- (println (ansip/format-str
- [:bright (format "Prompt will show when REPL connects to evaluation environment (i.e. %s)"
- (if (= :nodejs (:target repl-options))
- "Node"
- "a REPL hosting webpage"))]))
- (println repl-header)
-
- (if (in-nrepl?)
- (nrepl-repl repl-env repl-options)
- (let [repl-fn (or (when-not (false? (:rebel-readline (::config *config*)))
- (fw-util/require-resolve-var 'rebel-readline.cljs.repl/repl*))
- cljs.repl/repl*)]
- (try
- (repl-fn repl-env repl-options)
- (catch clojure.lang.ExceptionInfo e
- (if (-> e ex-data :type (= :rebel-readline.jline-api/bad-terminal))
- (do (println (.getMessage e))
- (cljs.repl/repl* repl-env repl-options))
- (throw e)))))))))
-
-(defn repl-action [repl-env repl-options]
- (log-server-start repl-env)
- (log/info "Starting REPL")
- ;; when we have a logging file start log here
- (start-file-logger)
- (repl repl-env repl-options))
-
-(defn serve [{:keys [repl-env repl-options eval-str join?]}]
- (cljs.repl/-setup repl-env repl-options)
- (when eval-str
- (cljs.repl/evaluate-form repl-env
- (assoc (ana/empty-env)
- :ns (ana/get-namespace ana/*cljs-ns*))
- "<cljs repl>"
- ;; todo allow opts to be added here
- (first (ana-api/forms-seq (StringReader. eval-str)))))
- (when-let [server (and join? @(:server repl-env))]
- (.join server)))
-
-(defn serve-action [{:keys [repl-env] :as options}]
- (log-server-start repl-env)
- (start-file-logger)
- (serve options))
-
-(defonce build-registry (atom {}))
-
-(defn register-build! [id build-info]
- (swap! build-registry assoc id (assoc build-info :id id)))
-
-(defn background-build [cfg {:keys [id config options]}]
- (let [{:keys [::build ::config repl-env-options repl-options] :as cfg}
- (-> (select-keys cfg [::start-figwheel-options])
- (assoc :options options
- ::build {:id id :config (assoc config :mode :serve)})
- update-config)
- repl-env (figwheel.repl/repl-env*
- (merge
- repl-env-options
- (select-keys cljs.repl/*repl-env* [:server])))
- cenv (cljs.env/default-compiler-env)
- repl-options (assoc repl-options :compiler-env cenv)
- build-inputs (::build-inputs config)]
- (when (empty? (:watch-dirs config))
- (log/failure (format "Can not watch build \"%s\" with no :watch-dirs" id)))
- (when (not-empty (:watch-dirs config))
- (log/info "Starting background autobuild - " (:id build))
- (binding [*config* cfg
- cljs.env/*compiler* cenv]
- (build-cljs (:id build) (apply bapi/inputs build-inputs) (:options cfg) cenv)
- (watch-build (:id build)
- (:watch-dirs config)
- build-inputs
- (:options cfg)
- cenv
- (config->reload-config config))
- (register-build!
- (get-in *config* [::build :id])
- {:repl-env repl-env
- :repl-options repl-options
- :config *config*
- :background true})
-
- (when (first (filter #{'figwheel.core} (:preloads (:options cfg))))
- ;; let's take parent repl-env and change the connection filter
- (binding [cljs.repl/*repl-env* repl-env
- figwheel.core/*config*
- (select-keys config [:hot-reload-cljs
- :broadcast-reload
- :reload-dependents])]
- (doseq [init-fn (::initializers cfg)] (init-fn))))))))
-
-(defn start-background-builds [{:keys [::background-builds] :as cfg}]
- (doseq [build background-builds]
- (background-build cfg build)))
-
-(defn validate-fix-target-classpath! [{:keys [::config ::build options]}]
- (when (and (nil? (:target options))
- ;; if build-once and not :serve -> don't validate fix classpath
- (not (and (::build-once config)
- (not (= (:mode config) :serve)))))
- ;; browsers need the target classpath to load files
- (when-not (contains? (:ring-stack-options config) :static)
- (when-let [output-to (:output-dir options (:output-to options))]
- (when-not (.isAbsolute (io/file output-to))
- (let [parts (fw-util/path-parts output-to)
- target-dir (first (split-with (complement #{"public"}) parts))]
- (when (some #{"public"} parts)
- (when-not (empty? target-dir)
- (let [target-dir (apply io/file target-dir)]
- (if (and (fw-util/dir-on-classpath? target-dir)
- (not (.exists target-dir)))
- (if (get config :helpful-classpaths true)
- (do
- (log/warn
- (ansip/format-str
- [:yellow
- "Making target directory "
- (pr-str (str target-dir))
- " and re-adding it to the classpath"
- " (this only needs to be done when the target directory doesn't exist)"]))
- (.mkdirs target-dir)
- (fw-util/add-classpath! (.toURL target-dir)))
- (log/warn (ansip/format-str
+ (defn repl [repl-env repl-options]
+ (binding [cljs.analyzer/*cljs-warning-handlers*
+ (conj (remove #{cljs.analyzer/default-warning-handler}
+ cljs.analyzer/*cljs-warning-handlers*)
+ (fn [warning-type env extra]
+ (when (get cljs.analyzer/*cljs-warnings* warning-type)
+ ;; warnings happen during compile so we must
+ ;; output to *err* but when rebel readline is
+ ;; available we will use the the root value of
+ ;; out which is bound to a special printer this
+ ;; is a bit tricky, its best just to handle
+ ;; *err* correctly in rebel-readline
+ (binding [*out*
+ (if (some-> (resolve 'rebel-readline.jline-api/*line-reader*)
+ deref)
+ (.getRawRoot #'*out*)
+ *err*)]
+ (->> {:warning-type warning-type
+ :env env
+ :extra extra
+ :path ana/*cljs-file*}
+ figwheel.core/warning-info
+ (fig-ex/root-source->file-excerpt (:root-source-info env))
+ log/format-ex
+ ansip/format-str
+ string/trim-newline
+ println)
+ (flush)))))]
+ (let [repl-options (-> repl-options
+ (assoc :caught (:caught repl-options repl-caught)))]
+ (println (ansip/format-str
+ [:bright (format "Prompt will show when REPL connects to evaluation environment (i.e. %s)"
+ (if (= :nodejs (:target repl-options))
+ "Node"
+ "a REPL hosting webpage"))]))
+ (println repl-header)
+
+ (if (in-nrepl?)
+ (nrepl-repl repl-env repl-options)
+ (let [repl-fn (or (when-not (false? (:rebel-readline (::config *config*)))
+ (fw-util/require-resolve-var 'rebel-readline.cljs.repl/repl*))
+ cljs.repl/repl*)]
+ (try
+ (repl-fn repl-env repl-options)
+ (catch clojure.lang.ExceptionInfo e
+ (if (-> e ex-data :type (= :rebel-readline.jline-api/bad-terminal))
+ (do (println (.getMessage e))
+ (cljs.repl/repl* repl-env repl-options))
+ (throw e)))))))))
+
+ (defn repl-action [repl-env repl-options]
+ (log-server-start repl-env)
+ (log/info "Starting REPL")
+ ;; when we have a logging file start log here
+ (start-file-logger)
+ (repl repl-env repl-options))
+
+ (defn serve [{:keys [repl-env repl-options eval-str join?]}]
+ (cljs.repl/-setup repl-env repl-options)
+ (when eval-str
+ (cljs.repl/evaluate-form repl-env
+ (assoc (ana/empty-env)
+ :ns (ana/get-namespace ana/*cljs-ns*))
+ "<cljs repl>"
+ ;; todo allow opts to be added here
+ (first (ana-api/forms-seq (StringReader. eval-str)))))
+ (when-let [server (and join? @(:server repl-env))]
+ (.join server)))
+
+ (defn serve-action [{:keys [repl-env] :as options}]
+ (log-server-start repl-env)
+ (start-file-logger)
+ (serve options))
+
+ (defonce build-registry (atom {}))
+
+ (defn register-build! [id build-info]
+ (swap! build-registry assoc id (assoc build-info :id id)))
+
+ (defn background-build [cfg {:keys [id config options]}]
+ (let [{:keys [::build ::config repl-env-options repl-options] :as cfg}
+ (-> (select-keys cfg [::start-figwheel-options])
+ (assoc :options options
+ ::build {:id id :config (assoc config :mode :serve)})
+ update-config)
+ repl-env (figwheel.repl/repl-env*
+ (merge
+ repl-env-options
+ (select-keys cljs.repl/*repl-env* [:server])))
+ cenv (cljs.env/default-compiler-env)
+ repl-options (assoc repl-options :compiler-env cenv)
+ build-inputs (::build-inputs config)]
+ (when (empty? (:watch-dirs config))
+ (log/failure (format "Can not watch build \"%s\" with no :watch-dirs" id)))
+ (when (not-empty (:watch-dirs config))
+ (log/info "Starting background autobuild - " (:id build))
+ (binding [*config* cfg
+ cljs.env/*compiler* cenv]
+ (build-cljs (:id build) (apply bapi/inputs build-inputs) (:options cfg) cenv)
+ (watch-build (:id build)
+ (:watch-dirs config)
+ build-inputs
+ (:options cfg)
+ cenv
+ (config->reload-config config))
+ (register-build!
+ (get-in *config* [::build :id])
+ {:repl-env repl-env
+ :repl-options repl-options
+ :config *config*
+ :background true})
+
+ (when (first (filter #{'figwheel.core} (:preloads (:options cfg))))
+ ;; let's take parent repl-env and change the connection filter
+ (binding [cljs.repl/*repl-env* repl-env
+ figwheel.core/*config*
+ (select-keys config [:hot-reload-cljs
+ :broadcast-reload
+ :reload-dependents])]
+ (doseq [init-fn (::initializers cfg)] (init-fn))))))))
+
+ (defn start-background-builds [{:keys [::background-builds] :as cfg}]
+ (doseq [build background-builds]
+ (background-build cfg build)))
+
+ (defn validate-fix-target-classpath! [{:keys [::config ::build options]}]
+ (when (and (nil? (:target options))
+ ;; if build-once and not :serve -> don't validate fix classpath
+ (not (and (::build-once config)
+ (not (= (:mode config) :serve)))))
+ ;; browsers need the target classpath to load files
+ (when-not (contains? (:ring-stack-options config) :static)
+ (when-let [output-to (:output-dir options (:output-to options))]
+ (when-not (.isAbsolute (io/file output-to))
+ (let [parts (fw-util/path-parts output-to)
+ target-dir (first (split-with (complement #{"public"}) parts))]
+ (when (some #{"public"} parts)
+ (when-not (empty? target-dir)
+ (let [target-dir (apply io/file target-dir)]
+ (if (and (fw-util/dir-on-classpath? target-dir)
+ (not (.exists target-dir)))
+ (if (get config :helpful-classpaths true)
+ (do
+ (log/warn
+ (ansip/format-str
[:yellow
- "Target directory "
+ "Making target directory "
(pr-str (str target-dir))
- " is on the classpath but doesn't exist. The figwheel "
- "server will not be able to find compiled assets."])))
- ;; quietly fix this situation??
-
- (when-not (fw-util/dir-on-classpath? target-dir)
- (if (get config :helpful-classpaths true)
- (do
- (.mkdirs target-dir)
- (add-classpath! target-dir)
- (warn-that-dir-not-on-classpath :target target-dir))
- (log/warn (ansip/format-str
- [:yellow
- "Target directory "
- (pr-str (str target-dir))
- " is not on the classpath! The figwheel "
- "server will not be able to find compiled assets."]))))))))))))))
-
-;; build-id situations
-;; - temp-dir build id doesn't matter
-;; - target directory build id
-;; (if unique would ensure clean main compile and run)
-;; when don't you want it to be unique
-;; when do you not want a clean compile when running main or repl?
-;; (when you are running it over and over again)
-;; for main we can use the main-ns for a build id
-;; - repl only
-;; - main only
-
-(defn default-main [repl-env-fn cfg]
- (let [cfg (if (should-add-temp-dir? cfg)
- (add-temp-dir cfg)
- cfg)
- cfg (if (get-in cfg [::build :id])
+ " and re-adding it to the classpath"
+ " (this only needs to be done when the target directory doesn't exist)"]))
+ (.mkdirs target-dir)
+ (fw-util/add-classpath! (.toURL target-dir)))
+ (log/warn (ansip/format-str
+ [:yellow
+ "Target directory "
+ (pr-str (str target-dir))
+ " is on the classpath but doesn't exist. The figwheel "
+ "server will not be able to find compiled assets."])))
+ ;; quietly fix this situation??
+
+ (when-not (fw-util/dir-on-classpath? target-dir)
+ (if (get config :helpful-classpaths true)
+ (do
+ (.mkdirs target-dir)
+ (add-classpath! target-dir)
+ (warn-that-dir-not-on-classpath :target target-dir))
+ (log/warn (ansip/format-str
+ [:yellow
+ "Target directory "
+ (pr-str (str target-dir))
+ " is not on the classpath! The figwheel "
+ "server will not be able to find compiled assets."]))))))))))))))
+
+ ;; build-id situations
+ ;; - temp-dir build id doesn't matter
+ ;; - target directory build id
+ ;; (if unique would ensure clean main compile and run)
+ ;; when don't you want it to be unique
+ ;; when do you not want a clean compile when running main or repl?
+ ;; (when you are running it over and over again)
+ ;; for main we can use the main-ns for a build id
+ ;; - repl only
+ ;; - main only
+
+ (defn default-main [repl-env-fn cfg]
+ (let [cfg (if (should-add-temp-dir? cfg)
+ (add-temp-dir cfg)
+ cfg)
+ cfg (if (get-in cfg [::build :id])
+ cfg
+ (assoc-in cfg [::build :id] "figwheel-main-option-build"))
+ output-to (get-in cfg [:options :output-to]
+ (default-output-to cfg))
+ main (:main cfg)
+ cfg (-> cfg
+ (assoc-in [:options :aot-cache] false)
+ (update :options #(assoc % :main
+ (or (some-> (:main cfg) symbol)
+ 'figwheel.repl.preload)))
+ (assoc-in [::config
+ :ring-stack-options
+ :figwheel.server.ring/dev
+ :figwheel.server.ring/system-app-handler]
+ ;; executing a function is slightly different as well
+ #(helper/middleware
+ %
+ {:header "Main fn exec page"
+ :body (str
+ (format "<blockquote class=\"action-box\">Invoked main function: <code>%s/-main</code></blockquote>" (str main))
+ (slurp
+ (io/resource "public/com/bhauman/figwheel/helper/content/welcome_main_exec.html")))
+ :output-to output-to}))
+ (assoc-in [::config :mode] :repl))
+ source (:uri (fw-util/ns->location (get-in cfg [:options :main])))]
+ (let [{:keys [options repl-options repl-env-options ::config] :as b-cfg}
+ (update-config cfg)
+ {:keys [pprint-config]} config]
+ (validate-fix-target-classpath! b-cfg)
+ (if pprint-config
+ (do
+ (log/info ":pprint-config true - printing config:")
+ (print-conf b-cfg))
+ (cljs.env/ensure
+ (build-cljs (get-in b-cfg [::build :id] "figwheel-main-option-build")
+ source
+ (:options b-cfg) cljs.env/*compiler*)
+ ;; all the complexity below is to handle async results from -main
+ (let [stolen-repl-env (promise)
+ result-prom (promise)]
+ (async-result/listen result-prom)
+ (try
+ (with-redefs [cljs.repl/tear-down (partial deliver stolen-repl-env)]
+ (let [res (cljs.cli/default-main repl-env-fn b-cfg)
+ parsed-result (try
+ (read-string res)
+ (catch Throwable t
+ ::read-error))]
+ (if (= parsed-result ::read-error)
+ (deliver result-prom res)
+ (if (and (coll? parsed-result)
+ (= (first parsed-result) :figwheel.main.async-result/wait))
+ (let [[_ arg1 arg2] parsed-result
+ timeout-val (or arg2 :figwheel.main.async-result/timed-out)]
+ (when (= timeout-val (deref result-prom (or arg1 5000) timeout-val))
+ (println (pr-str timeout-val))
+ (throw (ex-info "Main script timed out" {:value timeout-val}))))
+ (deliver result-prom parsed-result)))
+ (let [final-result @result-prom]
+ (if (and (map? final-result)
+ (= (get final-result :type)
+ :figwheel.main.async-result/exception))
+ (throw (ex-info
+ (:value final-result "System error exit from ClojureScript")
+ {:type :js-eval-exception
+ :error final-result
+ :repl-env @stolen-repl-env}))
+ (if (string? final-result)
+ (println final-result)
+ (println (pr-str final-result)))))))
+ (finally
+ (cljs.repl/tear-down @stolen-repl-env)))))))))
+
+ (defn add-default-system-app-handler [{:keys [options ::config] :as cfg}]
+ (let [extra-mains-name->output-to
+ (into {}
+ (keep (fn [[nm em-options]]
+ [(name nm) (:output-to (extra-main-options nm em-options options))])
+ (:extra-main-files config)))]
+ (update-in
+ cfg
+ [:repl-env-options
+ :ring-stack-options
+ :figwheel.server.ring/dev
+ :figwheel.server.ring/system-app-handler]
+ (fn [sah]
+ (if sah
+ sah
+ #(-> %
+ (helper/extra-main-hosting extra-mains-name->output-to)
+ (helper/missing-index
+ (if (and (:modules options)
+ (:output-dir options))
+ {:output-to (str (io/file (:output-dir options) "cljs_base.js"))}
+ (select-keys (:options cfg) [:output-to])))))))))
+
+ (defn validate-basic-assumptions! [{:keys [options ::config] :as cfg}]
+ (when (and (= (:mode config) :repl)
+ (not= :none (:optimizations options :none)))
+ (throw (ex-info "Can only start a REPL and inject hot-reloading when the :optimizations level is set to :none" {::error true}))))
+
+ (defn default-compile [repl-env-fn cfg]
+ (let [{:keys [options repl-options repl-env-options ::config] :as b-cfg}
+ (add-default-system-app-handler (update-config cfg))
+ {:keys [mode pprint-config ::build-once]} config
+ repl-env (apply repl-env-fn (mapcat identity repl-env-options))
+ cenv (cljs.env/default-compiler-env options)
+ repl-options (assoc repl-options :compiler-env cenv)]
+ (validate-basic-assumptions! b-cfg)
+ (validate-fix-target-classpath! b-cfg)
+ (binding [*base-config* cfg
+ *config* b-cfg]
+ (cljs.env/with-compiler-env cenv
+ (log/trace "Verbose config:" (with-out-str (pprint b-cfg)))
+ (if pprint-config
+ (do
+ (log/info ":pprint-config true - printing config:")
+ (print-conf b-cfg))
+ (binding [cljs.repl/*repl-env* repl-env
+ figwheel.core/*config* (select-keys config [:hot-reload-cljs
+ :broadcast-reload
+ :reload-dependents])]
+ (try
+ (let [fw-mode? (figwheel-mode? b-cfg)]
+ (try
+ (build config options cenv)
+ (catch Throwable t
+ (log/error t)
+ ;; when not watching throw build errors
+ (when-not (and (not build-once)
+ (= :none (:optimizations options :none))
+ (not-empty (:watch-dirs config)))
+ (throw t))))
+ (log/trace "Figwheel.core config:" (pr-str figwheel.core/*config*))
+ (when-not build-once
+ (register-build!
+ (get-in *config* [::build :id])
+ {:repl-env repl-env
+ :repl-options repl-options
+ :config *config*})
+ (start-background-builds (select-keys cfg [::background-builds
+ ::start-figwheel-options]))
+ (doseq [init-fn (::initializers b-cfg)] (init-fn)))
+ (cond
+ (and (= mode :repl) (not build-once))
+ ;; this forwards command line args
+ (repl-action repl-env repl-options)
+ (= mode :serve)
+ ;; we need to get the server host:port args
+ (serve-action
+ {:repl-env repl-env
+ :repl-options repl-options
+ :join? (get b-cfg ::join-server? true)})
+ ;; the final case is compiling without a repl or a server
+ ;; if there is a watcher running join it
+ (and (not build-once)
+ (fww/running?)
+ (get b-cfg ::join-server? true))
+ (fww/join)))
+ (finally
+ ;; these are the blocking states that we want to clean up after
+ (when (or (get b-cfg ::join-server? true)
+ (and
+ (not (in-nrepl?))
+ (= mode :repl)))
+ (fww/stop!)
+ (remove-watch cenv :figwheel.core/watch-hook)
+ (swap! build-registry dissoc (get-in *config* [::build :id])))))))))))
+
+ ;; ------------------------------------------------------------
+ ;; REPL API
+ ;; ------------------------------------------------------------
+
+ (defn- start-build-arg->build-options [build]
+ (let [[build-id build-options config]
+ (if (map? build)
+ [(:id build) (:options build)
+ (:config build)]
+ [build])
+ build-id (name build-id)
+ options (or (and (not build-options)
+ (get-build build-id))
+ build-options
+ {})
+ config (or config (meta options))]
+ (cond-> {:id build-id
+ :options options}
+ config (assoc :config config))))
+
+ (defn build-option-arg? [a]
+ (or
+ (string? a)
+ (keyword? a)
+ (symbol? a)
+ (and (map? a)
+ (:id a)
+ (:options a))))
+
+ (defn start*
+ ([join-server? build]
+ (assert (build-option-arg? build) "Figwheel Start: build argument required")
+ (start* join-server? nil build))
+ ([join-server? figwheel-options-or-build bbuild & builds]
+ (let [[figwheel-options build & background-builds]
+ (if-not (build-option-arg? figwheel-options-or-build)
+ (concat [figwheel-options-or-build bbuild] builds)
+ (concat [nil figwheel-options-or-build bbuild] builds))
+ {:keys [id] :as build} (start-build-arg->build-options build)
cfg
- (assoc-in cfg [::build :id] "figwheel-main-option-build"))
- output-to (get-in cfg [:options :output-to]
- (default-output-to cfg))
- main (:main cfg)
- cfg (-> cfg
- (assoc-in [:options :aot-cache] false)
- (update :options #(assoc % :main
- (or (some-> (:main cfg) symbol)
- 'figwheel.repl.preload)))
- (assoc-in [::config
- :ring-stack-options
- :figwheel.server.ring/dev
- :figwheel.server.ring/system-app-handler]
- ;; executing a function is slightly different as well
- #(helper/middleware
- %
- {:header "Main fn exec page"
- :body (str
- (format "<blockquote class=\"action-box\">Invoked main function: <code>%s/-main</code></blockquote>" (str main))
- (slurp
- (io/resource "public/com/bhauman/figwheel/helper/content/welcome_main_exec.html")))
- :output-to output-to}))
- (assoc-in [::config :mode] :repl))
- source (:uri (fw-util/ns->location (get-in cfg [:options :main])))]
- (let [{:keys [options repl-options repl-env-options ::config] :as b-cfg}
- (update-config cfg)
- {:keys [pprint-config]} config]
- (validate-fix-target-classpath! b-cfg)
- (if pprint-config
- (do
- (log/info ":pprint-config true - printing config:")
- (print-conf b-cfg))
- (cljs.env/ensure
- (build-cljs (get-in b-cfg [::build :id] "figwheel-main-option-build")
- source
- (:options b-cfg) cljs.env/*compiler*)
- ;; all the complexity below is to handle async results from -main
- (let [stolen-repl-env (promise)
- result-prom (promise)]
- (async-result/listen result-prom)
- (try
- (with-redefs [cljs.repl/tear-down (partial deliver stolen-repl-env)]
- (let [res (cljs.cli/default-main repl-env-fn b-cfg)
- parsed-result (try
- (read-string res)
- (catch Throwable t
- ::read-error))]
- (if (= parsed-result ::read-error)
- (deliver result-prom res)
- (if (and (coll? parsed-result)
- (= (first parsed-result) :figwheel.main.async-result/wait))
- (let [[_ arg1 arg2] parsed-result
- timeout-val (or arg2 :figwheel.main.async-result/timed-out)]
- (when (= timeout-val (deref result-prom (or arg1 5000) timeout-val))
- (println (pr-str timeout-val))
- (throw (ex-info "Main script timed out" {:value timeout-val}))))
- (deliver result-prom parsed-result)))
- (let [final-result @result-prom]
- (if (and (map? final-result)
- (= (get final-result :type)
- :figwheel.main.async-result/exception))
- (throw (ex-info
- (:value final-result "System error exit from ClojureScript")
- {:type :js-eval-exception
- :error final-result
- :repl-env @stolen-repl-env}))
- (if (string? final-result)
- (println final-result)
- (println (pr-str final-result)))))))
- (finally
- (cljs.repl/tear-down @stolen-repl-env)))))))))
-
-(defn add-default-system-app-handler [{:keys [options ::config] :as cfg}]
- (let [extra-mains-name->output-to
- (into {}
- (keep (fn [[nm em-options]]
- [(name nm) (:output-to (extra-main-options nm em-options options))])
- (:extra-main-files config)))]
- (update-in
- cfg
- [:repl-env-options
- :ring-stack-options
- :figwheel.server.ring/dev
- :figwheel.server.ring/system-app-handler]
- (fn [sah]
- (if sah
- sah
- #(-> %
- (helper/extra-main-hosting extra-mains-name->output-to)
- (helper/missing-index
- (if (and (:modules options)
- (:output-dir options))
- {:output-to (str (io/file (:output-dir options) "cljs_base.js"))}
- (select-keys (:options cfg) [:output-to])))))))))
-
-(defn validate-basic-assumptions! [{:keys [options ::config] :as cfg}]
- (when (and (= (:mode config) :repl)
- (not= :none (:optimizations options :none)))
- (throw (ex-info "Can only start a REPL and inject hot-reloading when the :optimizations level is set to :none" {::error true}))))
-
-(defn default-compile [repl-env-fn cfg]
- (let [{:keys [options repl-options repl-env-options ::config] :as b-cfg}
- (add-default-system-app-handler (update-config cfg))
- {:keys [mode pprint-config ::build-once]} config
- repl-env (apply repl-env-fn (mapcat identity repl-env-options))
- cenv (cljs.env/default-compiler-env options)
- repl-options (assoc repl-options :compiler-env cenv)]
- (validate-basic-assumptions! b-cfg)
- (validate-fix-target-classpath! b-cfg)
- (binding [*base-config* cfg
- *config* b-cfg]
- (cljs.env/with-compiler-env cenv
- (log/trace "Verbose config:" (with-out-str (pprint b-cfg)))
- (if pprint-config
- (do
- (log/info ":pprint-config true - printing config:")
- (print-conf b-cfg))
- (binding [cljs.repl/*repl-env* repl-env
- figwheel.core/*config* (select-keys config [:hot-reload-cljs
- :broadcast-reload
- :reload-dependents])]
- (try
- (let [fw-mode? (figwheel-mode? b-cfg)]
- (try
- (build config options cenv)
- (catch Throwable t
- (log/error t)
- ;; when not watching throw build errors
- (when-not (and (not build-once)
- (= :none (:optimizations options :none))
- (not-empty (:watch-dirs config)))
- (throw t))))
- (log/trace "Figwheel.core config:" (pr-str figwheel.core/*config*))
- (when-not build-once
- (register-build!
- (get-in *config* [::build :id])
- {:repl-env repl-env
- :repl-options repl-options
- :config *config*})
- (start-background-builds (select-keys cfg [::background-builds
- ::start-figwheel-options]))
- (doseq [init-fn (::initializers b-cfg)] (init-fn)))
- (cond
- (and (= mode :repl) (not build-once))
- ;; this forwards command line args
- (repl-action repl-env repl-options)
- (= mode :serve)
- ;; we need to get the server host:port args
- (serve-action
- {:repl-env repl-env
- :repl-options repl-options
- :join? (get b-cfg ::join-server? true)})
- ;; the final case is compiling without a repl or a server
- ;; if there is a watcher running join it
- (and (not build-once)
- (fww/running?)
- (get b-cfg ::join-server? true))
- (fww/join)))
- (finally
- ;; these are the blocking states that we want to clean up after
- (when (or (get b-cfg ::join-server? true)
- (and
- (not (in-nrepl?))
- (= mode :repl)))
- (fww/stop!)
- (remove-watch cenv :figwheel.core/watch-hook)
- (swap! build-registry dissoc (get-in *config* [::build :id])))))))))))
-
-;; ------------------------------------------------------------
-;; REPL API
-;; ------------------------------------------------------------
-
-(defn- start-build-arg->build-options [build]
- (let [[build-id build-options config]
- (if (map? build)
- [(:id build) (:options build)
- (:config build)]
- [build])
- build-id (name build-id)
- options (or (and (not build-options)
- (get-build build-id))
- build-options
- {})
- config (or config (meta options))]
- (cond-> {:id build-id
- :options options}
- config (assoc :config config))))
-
-(defn build-option-arg? [a]
- (or
- (string? a)
- (keyword? a)
- (symbol? a)
- (and (map? a)
- (:id a)
- (:options a))))
-
-(defn start*
- ([join-server? build]
- (assert (build-option-arg? build) "Figwheel Start: build argument required")
- (start* join-server? nil build))
- ([join-server? figwheel-options-or-build bbuild & builds]
- (let [[figwheel-options build & background-builds]
- (if-not (build-option-arg? figwheel-options-or-build)
- (concat [figwheel-options-or-build bbuild] builds)
- (concat [nil figwheel-options-or-build bbuild] builds))
- {:keys [id] :as build} (start-build-arg->build-options build)
- cfg
- (cond-> {:options (:options build)
- ::join-server? (if (true? join-server?) true false)}
- figwheel-options (assoc ::start-figwheel-options figwheel-options)
- id (assoc ::build (dissoc build :options))
- (and (not (get figwheel-options :mode))
- (= :none (get-in build [:options :optimizations] :none)))
- (assoc-in [::config :mode] :repl)
- (not-empty background-builds)
- (assoc ::background-builds (mapv
- start-build-arg->build-options
- background-builds)))]
- (if (and id (get @build-registry id))
- (throw (ex-info (format "A build with id \"%s\" is already running." id) {}))
- (default-compile cljs.repl.figwheel/repl-env cfg)))))
-
-(defn ^{:deprecated "0.1.6"} start
- "Starts a Figwheel build process.
+ (cond-> {:options (:options build)
+ ::join-server? (if (true? join-server?) true false)}
+ figwheel-options (assoc ::start-figwheel-options figwheel-options)
+ id (assoc ::build (dissoc build :options))
+ (and (not (get figwheel-options :mode))
+ (= :none (get-in build [:options :optimizations] :none)))
+ (assoc-in [::config :mode] :repl)
+ (not-empty background-builds)
+ (assoc ::background-builds (mapv
+ start-build-arg->build-options
+ background-builds)))]
+ (if (and id (get @build-registry id))
+ (throw (ex-info (format "A build with id \"%s\" is already running." id) {}))
+ (default-compile cljs.repl.figwheel/repl-env cfg)))))
+
+ (defn ^{:deprecated "0.1.6"} start
+ "Starts a Figwheel build process.
Deprecated see the documentation for figwheel.main.api/start"
- [& args]
- (apply start* false args))
-
-(defn ^{:deprecated "0.1.6"} start-join
- "Deprecated see the documentation for figwheel.main.api/start-join"
- [& args]
- (apply start* true args))
-
-;; ----------------------------------------------------------------------------
-;; CLJS REPL api
-;; ----------------------------------------------------------------------------
-
-;; Unfortunately this is rather hacky way to allow some control over builds
-;; this works fine for allowing folks to reset builds that are running
-;; but not super helpful otherwise
-
-;; this does not allow starting up new builds or truely dropping a
-;; build it only manages stopping and starting the the watcher
-;; process, reloading the config, and stopping the watcher process
-;; it doesn't stop and restart the server as that would interrupt the repl
-;; session
-
-(defn autobuilding-ids []
- (->> (:watches @fww/*watcher*)
- keys
- (filter #(-> % first (= ::autobuild)))
- (map second)
- set))
-
-(defn currently-available-ids [] (set (keys @build-registry)))
-
-;; doesn't respect ::start-figwheel-options
-(defn config-for-id [id]
- (when-let [{:keys [config]} (get @build-registry id)]
- config))
-
-(defn clean-build [{:keys [output-to output-dir]}]
- (when (and output-to output-dir)
- (doseq [file (cons (io/file output-to)
- (reverse (file-seq (io/file output-dir))))]
- (when (.exists file) (.delete file)))))
-
-(defn warn-on-bad-id [ids]
- (when-let [bad-ids (not-empty (remove (currently-available-ids) ids))]
- (doseq [bad-id bad-ids]
- (println "No available build currently has id:" bad-id))))
-
-;; TODO this should clean ids that are not currently running as well
-;; TODO should this default to cleaning all builds??
-;; I think yes
-(defn clean* [ids]
- (let [ids (->> ids (map name) distinct)]
- (warn-on-bad-id ids)
- (doseq [id ids]
- (when-let [options (-> build-registry deref (get id) :config :options)]
- (println "Cleaning build id:" id)
- (clean-build options)))))
-
-(defmacro ^:cljs-repl-api clean
- "Takes one or more builds ids and deletes their compiled artifacts."
- [& build-ids]
- (clean* (map name build-ids))
- nil)
-
-(defn status* []
- (println "------- Figwheel Main Status -------")
- (println "Currently available:" (string/join ", " (currently-available-ids)))
- (if-let [ids (not-empty (autobuilding-ids))]
- (println "Currently building:" (string/join ", " ids))
- (println "No builds are currently being built.")))
-
-(defmacro ^:cljs-repl-api status
- "Displays the build ids of the builds are currently being watched and compiled."
- []
- (status*) nil)
-
-(defn stop-builds* [ids]
- (let [ids (->> ids (map name) distinct)]
- (warn-on-bad-id ids)
- (doseq [k (map #(vector ::autobuild %) ids)]
- (when (-> fww/*watcher* deref :watches (get k))
- (println "Stopped building id:" (last k))
- (fww/remove-watch! k)))))
-
-;; TODO should this default to stopping all builds??
-;; I think yes
-(defmacro ^:cljs-repl-api stop-builds
- "Takes one or more build ids and stops watching and compiling them."
- [& build-ids]
- (stop-builds*
- (or (not-empty build-ids)
- (autobuilding-ids)))
- nil)
-
-(defn start-build*
- "This starts a build that has previously been stopped."
- [id]
- (when-let [{:keys [repl-env repl-options] :as build-info} (get @build-registry (name id))]
- (let [{:keys [options ::config]} (:config build-info)
- {:keys [watch-dirs ::build-inputs]} config
- compiler-env (:compiler-env repl-options)]
- (println "Starting build id:" id)
- ;; XXX should this have syntax error feedback?
- (build-cljs id (apply bapi/inputs build-inputs) options compiler-env)
- (watch-build id
- watch-dirs
- build-inputs
- options
- compiler-env
- (config->reload-config config))
- ;; this might not even need to be done
- #_(when (first (filter #{'figwheel.core} (:preloads options)))
- (binding [cljs.repl/*repl-env* repl-env]
- (figwheel.core/start*))))))
-
-(defn start-builds* [ids]
- (let [ids (->> ids (map name) distinct)
- already-building (not-empty (filter (autobuilding-ids) ids))
- ids (filter (complement (autobuilding-ids)) ids)]
- (when (not-empty already-building)
- (doseq [i already-building]
- (println "Already building id: " i)))
- (doseq [id ids]
- (start-build* id))))
-
-(defmacro ^:cljs-repl-api start-builds
- "Takes one or more build names and starts them building."
- [& build-ids]
- (start-builds*
- (or (not-empty build-ids)
- (currently-available-ids)))
- nil)
-
-(defn reload-config* [id]
- (println "Reloading config for id:" id)
- ;; update the config in the registry
- (when-let [{:keys [build-info]} (get (currently-available-ids) (name id))]
- (swap! build-registry update-in [id :config]
- #(update-config
- (-> (when (::start-figwheel-options %)
- (select-keys % ::start-figwheel-options))
- (build-opt id)
- (assoc-in [::config :mode] :repl))))))
-
-(defn reset* [ids]
- (let [ids (->> ids (map name) distinct)
- ids (or (not-empty ids) (autobuilding-ids))]
- (clean* ids)
- (stop-builds* ids)
- (mapv reload-config* ids)
- (start-builds* ids)
- nil))
-
-(defmacro ^:cljs-repl-api reset
- "If no args are provided, all current builds will be cleaned and restarted.
+ [& args]
+ (apply start* false args))
+
+ (defn ^{:deprecated "0.1.6"} start-join
+ "Deprecated see the documentation for figwheel.main.api/start-join"
+ [& args]
+ (apply start* true args))
+
+ ;; ----------------------------------------------------------------------------
+ ;; CLJS REPL api
+ ;; ----------------------------------------------------------------------------
+
+ ;; Unfortunately this is rather hacky way to allow some control over builds
+ ;; this works fine for allowing folks to reset builds that are running
+ ;; but not super helpful otherwise
+
+ ;; this does not allow starting up new builds or truely dropping a
+ ;; build it only manages stopping and starting the the watcher
+ ;; process, reloading the config, and stopping the watcher process
+ ;; it doesn't stop and restart the server as that would interrupt the repl
+ ;; session
+
+ (defn autobuilding-ids []
+ (->> (:watches @fww/*watcher*)
+ keys
+ (filter #(-> % first (= ::autobuild)))
+ (map second)
+ set))
+
+ (defn currently-available-ids [] (set (keys @build-registry)))
+
+ ;; doesn't respect ::start-figwheel-options
+ (defn config-for-id [id]
+ (when-let [{:keys [config]} (get @build-registry id)]
+ config))
+
+ (defn clean-build [{:keys [output-to output-dir]}]
+ (when (and output-to output-dir)
+ (doseq [file (cons (io/file output-to)
+ (reverse (file-seq (io/file output-dir))))]
+ (when (.exists file) (.delete file)))))
+
+ (defn warn-on-bad-id [ids]
+ (when-let [bad-ids (not-empty (remove (currently-available-ids) ids))]
+ (doseq [bad-id bad-ids]
+ (println "No available build currently has id:" bad-id))))
+
+ ;; TODO this should clean ids that are not currently running as well
+ ;; TODO should this default to cleaning all builds??
+ ;; I think yes
+ (defn clean* [ids]
+ (let [ids (->> ids (map name) distinct)]
+ (warn-on-bad-id ids)
+ (doseq [id ids]
+ (when-let [options (-> build-registry deref (get id) :config :options)]
+ (println "Cleaning build id:" id)
+ (clean-build options)))))
+
+ (defmacro ^:cljs-repl-api clean
+ "Takes one or more builds ids and deletes their compiled artifacts."
+ [& build-ids]
+ (clean* (map name build-ids))
+ nil)
+
+ (defn status* []
+ (println "------- Figwheel Main Status -------")
+ (println "Currently available:" (string/join ", " (currently-available-ids)))
+ (if-let [ids (not-empty (autobuilding-ids))]
+ (println "Currently building:" (string/join ", " ids))
+ (println "No builds are currently being built.")))
+
+ (defmacro ^:cljs-repl-api status
+ "Displays the build ids of the builds are currently being watched and compiled."
+ []
+ (status*) nil)
+
+ (defn stop-builds* [ids]
+ (let [ids (->> ids (map name) distinct)]
+ (warn-on-bad-id ids)
+ (doseq [k (map #(vector ::autobuild %) ids)]
+ (when (-> fww/*watcher* deref :watches (get k))
+ (println "Stopped building id:" (last k))
+ (fww/remove-watch! k)))))
+
+ ;; TODO should this default to stopping all builds??
+ ;; I think yes
+ (defmacro ^:cljs-repl-api stop-builds
+ "Takes one or more build ids and stops watching and compiling them."
+ [& build-ids]
+ (stop-builds*
+ (or (not-empty build-ids)
+ (autobuilding-ids)))
+ nil)
+
+ (defn start-build*
+ "This starts a build that has previously been stopped."
+ [id]
+ (when-let [{:keys [repl-env repl-options] :as build-info} (get @build-registry (name id))]
+ (let [{:keys [options ::config]} (:config build-info)
+ {:keys [watch-dirs ::build-inputs]} config
+ compiler-env (:compiler-env repl-options)]
+ (println "Starting build id:" id)
+ ;; XXX should this have syntax error feedback?
+ (build-cljs id (apply bapi/inputs build-inputs) options compiler-env)
+ (watch-build id
+ watch-dirs
+ build-inputs
+ options
+ compiler-env
+ (config->reload-config config))
+ ;; this might not even need to be done
+ #_(when (first (filter #{'figwheel.core} (:preloads options)))
+ (binding [cljs.repl/*repl-env* repl-env]
+ (figwheel.core/start*))))))
+
+ (defn start-builds* [ids]
+ (let [ids (->> ids (map name) distinct)
+ already-building (not-empty (filter (autobuilding-ids) ids))
+ ids (filter (complement (autobuilding-ids)) ids)]
+ (when (not-empty already-building)
+ (doseq [i already-building]
+ (println "Already building id: " i)))
+ (doseq [id ids]
+ (start-build* id))))
+
+ (defmacro ^:cljs-repl-api start-builds
+ "Takes one or more build names and starts them building."
+ [& build-ids]
+ (start-builds*
+ (or (not-empty build-ids)
+ (currently-available-ids)))
+ nil)
+
+ (defn reload-config* [id]
+ (println "Reloading config for id:" id)
+ ;; update the config in the registry
+ (when-let [{:keys [build-info]} (get (currently-available-ids) (name id))]
+ (swap! build-registry update-in [id :config]
+ #(update-config
+ (-> (when (::start-figwheel-options %)
+ (select-keys % ::start-figwheel-options))
+ (build-opt id)
+ (assoc-in [::config :mode] :repl))))))
+
+ (defn reset* [ids]
+ (let [ids (->> ids (map name) distinct)
+ ids (or (not-empty ids) (autobuilding-ids))]
+ (clean* ids)
+ (stop-builds* ids)
+ (mapv reload-config* ids)
+ (start-builds* ids)
+ nil))
+
+ (defmacro ^:cljs-repl-api reset
+ "If no args are provided, all current builds will be cleaned and restarted.
Otherwise, this will clean and restart the provided build ids."
- [& build-ids]
- (reset* build-ids))
-
-;; TODO build inputs will affect this
-(defn build-once* [ids]
- (let [ids (->> ids (map name) distinct)
- bad-ids (filter (complement (currently-available-ids)) ids)
- good-ids (filter (currently-available-ids) ids)]
- (when (not-empty bad-ids)
- (doseq [i bad-ids]
- (println "Build id not found:" i)))
- (when (not-empty good-ids)
- ;; clean?
- (doseq [i good-ids]
- (let [{:keys [options ::config]} (config-for-id i)
- input (if-let [paths (not-empty (:watch-dirs config))]
- (apply bapi/inputs paths)
- (when-let [source (when (:main options)
- (:uri (fw-util/ns->location (symbol (:main options)))))]
- source))]
- (when input
- (build-cljs i input options
- (cljs.env/default-compiler-env options))))))))
-
-(defmacro ^:cljs-repl-api build-once
- "Forces a single compile of the provided build ids."
- [& build-ids]
- (build-once* build-ids)
- nil)
-
-;; ----------------------------------------------------------------------------
-;; Main
-;; ----------------------------------------------------------------------------
-
-(defn fix-simple-bool-arg* [flags args]
- (let [[pre post] (split-with (complement flags) args)]
- (if (empty? post)
- pre
- (concat pre [(first post) "true"] (rest post)))))
-
-(defn fix-simple-bool-args [flags args]
- (reverse
- (reduce (fn [accum arg]
- (if (and (flags (first accum))
- (not (#{"true" "false"} arg)))
- (-> accum
- (conj "true")
- (conj arg))
- (conj accum arg)))
- (list)
- args)))
-
-(defn -main [& orig-args]
- ;; todo make this local with-redefs?
- (alter-var-root #'cli/default-commands cli/add-commands figwheel-commands)
- ;; set log level early
- (when-let [level (get-edn-file-key "figwheel-main.edn" :log-level)]
- (log/set-level level))
- (try
- (let [args (fix-simple-bool-args #{"-pc" "--print-config"} orig-args)
- [pre post] (split-with (complement #{"-re" "--repl-env"}) args)
- _ (when (not-empty post)
- (throw
- (ex-info (str "figwheel.main does not support the --repl-env option\n"
- "The figwheel REPL is implicitly used.\n"
- "Perhaps you were intending to use the --target option?")
- {::error true})))
- _ (validate-cli! (vec orig-args))
- args' (concat ["-re" "figwheel"] args)
- args' (if (or (empty? args)
- (= args ["-pc" "true"])
- (= args ["--print-config" "true"]))
- (concat args' ["-r"]) args')]
- (with-redefs [cljs.cli/default-compile default-compile
- cljs.cli/load-edn-opts load-edn-opts]
- (apply cljs.main/-main args')))
- (catch Throwable e
- (let [d (ex-data e)
- build-once? (some (set orig-args) ["--build-once" "-bo"])]
- (cond
- (or
- (:figwheel.main.schema.core/error d)
- (:figwheel.main.schema.cli/error d)
- (:cljs.main/error d)
- (::error d))
- (binding [*out* *err*]
- (if build-once?
- (throw e)
- (println (.getMessage e))))
- (and (#{:js-eval-exception :js-eval-error} (:type d))
- (:error d))
- (let [{:keys [repl-env error form]} d]
- (#'cljs.repl/display-error repl-env error form {})
- (throw e))
- :else (throw e))))))))
+ [& build-ids]
+ (reset* build-ids))
+
+ ;; TODO build inputs will affect this
+ (defn build-once* [ids]
+ (let [ids (->> ids (map name) distinct)
+ bad-ids (filter (complement (currently-available-ids)) ids)
+ good-ids (filter (currently-available-ids) ids)]
+ (when (not-empty bad-ids)
+ (doseq [i bad-ids]
+ (println "Build id not found:" i)))
+ (when (not-empty good-ids)
+ ;; clean?
+ (doseq [i good-ids]
+ (let [{:keys [options ::config]} (config-for-id i)
+ input (if-let [paths (not-empty (:watch-dirs config))]
+ (apply bapi/inputs paths)
+ (when-let [source (when (:main options)
+ (:uri (fw-util/ns->location (symbol (:main options)))))]
+ source))]
+ (when input
+ (build-cljs i input options
+ (cljs.env/default-compiler-env options))))))))
+
+ (defmacro ^:cljs-repl-api build-once
+ "Forces a single compile of the provided build ids."
+ [& build-ids]
+ (build-once* build-ids)
+ nil)
+
+ ;; ----------------------------------------------------------------------------
+ ;; Main
+ ;; ----------------------------------------------------------------------------
+
+ (defn fix-simple-bool-arg* [flags args]
+ (let [[pre post] (split-with (complement flags) args)]
+ (if (empty? post)
+ pre
+ (concat pre [(first post) "true"] (rest post)))))
+
+ (defn fix-simple-bool-args [flags args]
+ (reverse
+ (reduce (fn [accum arg]
+ (if (and (flags (first accum))
+ (not (#{"true" "false"} arg)))
+ (-> accum
+ (conj "true")
+ (conj arg))
+ (conj accum arg)))
+ (list)
+ args)))
+
+ (defn -main [& orig-args]
+ ;; todo make this local with-redefs?
+ (alter-var-root #'cli/default-commands cli/add-commands figwheel-commands)
+ ;; set log level early
+ (when-let [level (get-edn-file-key "figwheel-main.edn" :log-level)]
+ (log/set-level level))
+ (try
+ (let [args (fix-simple-bool-args #{"-pc" "--print-config"} orig-args)
+ [pre post] (split-with (complement #{"-re" "--repl-env"}) args)
+ _ (when (not-empty post)
+ (throw
+ (ex-info (str "figwheel.main does not support the --repl-env option\n"
+ "The figwheel REPL is implicitly used.\n"
+ "Perhaps you were intending to use the --target option?")
+ {::error true})))
+ _ (validate-cli! (vec orig-args))
+ args' (concat ["-re" "figwheel"] args)
+ args' (if (or (empty? args)
+ (= args ["-pc" "true"])
+ (= args ["--print-config" "true"]))
+ (concat args' ["-r"]) args')]
+ (with-redefs [cljs.cli/default-compile default-compile
+ cljs.cli/load-edn-opts load-edn-opts]
+ (apply cljs.main/-main args')))
+ (catch Throwable e
+ (let [d (ex-data e)
+ build-once? (some (set orig-args) ["--build-once" "-bo"])]
+ (cond
+ (or
+ (:figwheel.main.schema.core/error d)
+ (:figwheel.main.schema.cli/error d)
+ (:cljs.main/error d)
+ (::error d))
+ (binding [*out* *err*]
+ (if build-once?
+ (throw e)
+ (println (.getMessage e))))
+ (and (#{:js-eval-exception :js-eval-error} (:type d))
+ (:error d))
+ (let [{:keys [repl-env error form]} d]
+ (#'cljs.repl/display-error repl-env error form {})
+ (throw e))
+ :else (throw e))))))))
#_(def test-args
- (concat ["-co" "{:aot-cache false :asset-path \"out\"}" "-b" "dev" "-e" "(figwheel.core/start-from-repl)"]
- (string/split "-w src -d target/public/out -o target/public/out/mainer.js -c exproj.core -r" #"\s")))
+ (concat ["-co" "{:aot-cache false :asset-path \"out\"}" "-b" "dev" "-e" "(figwheel.core/start-from-repl)"]
+ (string/split "-w src -d target/public/out -o target/public/out/mainer.js -c exproj.core -r" #"\s")))
#_(handle-build-opt (concat (first (split-at-main-opt args)) ["-h"]))
diff --git a/src/figwheel/main/ansi_party.clj b/src/figwheel/main/ansi_party.clj
index 6f0bb95..1f1b67a 100644
--- a/src/figwheel/main/ansi_party.clj
+++ b/src/figwheel/main/ansi_party.clj
@@ -8,16 +8,16 @@
(if (string? x)
x
(walk/postwalk
- (fn [x]
- (cond
- (vector? x)
- (let [[kys args] (split-with keyword? x)
- form-fns (not-empty (keep *formatters* kys))
- form-fn (if form-fns (apply comp form-fns) identity)]
- (form-fn (apply str args)))
- (seq? x) (apply str x)
- :else x))
- x)))
+ (fn [x]
+ (cond
+ (vector? x)
+ (let [[kys args] (split-with keyword? x)
+ form-fns (not-empty (keep *formatters* kys))
+ form-fn (if form-fns (apply comp form-fns) identity)]
+ (form-fn (apply str args)))
+ (seq? x) (apply str x)
+ :else x))
+ x)))
(defn ansi-code [code]
(when (and *use-color* code)
@@ -28,7 +28,7 @@
(defmacro with-added-formatters [formatter-map & body]
`(binding [*formatters* (merge *formatters* ~formatter-map)]
- ~@body))
+ ~@body))
(defn- setup-ansi-table [ansi-code-map]
(->> ansi-code-map
diff --git a/src/figwheel/main/async_result.cljc b/src/figwheel/main/async_result.cljc
index 803cf29..3167957 100644
--- a/src/figwheel/main/async_result.cljc
+++ b/src/figwheel/main/async_result.cljc
@@ -25,7 +25,7 @@
)
:clj (defn listen [prom]
(figwheel.repl/add-listener
- ::listener
- (fn [{:keys [response] :as msg}]
- (when (= "async-result" (:figwheel-event response))
- (deliver prom (:value response)))))))
+ ::listener
+ (fn [{:keys [response] :as msg}]
+ (when (= "async-result" (:figwheel-event response))
+ (deliver prom (:value response)))))))
diff --git a/src/figwheel/main/css_reload.cljc b/src/figwheel/main/css_reload.cljc
index 687fef9..69c7f9c 100644
--- a/src/figwheel/main/css_reload.cljc
+++ b/src/figwheel/main/css_reload.cljc
@@ -18,190 +18,190 @@
(do
-;; --------------------------------------------------
-;; Logging
-;; --------------------------------------------------
-;;
-;; Levels
-;; goog.debug.Logger.Level.(SEVERE WARNING INFO CONFIG FINE FINER FINEST)
-;;
-;; set level (.setLevel logger goog.debug.Logger.Level.INFO)
-;; disable (.setCapturing log-console false)
-
-(defonce logger (glog/getLogger "Figwheel CSS Reload"))
-
-(defn ^:export console-logging []
- (when-not (gobj/get goog.debug.Console "instance")
- (let [c (goog.debug.Console.)]
- ;; don't display time
- (doto (.getFormatter c)
- (gobj/set "showAbsoluteTime" false)
- (gobj/set "showRelativeTime" false))
- (gobj/set goog.debug.Console "instance" c)
- c))
- (when-let [console-instance (gobj/get goog.debug.Console "instance")]
- (.setCapturing console-instance true)
- true))
-
-(defonce log-console (console-logging))
-
-(defn add-cache-buster [url]
- (.makeUnique (guri/parse url)))
-
-(defn current-links []
- (->> (.getElementsByTagName js/document "link")
- (.call (.. js/Array -prototype -slice))
- (remove (comp #{"preload"} #(.-rel %)))))
-
-(defn truncate-url [url]
- (-> (first (string/split url #"\?"))
- (string/replace-first (str (.-protocol js/location) "//") "")
- (string/replace-first ".*://" "")
- (string/replace-first #"^//" "")
- (string/replace-first #"[^\/]*" "")))
-
-(defn matches-file?
- [file link]
- (when-let [link-href (.-href link)]
- (let [match (string/join "/"
- (take-while identity
- (map #(if (= %1 %2) %1 false)
- (reverse (string/split file "/"))
- (reverse (string/split (truncate-url link-href) "/")))))
- match-length (count match)
- file-name-length (count (last (string/split file "/")))]
- (when (>= match-length file-name-length) ;; has to match more than the file name length
- {:link link
- :link-href link-href
- :match-length match-length
- :current-url-length (count (truncate-url link-href))}))))
-
-(defn get-correct-link [file]
- (when-let [res (first
- (sort-by
- (fn [{:keys [match-length current-url-length]}]
- (- current-url-length match-length))
- (keep #(matches-file? file %)
- (current-links))))]
- (:link res)))
-
-(defn clone-link [link url]
- (let [clone (.createElement js/document "link")]
- (set! (.-rel clone) "stylesheet")
- (set! (.-media clone) (.-media link))
- (set! (.-disabled clone) (.-disabled link))
- (set! (.-href clone) (add-cache-buster url))
- clone))
-
-(defn create-link [url]
- (let [link (.createElement js/document "link")]
- (set! (.-rel link) "stylesheet")
- (set! (.-href link) (add-cache-buster url))
- link))
-
-(defn add-link-to-document [orig-link klone finished-fn]
- (let [parent (.-parentNode orig-link)]
- (if (= orig-link (.-lastChild parent))
- (.appendChild parent klone)
- (.insertBefore parent klone (.-nextSibling orig-link)))
- ;; prevent css removal flash
- (js/setTimeout #(do
- (.removeChild parent orig-link)
- (finished-fn))
- 300)))
-
-(defonce reload-css-deferred-chain (atom (Promise. #(%1 []))))
-
-(defn reload-css-file [file fin]
- (if-let [link (get-correct-link file)]
- (add-link-to-document link (clone-link link (.-href link))
- #(fin file))
- (fin nil)))
-
-(defn conj-reload-prom [prom file]
- (.then prom
- (fn [files]
- (Promise. (fn [succ fail]
- (reload-css-file file
- (fn [f]
- (succ (if f
- (conj files f)
- files)))))))))
-
-(defn dispatch-on-css-load [files]
- (.dispatchEvent
- js/document.body
- (doto (js/Event. "figwheel.after-css-load" js/document.body)
- (gobj/add "data" {:css-files files}))))
-
-(defn reload-css-files* [files on-cssload]
- (doseq [file files]
- (swap! reload-css-deferred-chain conj-reload-prom file))
- (swap! reload-css-deferred-chain
- (fn [prom]
- (.then prom
- (fn [loaded-files]
- (when (not-empty loaded-files)
- (glog/info logger (str "loaded " (pr-str loaded-files)))
- (dispatch-on-css-load loaded-files))
- (when-let [not-loaded (not-empty (remove (set loaded-files) (set files)))]
- (glog/warning logger (str "Unable to reload " (pr-str not-loaded))))
- ;; reset
- [])))))
-
-
-(defn reload-css-files [{:keys [on-cssload]} files]
- (when (not (nil? goog/global.document))
- (when-let [files' (not-empty (distinct files))]
- (reload-css-files* files' on-cssload))))
-
-;;takes an array of css files, relativized with forward slash path-separators
-(defn ^:export reload-css-files-remote [files-array]
- (reload-css-files {} files-array)
- true)
-
-)
+ ;; --------------------------------------------------
+ ;; Logging
+ ;; --------------------------------------------------
+ ;;
+ ;; Levels
+ ;; goog.debug.Logger.Level.(SEVERE WARNING INFO CONFIG FINE FINER FINEST)
+ ;;
+ ;; set level (.setLevel logger goog.debug.Logger.Level.INFO)
+ ;; disable (.setCapturing log-console false)
+
+ (defonce logger (glog/getLogger "Figwheel CSS Reload"))
+
+ (defn ^:export console-logging []
+ (when-not (gobj/get goog.debug.Console "instance")
+ (let [c (goog.debug.Console.)]
+ ;; don't display time
+ (doto (.getFormatter c)
+ (gobj/set "showAbsoluteTime" false)
+ (gobj/set "showRelativeTime" false))
+ (gobj/set goog.debug.Console "instance" c)
+ c))
+ (when-let [console-instance (gobj/get goog.debug.Console "instance")]
+ (.setCapturing console-instance true)
+ true))
+
+ (defonce log-console (console-logging))
+
+ (defn add-cache-buster [url]
+ (.makeUnique (guri/parse url)))
+
+ (defn current-links []
+ (->> (.getElementsByTagName js/document "link")
+ (.call (.. js/Array -prototype -slice))
+ (remove (comp #{"preload"} #(.-rel %)))))
+
+ (defn truncate-url [url]
+ (-> (first (string/split url #"\?"))
+ (string/replace-first (str (.-protocol js/location) "//") "")
+ (string/replace-first ".*://" "")
+ (string/replace-first #"^//" "")
+ (string/replace-first #"[^\/]*" "")))
+
+ (defn matches-file?
+ [file link]
+ (when-let [link-href (.-href link)]
+ (let [match (string/join "/"
+ (take-while identity
+ (map #(if (= %1 %2) %1 false)
+ (reverse (string/split file "/"))
+ (reverse (string/split (truncate-url link-href) "/")))))
+ match-length (count match)
+ file-name-length (count (last (string/split file "/")))]
+ (when (>= match-length file-name-length) ;; has to match more than the file name length
+ {:link link
+ :link-href link-href
+ :match-length match-length
+ :current-url-length (count (truncate-url link-href))}))))
+
+ (defn get-correct-link [file]
+ (when-let [res (first
+ (sort-by
+ (fn [{:keys [match-length current-url-length]}]
+ (- current-url-length match-length))
+ (keep #(matches-file? file %)
+ (current-links))))]
+ (:link res)))
+
+ (defn clone-link [link url]
+ (let [clone (.createElement js/document "link")]
+ (set! (.-rel clone) "stylesheet")
+ (set! (.-media clone) (.-media link))
+ (set! (.-disabled clone) (.-disabled link))
+ (set! (.-href clone) (add-cache-buster url))
+ clone))
+
+ (defn create-link [url]
+ (let [link (.createElement js/document "link")]
+ (set! (.-rel link) "stylesheet")
+ (set! (.-href link) (add-cache-buster url))
+ link))
+
+ (defn add-link-to-document [orig-link klone finished-fn]
+ (let [parent (.-parentNode orig-link)]
+ (if (= orig-link (.-lastChild parent))
+ (.appendChild parent klone)
+ (.insertBefore parent klone (.-nextSibling orig-link)))
+ ;; prevent css removal flash
+ (js/setTimeout #(do
+ (.removeChild parent orig-link)
+ (finished-fn))
+ 300)))
+
+ (defonce reload-css-deferred-chain (atom (Promise. #(%1 []))))
+
+ (defn reload-css-file [file fin]
+ (if-let [link (get-correct-link file)]
+ (add-link-to-document link (clone-link link (.-href link))
+ #(fin file))
+ (fin nil)))
+
+ (defn conj-reload-prom [prom file]
+ (.then prom
+ (fn [files]
+ (Promise. (fn [succ fail]
+ (reload-css-file file
+ (fn [f]
+ (succ (if f
+ (conj files f)
+ files)))))))))
+
+ (defn dispatch-on-css-load [files]
+ (.dispatchEvent
+ js/document.body
+ (doto (js/Event. "figwheel.after-css-load" js/document.body)
+ (gobj/add "data" {:css-files files}))))
+
+ (defn reload-css-files* [files on-cssload]
+ (doseq [file files]
+ (swap! reload-css-deferred-chain conj-reload-prom file))
+ (swap! reload-css-deferred-chain
+ (fn [prom]
+ (.then prom
+ (fn [loaded-files]
+ (when (not-empty loaded-files)
+ (glog/info logger (str "loaded " (pr-str loaded-files)))
+ (dispatch-on-css-load loaded-files))
+ (when-let [not-loaded (not-empty (remove (set loaded-files) (set files)))]
+ (glog/warning logger (str "Unable to reload " (pr-str not-loaded))))
+ ;; reset
+ [])))))
+
+
+ (defn reload-css-files [{:keys [on-cssload]} files]
+ (when (not (nil? goog/global.document))
+ (when-let [files' (not-empty (distinct files))]
+ (reload-css-files* files' on-cssload))))
+
+ ;;takes an array of css files, relativized with forward slash path-separators
+ (defn ^:export reload-css-files-remote [files-array]
+ (reload-css-files {} files-array)
+ true)
+
+ )
:clj
(do
-(defn client-eval [code]
- (when-not (string/blank? code)
- (cljs.repl/-evaluate
- cljs.repl/*repl-env*
- "<cljs repl>" 1
- code)))
-
-(defn reload-css-files [files]
- (when-not (empty? files)
- (client-eval
- (format "figwheel.main.css_reload.reload_css_files_remote(%s);"
- (json/write-str files)))))
-
-(defn prep-css-file-path [file]
- (-> file
- .getCanonicalPath
- (string/replace java.io.File/separator "/")))
-
-;; repl-env needs to be bound
-(defn start* [paths]
- (fww/add-watch!
- [::watcher paths]
- {:paths paths
- :filter (fww/suffix-filter #{"css"})
- :handler (fww/throttle
- 50
- (bound-fn [evts]
- (when-let [files (not-empty (mapv (comp prep-css-file-path :file) evts))]
- (reload-css-files files))))}))
-
-(defn stop* [paths]
- (let [remove-watch! (resolve 'figwheel.main/remove-watch!)]
- (remove-watch! [::watcher paths])))
-
-(defmacro start [paths] (start* paths) nil)
-
-(defmacro stop [paths] (stop* paths) nil)
+ (defn client-eval [code]
+ (when-not (string/blank? code)
+ (cljs.repl/-evaluate
+ cljs.repl/*repl-env*
+ "<cljs repl>" 1
+ code)))
+
+ (defn reload-css-files [files]
+ (when-not (empty? files)
+ (client-eval
+ (format "figwheel.main.css_reload.reload_css_files_remote(%s);"
+ (json/write-str files)))))
+
+ (defn prep-css-file-path [file]
+ (-> file
+ .getCanonicalPath
+ (string/replace java.io.File/separator "/")))
+
+ ;; repl-env needs to be bound
+ (defn start* [paths]
+ (fww/add-watch!
+ [::watcher paths]
+ {:paths paths
+ :filter (fww/suffix-filter #{"css"})
+ :handler (fww/throttle
+ 50
+ (bound-fn [evts]
+ (when-let [files (not-empty (mapv (comp prep-css-file-path :file) evts))]
+ (reload-css-files files))))}))
+
+ (defn stop* [paths]
+ (let [remove-watch! (resolve 'figwheel.main/remove-watch!)]
+ (remove-watch! [::watcher paths])))
+
+ (defmacro start [paths] (start* paths) nil)
+
+ (defmacro stop [paths] (stop* paths) nil)
)
diff --git a/src/figwheel/main/editor.cljc b/src/figwheel/main/editor.cljc
index 2a7946e..a27e8ad 100644
--- a/src/figwheel/main/editor.cljc
+++ b/src/figwheel/main/editor.cljc
@@ -10,65 +10,65 @@
#?(:cljs
(do
-;; TODO would rather have a global event to listen to here
-(defmethod heads-up/heads-up-event-dispatch "file-selected" [dataset]
- (let [msg {:figwheel-event "file-selected"
- :file-name (.-fileName dataset)
- :file-line (.-fileLine dataset)
- :file-column (.-fileColumn dataset)}]
- (figwheel.repl/debug [:open-file-msg (pr-str msg)])
- (figwheel.repl/respond-to-connection msg)))
+ ;; TODO would rather have a global event to listen to here
+ (defmethod heads-up/heads-up-event-dispatch "file-selected" [dataset]
+ (let [msg {:figwheel-event "file-selected"
+ :file-name (.-fileName dataset)
+ :file-line (.-fileLine dataset)
+ :file-column (.-fileColumn dataset)}]
+ (figwheel.repl/debug [:open-file-msg (pr-str msg)])
+ (figwheel.repl/respond-to-connection msg)))
-)
+ )
:clj
(do
-(defn get-open-file-command [open-file-command {:keys [file-name file-line file-column]}]
- (when open-file-command
- (if (= open-file-command "emacsclient")
- (cond-> ["emacsclient" "-n"]
- (not (nil? file-line))
- (conj (str "+" file-line
- (when (not (nil? file-column))
- (str ":" file-column))))
- true (conj file-name))
- [open-file-command file-name (str file-line) (str file-column)])))
+ (defn get-open-file-command [open-file-command {:keys [file-name file-line file-column]}]
+ (when open-file-command
+ (if (= open-file-command "emacsclient")
+ (cond-> ["emacsclient" "-n"]
+ (not (nil? file-line))
+ (conj (str "+" file-line
+ (when (not (nil? file-column))
+ (str ":" file-column))))
+ true (conj file-name))
+ [open-file-command file-name (str file-line) (str file-column)])))
-(defn validate-file-selected-msg [{:keys [file-name file-line file-column] :as msg}]
- (and file-name (.exists (io/file file-name))
- (cond-> msg
- file-line (assoc :file-line (java.lang.Integer/parseInt file-line))
- file-column (assoc :file-column (java.lang.Integer/parseInt file-column)))))
+ (defn validate-file-selected-msg [{:keys [file-name file-line file-column] :as msg}]
+ (and file-name (.exists (io/file file-name))
+ (cond-> msg
+ file-line (assoc :file-line (java.lang.Integer/parseInt file-line))
+ file-column (assoc :file-column (java.lang.Integer/parseInt file-column)))))
-(defn exec-open-file-command [open-file-command msg]
- (when-let [msg (#'validate-file-selected-msg msg)]
- (if-let [command (get-open-file-command open-file-command msg)]
- (try
- (let [result (apply shell/sh command)]
- (if (zero? (:exit result))
- (println "Successful open file command: " (pr-str command))
- (println "Failed to call open file command: " (pr-str command)))
- (when-not (string/blank? (:out result))
- (println "OUT:")
- (println (:out result)))
- (when-not (string/blank? (:err result))
- (println "ERR:")
- (println (:err result)))
- (flush))
- (catch Exception e
- (println "Figwheel: there was a problem running the open file command - "
- command)
- (println (.getMessage e))))
- (println "Figwheel: Can't open " (pr-str (vals (select-keys msg [:file-name :file-line :file-column])))
- "No :open-file-command supplied in the config."))))
+ (defn exec-open-file-command [open-file-command msg]
+ (when-let [msg (#'validate-file-selected-msg msg)]
+ (if-let [command (get-open-file-command open-file-command msg)]
+ (try
+ (let [result (apply shell/sh command)]
+ (if (zero? (:exit result))
+ (println "Successful open file command: " (pr-str command))
+ (println "Failed to call open file command: " (pr-str command)))
+ (when-not (string/blank? (:out result))
+ (println "OUT:")
+ (println (:out result)))
+ (when-not (string/blank? (:err result))
+ (println "ERR:")
+ (println (:err result)))
+ (flush))
+ (catch Exception e
+ (println "Figwheel: there was a problem running the open file command - "
+ command)
+ (println (.getMessage e))))
+ (println "Figwheel: Can't open " (pr-str (vals (select-keys msg [:file-name :file-line :file-column])))
+ "No :open-file-command supplied in the config."))))
-(defn setup [open-file-command]
- (figwheel.repl/add-listener
- [::open-editor open-file-command]
- (fn [{:keys [response] :as msg}]
- (when (= "file-selected" (:figwheel-event response))
- (exec-open-file-command open-file-command response)))))
+ (defn setup [open-file-command]
+ (figwheel.repl/add-listener
+ [::open-editor open-file-command]
+ (fn [{:keys [response] :as msg}]
+ (when (= "file-selected" (:figwheel-event response))
+ (exec-open-file-command open-file-command response)))))
-))
+ ))
diff --git a/src/figwheel/main/evalback.cljc b/src/figwheel/main/evalback.cljc
index 587c6d8..07c6f1e 100644
--- a/src/figwheel/main/evalback.cljc
+++ b/src/figwheel/main/evalback.cljc
@@ -28,80 +28,80 @@
msg {:figwheel-event "eval-back"
:form-string
(str
- "(figwheel.main.evalback/handle "
- (pr-str uniq) " "
- form-str ")")}]
+ "(figwheel.main.evalback/handle "
+ (pr-str uniq) " "
+ form-str ")")}]
(swap! handlers assoc uniq callback)
(figwheel.repl/respond-to-connection msg)))
(defn eval-cljs [form callback]
(eval-string (pr-str form) callback))
-)
+ )
:clj
(do
-(def timeout-val (Object.))
-
-(defrecord EvalOnConnectionEnv []
- cljs.repl/IJavaScriptEnv
- (-setup [this opts])
- (-evaluate [this _ _ js]
- (when-let [conn (::connection this)]
- (let [prom (promise)
- _ (frepl/send-for-response* prom conn {:op :eval :code js})]
- {:status :success :value prom})))
- (-load [this provides url])
- (-tear-down [_]))
-
-(defn read-cljs-string [form-str]
- (when-not (string/blank? form-str)
- (try
- {:form (binding [*ns* (create-ns ana/*cljs-ns*)
- reader/resolve-symbol ana/resolve-symbol
- reader/*data-readers* tags/*cljs-data-readers*
- reader/*alias-map*
- (apply merge
- ((juxt :requires :require-macros)
- (ana/get-namespace ana/*cljs-ns*)))]
- (reader/read {:read-cond :allow :features #{:cljs}}
- (readers/source-logging-push-back-reader
- (java.io.StringReader. form-str))))}
- (catch Exception e
- {:exception (Throwable->map e)}))))
-
-(defn eval-cljs [repl-env form]
- (cljs.repl/evaluate-form
- repl-env
- (assoc (ana/empty-env) :ns (ana/get-namespace ana/*cljs-ns*))
- "<cljs repl>"
- form
- (#'cljs.repl/wrap-fn form)))
-
-;; XXX this doesn't work very well in an environment with multiple connections
-;; needs to obtain the compiler-env for the individual build process
-;; if we add a build-id to the messages or find a way to look up a build-id
-;; from a session id we can get the compiler-env from the build-registry
-(let [repl-env (EvalOnConnectionEnv.)]
- (defn eval-back-atcha [{:keys [session-id response] :as msg} cenv]
- (try
- (when-let [conn (get @figwheel.repl/*connections* session-id)]
- (binding [cljs.env/*compiler* cenv]
- (when-let [form (:form (read-cljs-string (:form-string response)))]
- (let [repl-env (assoc repl-env ::connection conn)]
- (eval-cljs repl-env form)))))
- (catch Throwable e
- (log/error "Error in eval back" e)))))
-
-(defn setup []
- (let [cenv cljs.env/*compiler*]
- (figwheel.repl/add-listener
- ::evalback
- (fn [{:keys [response] :as msg}]
- (when (= "eval-back" (:figwheel-event response))
- (#'eval-back-atcha msg cenv))))))
-
-
-
-))
+ (def timeout-val (Object.))
+
+ (defrecord EvalOnConnectionEnv []
+ cljs.repl/IJavaScriptEnv
+ (-setup [this opts])
+ (-evaluate [this _ _ js]
+ (when-let [conn (::connection this)]
+ (let [prom (promise)
+ _ (frepl/send-for-response* prom conn {:op :eval :code js})]
+ {:status :success :value prom})))
+ (-load [this provides url])
+ (-tear-down [_]))
+
+ (defn read-cljs-string [form-str]
+ (when-not (string/blank? form-str)
+ (try
+ {:form (binding [*ns* (create-ns ana/*cljs-ns*)
+ reader/resolve-symbol ana/resolve-symbol
+ reader/*data-readers* tags/*cljs-data-readers*
+ reader/*alias-map*
+ (apply merge
+ ((juxt :requires :require-macros)
+ (ana/get-namespace ana/*cljs-ns*)))]
+ (reader/read {:read-cond :allow :features #{:cljs}}
+ (readers/source-logging-push-back-reader
+ (java.io.StringReader. form-str))))}
+ (catch Exception e
+ {:exception (Throwable->map e)}))))
+
+ (defn eval-cljs [repl-env form]
+ (cljs.repl/evaluate-form
+ repl-env
+ (assoc (ana/empty-env) :ns (ana/get-namespace ana/*cljs-ns*))
+ "<cljs repl>"
+ form
+ (#'cljs.repl/wrap-fn form)))
+
+ ;; XXX this doesn't work very well in an environment with multiple connections
+ ;; needs to obtain the compiler-env for the individual build process
+ ;; if we add a build-id to the messages or find a way to look up a build-id
+ ;; from a session id we can get the compiler-env from the build-registry
+ (let [repl-env (EvalOnConnectionEnv.)]
+ (defn eval-back-atcha [{:keys [session-id response] :as msg} cenv]
+ (try
+ (when-let [conn (get @figwheel.repl/*connections* session-id)]
+ (binding [cljs.env/*compiler* cenv]
+ (when-let [form (:form (read-cljs-string (:form-string response)))]
+ (let [repl-env (assoc repl-env ::connection conn)]
+ (eval-cljs repl-env form)))))
+ (catch Throwable e
+ (log/error "Error in eval back" e)))))
+
+ (defn setup []
+ (let [cenv cljs.env/*compiler*]
+ (figwheel.repl/add-listener
+ ::evalback
+ (fn [{:keys [response] :as msg}]
+ (when (= "eval-back" (:figwheel-event response))
+ (#'eval-back-atcha msg cenv))))))
+
+
+
+ ))
diff --git a/src/figwheel/main/helper.cljc b/src/figwheel/main/helper.cljc
index e3fc6fb..b8406e5 100644
--- a/src/figwheel/main/helper.cljc
+++ b/src/figwheel/main/helper.cljc
@@ -13,81 +13,81 @@
[goog Promise])))
#?(:cljs
- (do
+ (do
-(def sidebar-link-class "figwheel_main_content_link")
-(def sidebar-focus-class "figwheel_main_content_link_focus")
+ (def sidebar-link-class "figwheel_main_content_link")
+ (def sidebar-focus-class "figwheel_main_content_link_focus")
-(defn connected-signal []
- (some-> (gdom/getElement "connect-status")
- (classlist/add "connected")))
+ (defn connected-signal []
+ (some-> (gdom/getElement "connect-status")
+ (classlist/add "connected")))
-(defn on-disconnect []
- (some-> (gdom/getElement "connect-status")
- (classlist/remove "connected")))
+ (defn on-disconnect []
+ (some-> (gdom/getElement "connect-status")
+ (classlist/remove "connected")))
-(defonce resource-atom (atom {}))
+ (defonce resource-atom (atom {}))
-(defn get-content [url]
- (Promise.
- (fn [succ e]
- (if-let [res (get @resource-atom url)]
- (succ res)
- (xhr/send url
- (fn [resp]
- (some-> resp
- (gobj/get "currentTarget")
- (.getResponseText)
- (#(do (swap! resource-atom assoc url %)
- %))
- succ)))))))
+ (defn get-content [url]
+ (Promise.
+ (fn [succ e]
+ (if-let [res (get @resource-atom url)]
+ (succ res)
+ (xhr/send url
+ (fn [resp]
+ (some-> resp
+ (gobj/get "currentTarget")
+ (.getResponseText)
+ (#(do (swap! resource-atom assoc url %)
+ %))
+ succ)))))))
-(defn load-content [url div-id]
- (.then (get-content url)
- (fn [content]
- (gdom/getElement div-id)
- (set! (.-innerHTML (gdom/getElement div-id))
- content))))
+ (defn load-content [url div-id]
+ (.then (get-content url)
+ (fn [content]
+ (gdom/getElement div-id)
+ (set! (.-innerHTML (gdom/getElement div-id))
+ content))))
-(defn focus-anchor! [anchor-tag]
- (.forEach (gdom/getElementsByTagNameAndClass "a" sidebar-link-class)
- (fn [a]
- (classlist/remove a sidebar-focus-class)
- (when (= a anchor-tag)
- (classlist/add a sidebar-focus-class)))))
+ (defn focus-anchor! [anchor-tag]
+ (.forEach (gdom/getElementsByTagNameAndClass "a" sidebar-link-class)
+ (fn [a]
+ (classlist/remove a sidebar-focus-class)
+ (when (= a anchor-tag)
+ (classlist/add a sidebar-focus-class)))))
-(defn init-sidebar-link-actions! []
- (.forEach (gdom/getElementsByTagNameAndClass "a" sidebar-link-class)
- (fn [a]
- ;; pre-fetch
- (when-let [content-loc (.-rel a)]
- (get-content content-loc)
- (.addEventListener
- a "click"
- (fn [e]
- (.preventDefault e)
- (focus-anchor! a)
- (when-let [content-loc (.-rel (.-target e))]
- (load-content content-loc "main-content"))))))))
+ (defn init-sidebar-link-actions! []
+ (.forEach (gdom/getElementsByTagNameAndClass "a" sidebar-link-class)
+ (fn [a]
+ ;; pre-fetch
+ (when-let [content-loc (.-rel a)]
+ (get-content content-loc)
+ (.addEventListener
+ a "click"
+ (fn [e]
+ (.preventDefault e)
+ (focus-anchor! a)
+ (when-let [content-loc (.-rel (.-target e))]
+ (load-content content-loc "main-content"))))))))
-(defn on-connect [e]
- (init-sidebar-link-actions!)
- (connected-signal))
+ (defn on-connect [e]
+ (init-sidebar-link-actions!)
+ (connected-signal))
-(defonce initialize
- (do
- (.addEventListener js/document.body "figwheel.repl.connected"
- on-connect)
- (.addEventListener js/document.body "figwheel.repl.disconnected"
- on-disconnect)))
-))
+ (defonce initialize
+ (do
+ (.addEventListener js/document.body "figwheel.repl.connected"
+ on-connect)
+ (.addEventListener js/document.body "figwheel.repl.disconnected"
+ on-disconnect)))
+ ))
#?(:clj
- (do
- (defn main-wrapper [{:keys [body output-to header app-div-class sidebar]
- :or {app-div-class "app"
- sidebar true} :as options}]
- (format
+ (do
+ (defn main-wrapper [{:keys [body output-to header app-div-class sidebar]
+ :or {app-div-class "app"
+ sidebar true} :as options}]
+ (format
"<!DOCTYPE html>
<html>
<head>
@@ -165,128 +165,128 @@
:else "")
(str body)
(str
- (when-not (:dev-mode options)
- "<script src=\"/com/bhauman/figwheel/helper.js\"></script>"))
+ (when-not (:dev-mode options)
+ "<script src=\"/com/bhauman/figwheel/helper.js\"></script>"))
(str
- (when (and output-to
- (.isFile (io/file output-to)))
- (-> (slurp output-to)
- (string/replace #"<\/script" "<\\\\/script"))))))
+ (when (and output-to
+ (.isFile (io/file output-to)))
+ (-> (slurp output-to)
+ (string/replace #"<\/script" "<\\\\/script"))))))
-(defn main-action [req options]
- {:status 200
- :headers {"Content-Type" "text/html"}
- :body (main-wrapper options)})
+ (defn main-action [req options]
+ {:status 200
+ :headers {"Content-Type" "text/html"}
+ :body (main-wrapper options)})
-(defn dev-endpoint [req]
- (let [method-uri ((juxt :request-method :uri) req)]
- (when (= method-uri [:get "/"])
- (main-action req {:output-to "target/public/cljs-out/helper-main.js"
- :dev-mode true
- :header "Dev Mode"
- :body (slurp (io/resource "public/com/bhauman/figwheel/helper/content/repl_welcome.html"))}))))
+ (defn dev-endpoint [req]
+ (let [method-uri ((juxt :request-method :uri) req)]
+ (when (= method-uri [:get "/"])
+ (main-action req {:output-to "target/public/cljs-out/helper-main.js"
+ :dev-mode true
+ :header "Dev Mode"
+ :body (slurp (io/resource "public/com/bhauman/figwheel/helper/content/repl_welcome.html"))}))))
-(defn middleware [handler options]
- (fn [req]
- (let [method-uri ((juxt :request-method :uri) req)]
- (cond
- (and (= [:get "/figwheel/helper/welcome"] method-uri) (:body options))
- {:status 200
- :headers {"Content-Type" "text/html"}
- :body (:body options)}
- (= method-uri [:get "/"])
- (main-action req options)
- :else (handler req)))))
+ (defn middleware [handler options]
+ (fn [req]
+ (let [method-uri ((juxt :request-method :uri) req)]
+ (cond
+ (and (= [:get "/figwheel/helper/welcome"] method-uri) (:body options))
+ {:status 200
+ :headers {"Content-Type" "text/html"}
+ :body (:body options)}
+ (= method-uri [:get "/"])
+ (main-action req options)
+ :else (handler req)))))
-(defn missing-index-middleware [handler options]
- (fn [r]
- (let [method-uri ((juxt :request-method :uri) r)]
- (cond
- (and (= [:get "/figwheel/helper/welcome"] method-uri)
- (:body options))
- {:status 200
- :headers {"Content-Type" "text/html"}
- :body (:body options)}
- :else
- (let [res (handler r)]
- (if (and (= [:get "/"] method-uri)
- (= 404 (:status res)))
- (main-action r options)
- res))))))
+ (defn missing-index-middleware [handler options]
+ (fn [r]
+ (let [method-uri ((juxt :request-method :uri) r)]
+ (cond
+ (and (= [:get "/figwheel/helper/welcome"] method-uri)
+ (:body options))
+ {:status 200
+ :headers {"Content-Type" "text/html"}
+ :body (:body options)}
+ :else
+ (let [res (handler r)]
+ (if (and (= [:get "/"] method-uri)
+ (= 404 (:status res)))
+ (main-action r options)
+ res))))))
-(defn default-index-code [output-to]
- (let [path (best-guess-script-path output-to)]
- (str
- "<div class=\"CodeRay\">"
- "<div class=\"code\">"
- "<pre>"
- "&lt;!DOCTYPE html&gt;\n"
- "&lt;html&gt;\n"
- " &lt;head&gt;\n"
- " &lt;meta charset=\"UTF-8\"&gt;\n"
- " &lt;/head&gt;\n"
- " &lt;body&gt;\n"
- " &lt;div id=\"app\"&gt;\n"
- " &lt;/div&gt;\n"
- " &lt;script src=\""
- (if path path
- (str "[correct-path-to "
- (or output-to "main.js file")
- "]"))
- "\" type=\"text/javascript\"&gt;&lt;/script&gt;\n"
- " &lt;/body&gt;\n"
- "&lt;/html&gt;\n"
- "</pre></div></div>")))
+ (defn default-index-code [output-to]
+ (let [path (best-guess-script-path output-to)]
+ (str
+ "<div class=\"CodeRay\">"
+ "<div class=\"code\">"
+ "<pre>"
+ "&lt;!DOCTYPE html&gt;\n"
+ "&lt;html&gt;\n"
+ " &lt;head&gt;\n"
+ " &lt;meta charset=\"UTF-8\"&gt;\n"
+ " &lt;/head&gt;\n"
+ " &lt;body&gt;\n"
+ " &lt;div id=\"app\"&gt;\n"
+ " &lt;/div&gt;\n"
+ " &lt;script src=\""
+ (if path path
+ (str "[correct-path-to "
+ (or output-to "main.js file")
+ "]"))
+ "\" type=\"text/javascript\"&gt;&lt;/script&gt;\n"
+ " &lt;/body&gt;\n"
+ "&lt;/html&gt;\n"
+ "</pre></div></div>")))
-(defn missing-index [handler options]
- (missing-index-middleware
- handler
- (merge
- {:header "Figwheel Default Dev Page"
- :body (str
- (slurp (io/resource "public/com/bhauman/figwheel/helper/content/missing_index.html"))
- (default-index-code (:output-to options)))}
- options)))
+ (defn missing-index [handler options]
+ (missing-index-middleware
+ handler
+ (merge
+ {:header "Figwheel Default Dev Page"
+ :body (str
+ (slurp (io/resource "public/com/bhauman/figwheel/helper/content/missing_index.html"))
+ (default-index-code (:output-to options)))}
+ options)))
-(defn extra-main-body [nm output-to]
- (str (format (str "<h1>Host page for <code>:%s</code> main file</h1>"
- "<blockquote>You can override the content of this "
- "page by replacing the contents of the <code>app-%s</code> "
- "div.</blockquote><p></p>"
- "<blockquote>You can create your own "
- "<a href=\"https://figwheel.org/docs/your_own_page.html\" target=\"_blank\">host page</a> "
- "for this extra main by including the "
- "<code>%s</code> bootstrap script in your host page. "
- "If you are unsure how to create a host page please see this "
- "<a href=\"https://figwheel.org/docs/your_own_page.html\" target=\"_blank\">documentation</a>. "
- "</blockquote>") nm nm (if (string/includes? output-to "/public/")
- (str "/" (second (string/split output-to #"\/public\/")))
- (format "/cljs-out/[build-id]-main-%s.js" nm)))))
+ (defn extra-main-body [nm output-to]
+ (str (format (str "<h1>Host page for <code>:%s</code> main file</h1>"
+ "<blockquote>You can override the content of this "
+ "page by replacing the contents of the <code>app-%s</code> "
+ "div.</blockquote><p></p>"
+ "<blockquote>You can create your own "
+ "<a href=\"https://figwheel.org/docs/your_own_page.html\" target=\"_blank\">host page</a> "
+ "for this extra main by including the "
+ "<code>%s</code> bootstrap script in your host page. "
+ "If you are unsure how to create a host page please see this "
+ "<a href=\"https://figwheel.org/docs/your_own_page.html\" target=\"_blank\">documentation</a>. "
+ "</blockquote>") nm nm (if (string/includes? output-to "/public/")
+ (str "/" (second (string/split output-to #"\/public\/")))
+ (format "/cljs-out/[build-id]-main-%s.js" nm)))))
-(defn extra-main-hosting [handler
- name-output-to-map]
- (if (not-empty name-output-to-map)
- (fn [req]
- (let [[method uri] ((juxt :request-method :uri) req)]
- (if (and (= :get method)
- (string/starts-with? uri "/figwheel-extra-main/"))
- (let [nm (string/replace uri "/figwheel-extra-main/" "")]
- (if-let [output-to (name-output-to-map nm)]
- (main-action req {:output-to output-to
- :header (format "Extra Main: %s Host Page" (string/capitalize nm))
- :app-div-class (str "app-" nm)
- :sidebar false
- :body (extra-main-body nm output-to)})
- (handler req)))
- (handler req))))
- handler))
+ (defn extra-main-hosting [handler
+ name-output-to-map]
+ (if (not-empty name-output-to-map)
+ (fn [req]
+ (let [[method uri] ((juxt :request-method :uri) req)]
+ (if (and (= :get method)
+ (string/starts-with? uri "/figwheel-extra-main/"))
+ (let [nm (string/replace uri "/figwheel-extra-main/" "")]
+ (if-let [output-to (name-output-to-map nm)]
+ (main-action req {:output-to output-to
+ :header (format "Extra Main: %s Host Page" (string/capitalize nm))
+ :app-div-class (str "app-" nm)
+ :sidebar false
+ :body (extra-main-body nm output-to)})
+ (handler req)))
+ (handler req))))
+ handler))
-(defn serve-only-middleware [handler options]
- (missing-index-middleware
- handler
- (merge
- {:header "Server Only Page"
- :body (slurp (io/resource "public/com/bhauman/figwheel/helper/content/server_only_welcome.html"))}
- options)))
+ (defn serve-only-middleware [handler options]
+ (missing-index-middleware
+ handler
+ (merge
+ {:header "Server Only Page"
+ :body (slurp (io/resource "public/com/bhauman/figwheel/helper/content/server_only_welcome.html"))}
+ options)))
-)) ;; clj conditional reader end
+ )) ;; clj conditional reader end
diff --git a/src/figwheel/main/logging.clj b/src/figwheel/main/logging.clj
index 4310fa9..fd19de7 100644
--- a/src/figwheel/main/logging.clj
+++ b/src/figwheel/main/logging.clj
@@ -40,9 +40,9 @@
(let [levels-map* (merge levels-map {:all Level/ALL :off Level/OFF})]
(fn [^java.util.logging.Logger logger level]
(some->>
- level
- (get levels-map*)
- (.setLevel logger))))})
+ level
+ (get levels-map*)
+ (.setLevel logger))))})
(defn format-log-record [^LogRecord record]
(let [lvl (.getLevel record)]
@@ -95,10 +95,10 @@
(alter-var-root #'ap/*use-color* (fn [_] false))
(remove-handlers *logger*)
(.addHandler
- *logger*
- (doto (FileHandler. fname)
- (.setFormatter fig-formatter)
- (.setLevel java.util.logging.Level/ALL))))
+ *logger*
+ (doto (FileHandler. fname)
+ (.setFormatter fig-formatter)
+ (.setLevel java.util.logging.Level/ALL))))
(defn set-level [lvl-key]
(fwsetlevel! *logger* lvl-key))
@@ -174,16 +174,16 @@
"s ") %)]
(apply vector :lines
(map
- (fn [[k n s]]
- (condp = k
- :code-line [:yellow (number-fn n) s "\n"]
- :error-in-code [:line [:yellow (number-fn n) ] [:bright s] "\n"]
- :error-message [:yellow (number-fn "") (first (string/split s #"\^---")) "^---\n"]))
- ;; only one error message
- (let [[pre post] (split-with #(not= :error-message (first %)) data)]
- (concat pre (take 1 post)
- (filter #(not= :error-message (first %))
- post)))))))
+ (fn [[k n s]]
+ (condp = k
+ :code-line [:yellow (number-fn n) s "\n"]
+ :error-in-code [:line [:yellow (number-fn n) ] [:bright s] "\n"]
+ :error-message [:yellow (number-fn "") (first (string/split s #"\^---")) "^---\n"]))
+ ;; only one error message
+ (let [[pre post] (split-with #(not= :error-message (first %)) data)]
+ (concat pre (take 1 post)
+ (filter #(not= :error-message (first %))
+ post)))))))
(defn except-data->format-data [{:keys [message] :as except-data}]
[:exception
@@ -220,20 +220,20 @@
[:lines
[:line [:yellow (str type)] "\n"]
(vec (cons
- :lines
- (map
- format-trace-line
- (take 30
- (:trace tm)))))])))
+ :lines
+ (map
+ format-trace-line
+ (take 30
+ (:trace tm)))))])))
(defn syntax-exception [e]
(let [ex (exception-with-excerpt e)]
(info
- (format-str
- (if (and (nil? (:message ex))
- (nil? (:file-excerpt ex)))
- (format-stacktrace-ex ex)
- (format-ex ex))))))
+ (format-str
+ (if (and (nil? (:message ex))
+ (nil? (:file-excerpt ex)))
+ (format-stacktrace-ex ex)
+ (format-ex ex))))))
(defn cljs-syntax-warning [warning]
(-> (figwheel.core/warning-info warning)
diff --git a/src/figwheel/main/npm.clj b/src/figwheel/main/npm.clj
index fa50ba2..3ae804d 100644
--- a/src/figwheel/main/npm.clj
+++ b/src/figwheel/main/npm.clj
@@ -55,10 +55,10 @@
(defn index-js-from-data [data]
(string/join
- "\n"
- (concat
- (map import-statement data)
- (mapcat window-statements data))))
+ "\n"
+ (concat
+ (map import-statement data)
+ (mapcat window-statements data))))
;; ------------------------------------------------------------
;; foreign-libs-entry
@@ -94,18 +94,18 @@
(defn check-that-files-exist [[bundle-file js-index-file]]
(when (not (.isFile (io/file bundle-file)))
(throw (ex-info
- (format "Webpack: bundle file '%s' doesn't exist. Make sure you have generated the bundle." bundle-file)
- {:figwheel.main/error true})))
+ (format "Webpack: bundle file '%s' doesn't exist. Make sure you have generated the bundle." bundle-file)
+ {:figwheel.main/error true})))
(when (not (.isFile (io/file js-index-file)))
(throw (ex-info
- (format "Webpack: index file '%s' containing imports does not exist." js-index-file)
- {:figwheel.main/error true})))
+ (format "Webpack: index file '%s' containing imports does not exist." js-index-file)
+ {:figwheel.main/error true})))
[bundle-file js-index-file])
(defn bundles->foreign-libs [bundles]
(mapv
- (comp bundle->foreign-lib check-that-files-exist)
- bundles))
+ (comp bundle->foreign-lib check-that-files-exist)
+ bundles))
(defn config [{:keys [:figwheel.main/config] :as cfg}]
(if-let [{:keys [bundles]} (:npm config)]
@@ -128,8 +128,8 @@
(comment
;; example data
-(def index-file
- "import React from 'react';
+ (def index-file
+ "import React from 'react';
import ReactDom from 'react-dom';
import CreateReactClass from 'create-react-class';
import SlatePlainSerializer from 'slate-plain-serializer';
@@ -145,8 +145,8 @@ window[\"ouchy-ouch\"] = Change;
window['ouchy-oucher'] = Change;
")
-(def index-data
- {:react 'react
- :react-dom 'react-dom
- [[:change :as :slate-change]] 'slate})
-)
+ (def index-data
+ {:react 'react
+ :react-dom 'react-dom
+ [[:change :as :slate-change]] 'slate})
+ )
diff --git a/src/figwheel/main/schema/cli.clj b/src/figwheel/main/schema/cli.clj
index eabaad0..6a80b89 100644
--- a/src/figwheel/main/schema/cli.clj
+++ b/src/figwheel/main/schema/cli.clj
@@ -105,8 +105,8 @@ resource paths should start with @")
(defn build-exists? [b]
(every?
- file-exists?
- (map #(str % ".cljs.edn") (string/split b #":"))))
+ file-exists?
+ (map #(str % ".cljs.edn") (string/split b #":"))))
(exp/def ::not-end-with-cljs-edn #(not (string/ends-with? % ".cljs.edn"))
"should not end with .cljs.edn as this is already implied\n(this should be maria if you have a maria.cljs.edn file)")
@@ -157,23 +157,23 @@ resource paths should start with @")
(s/def ::init-opts
(s/alt
- :compile-opts ::compile-opts
- :output-dir ::output-dir
- :repl-opts ::repl-opts
- :figwheel-opts ::figwheel-opts
- :target ::target
- :init ::init
- :eval ::eval
- :verbose ::verbose
- :optimizations ::optimizations
- :background-build ::background-build
- :figwheel ::figwheel
- :output-to ::output-to
- :print-config ::print-config
- :watch ::watch
- :port ::port
- :host ::host
- :ring-handler ::ring-handler))
+ :compile-opts ::compile-opts
+ :output-dir ::output-dir
+ :repl-opts ::repl-opts
+ :figwheel-opts ::figwheel-opts
+ :target ::target
+ :init ::init
+ :eval ::eval
+ :verbose ::verbose
+ :optimizations ::optimizations
+ :background-build ::background-build
+ :figwheel ::figwheel
+ :output-to ::output-to
+ :print-config ::print-config
+ :watch ::watch
+ :port ::port
+ :host ::host
+ :ring-handler ::ring-handler))
;; TODO
@@ -235,21 +235,21 @@ resource paths should start with @")
(s/def ::help #{"-h" "--help" "-?"})
(s/def ::main-opts (s/alt
- :stdin ::stdin
- :script ::script
- :build (s/cat :opt ::build
- :repl-serve (s/? ::repl-or-serve))
- :compile-ns (s/cat :flag #{"-c" "--compile"}
- :ns ::cljs-namespace-available
- :repl-serve (s/? ::repl-or-serve))
- :compile (s/cat :flag #{"-c" "--compile"}
- :repl-serve (s/? ::repl-or-serve))
- :build-once (s/cat :opt ::build-once
- :repl-serve (s/? ::serve))
- :help ::help
- :repl ::repl
- :serve ::serve
- :main ::main))
+ :stdin ::stdin
+ :script ::script
+ :build (s/cat :opt ::build
+ :repl-serve (s/? ::repl-or-serve))
+ :compile-ns (s/cat :flag #{"-c" "--compile"}
+ :ns ::cljs-namespace-available
+ :repl-serve (s/? ::repl-or-serve))
+ :compile (s/cat :flag #{"-c" "--compile"}
+ :repl-serve (s/? ::repl-or-serve))
+ :build-once (s/cat :opt ::build-once
+ :repl-serve (s/? ::serve))
+ :help ::help
+ :repl ::repl
+ :serve ::serve
+ :main ::main))
(s/def ::cli-options (s/cat :inits (s/* ::init-opts)
:mains (s/? ::main-opts)))
@@ -423,9 +423,9 @@ resource paths should start with @")
(and (integer? pos) (not (zero? pos))))
(nth val (dec (first in))))]
(first (filter
- (fn [[kys v]]
- ((set kys) flag))
- (apply concat ((juxt :main :init) cljs.cli/default-commands))))))
+ (fn [[kys v]]
+ ((set kys) flag))
+ (apply concat ((juxt :main :init) cljs.cli/default-commands))))))
(let [expected-str (deref #'exp/expected-str)]
(defn expected-str-with-doc [_type spec-name val path problems opts]
@@ -433,20 +433,20 @@ resource paths should start with @")
(when-let [[flags {:keys [doc]}] (doc-for-flag val (first problems))]
(when doc
(str
- "\n\n__ Doc for " (string/join " " flags) " _____\n\n"
- (printer/indent (string/join "\n" (#'cljs.cli/auto-fill doc 65)))))))))
+ "\n\n__ Doc for " (string/join " " flags) " _____\n\n"
+ (printer/indent (string/join "\n" (#'cljs.cli/auto-fill doc 65)))))))))
#_(defn validate-cli [cli-options]
- (when-let [data' (s/explain-data ::cli-options cli-options)]
- (let [data (update-problems
- (add-problem-types
- data'))]
- #_(clojure.pprint/pprint data)
- (with-redefs [exp/expected-str expected-str-with-doc]
- (with-out-str
- ((exp/custom-printer {:print-specs? false
- :show-valid-values? true})
- data))))))
+ (when-let [data' (s/explain-data ::cli-options cli-options)]
+ (let [data (update-problems
+ (add-problem-types
+ data'))]
+ #_(clojure.pprint/pprint data)
+ (with-redefs [exp/expected-str expected-str-with-doc]
+ (with-out-str
+ ((exp/custom-printer {:print-specs? false
+ :show-valid-values? true})
+ data))))))
;; ----------------------------------------------------------------------
;; ensure the opts respect group
@@ -457,24 +457,24 @@ resource paths should start with @")
(s/def ::cli-options-no-repl-env
;; include all opts except -i -e and -v
(s/cat :inits (s/*
- (s/alt
- :compile-opts ::compile-opts
- :output-dir ::output-dir
- :repl-opts ::repl-opts
- :figwheel-opts ::figwheel-opts
- :target ::target
- ;:init ::init
- ;:eval ::eval
- ;:verbose ::verbose
- :optimizations ::optimizations
- :background-build ::background-build
- :figwheel ::figwheel
- :output-to ::output-to
- :print-config ::print-config
- :watch ::watch
- :port ::port
- :host ::host
- :ring-handler ::ring-handler))
+ (s/alt
+ :compile-opts ::compile-opts
+ :output-dir ::output-dir
+ :repl-opts ::repl-opts
+ :figwheel-opts ::figwheel-opts
+ :target ::target
+ ;:init ::init
+ ;:eval ::eval
+ ;:verbose ::verbose
+ :optimizations ::optimizations
+ :background-build ::background-build
+ :figwheel ::figwheel
+ :output-to ::output-to
+ :print-config ::print-config
+ :watch ::watch
+ :port ::port
+ :host ::host
+ :ring-handler ::ring-handler))
:mains (s/? ::main-opts)))
#_(let [mains [:compile {:flag "-c", :repl-serve [:repl {:flag "-r"}]}]]
@@ -488,44 +488,44 @@ resource paths should start with @")
(update error
::s/problems
#(mapv
- (fn [x]
- (let [res (assoc x
- :expound.spec.problem/type ::missing-main-opt
- ::conformed-mains mains
- ::should-have-main-opt
- ["--repl" "--main" "-r" "-m" "-" "[cljs script]"])]
- (cond
- (empty? mains) res
- (and (#{:compile :compile-ns :build} (first mains))
- (-> mains second :repl-serve nil? ))
- (assoc res ::should-have-main-opt ["--repl" "-r"])
- :else
- (assoc res
- :expound.spec.problem/type
- ::incompatible-flag-for-main-opt))))
- %)))))
+ (fn [x]
+ (let [res (assoc x
+ :expound.spec.problem/type ::missing-main-opt
+ ::conformed-mains mains
+ ::should-have-main-opt
+ ["--repl" "--main" "-r" "-m" "-" "[cljs script]"])]
+ (cond
+ (empty? mains) res
+ (and (#{:compile :compile-ns :build} (first mains))
+ (-> mains second :repl-serve nil? ))
+ (assoc res ::should-have-main-opt ["--repl" "-r"])
+ :else
+ (assoc res
+ :expound.spec.problem/type
+ ::incompatible-flag-for-main-opt))))
+ %)))))
(s/def ::cli-options-no-compile
;; include all opts except compile opts
(s/cat :inits (s/*
- (s/alt
- :compile-opts ::compile-opts
- :output-dir ::output-dir
- :repl-opts ::repl-opts
- :figwheel-opts ::figwheel-opts
- :target ::target
- :init ::init
- :eval ::eval
- :verbose ::verbose
- ;:optimizations ::optimizations
- ;:background-build ::background-build
- ;:figwheel ::figwheel
- ;:output-to ::output-to
- :print-config ::print-config
- ;:watch ::watch
- :port ::port
- :host ::host
- :ring-handler ::ring-handler))
+ (s/alt
+ :compile-opts ::compile-opts
+ :output-dir ::output-dir
+ :repl-opts ::repl-opts
+ :figwheel-opts ::figwheel-opts
+ :target ::target
+ :init ::init
+ :eval ::eval
+ :verbose ::verbose
+ ;:optimizations ::optimizations
+ ;:background-build ::background-build
+ ;:figwheel ::figwheel
+ ;:output-to ::output-to
+ :print-config ::print-config
+ ;:watch ::watch
+ :port ::port
+ :host ::host
+ :ring-handler ::ring-handler))
:mains (s/? ::main-opts)))
(defn not-compile-opt [{:keys [inits mains] :as conformed} cli-options]
@@ -534,32 +534,32 @@ resource paths should start with @")
(update error
::s/problems
#(mapv
- (fn [x]
- (let [res (assoc x
- :expound.spec.problem/type ::missing-main-opt
- ::conformed-mains mains
- ::should-have-main-opt
- ["--compile" "--build" "--build-once"
- "-c" "-b" "-bo"])]
- (if (empty? mains)
- res
- (assoc res
- :expound.spec.problem/type
- ::incompatible-flag-for-main-opt))))
- %)))))
+ (fn [x]
+ (let [res (assoc x
+ :expound.spec.problem/type ::missing-main-opt
+ ::conformed-mains mains
+ ::should-have-main-opt
+ ["--compile" "--build" "--build-once"
+ "-c" "-b" "-bo"])]
+ (if (empty? mains)
+ res
+ (assoc res
+ :expound.spec.problem/type
+ ::incompatible-flag-for-main-opt))))
+ %)))))
(defn get-explain-data [cli-options]
(or (s/explain-data ::cli-options cli-options)
(let [conformed (s/conform ::cli-options cli-options)]
(or
- (not-repl-env-opt conformed cli-options)
- (not-compile-opt conformed cli-options)))))
+ (not-repl-env-opt conformed cli-options)
+ (not-compile-opt conformed cli-options)))))
(defn validate-cli-extra [cli-options]
(if-let [data' (get-explain-data cli-options)]
(let [data (update-problems
- (add-problem-types
- data'))]
+ (add-problem-types
+ data'))]
#_(clojure.pprint/pprint data)
(with-redefs [exp/expected-str expected-str-with-doc]
(with-out-str
@@ -615,8 +615,8 @@ resource paths should start with @")
(defmethod exp/problem-group-str ::missing-main-opt [_type spec-name val path problems opts]
(spell-exp/exp-formated
- "Missing main option"
- _type spec-name val path problems opts))
+ "Missing main option"
+ _type spec-name val path problems opts))
(defmethod exp/expected-str ::missing-main-opt [_type spec-name val path problems opts]
(let [{:keys [::should-have-main-opt] :as prob} (first problems)
@@ -630,11 +630,11 @@ resource paths should start with @")
mains (not-empty (flatten (s/unform ::cli-options {:mains conformed-mains})))]
(prn conformed-mains mains)
(spell-exp/exp-formated
- (str "Incompatible flag for main option"
- (when mains
- (str "s: " (string/join " " mains)))
- " ---")
- _type spec-name val path problems opts)))
+ (str "Incompatible flag for main option"
+ (when mains
+ (str "s: " (string/join " " mains)))
+ " ---")
+ _type spec-name val path problems opts)))
(defmethod exp/expected-str ::incompatible-flag-for-main-opt
[_type spec-name val path problems opts]
@@ -645,9 +645,9 @@ resource paths should start with @")
(defmethod exp/problem-group-str ::missing-build-file [_type spec-name val path problems opts]
(spell-exp/exp-formated
- (str "Build file " (first (::missing-files (first problems)))
- ".cljs.edn not found" )
- _type spec-name val path problems opts))
+ (str "Build file " (first (::missing-files (first problems)))
+ ".cljs.edn not found" )
+ _type spec-name val path problems opts))
(defmethod exp/expected-str ::missing-build-file
[_type spec-name val path problems opts]
diff --git a/src/figwheel/main/schema/cljs_options.clj b/src/figwheel/main/schema/cljs_options.clj
index 34d5b49..b9a983c 100644
--- a/src/figwheel/main/schema/cljs_options.clj
+++ b/src/figwheel/main/schema/cljs_options.clj
@@ -10,13 +10,13 @@
;; ** Top level util specs
(s/def ::string-or-symbol (s/or
- :symbol ::schema/unquoted-symbol
- :string non-blank-string?))
+ :symbol ::schema/unquoted-symbol
+ :string non-blank-string?))
(s/def ::string-or-named (s/or
- :symbol ::schema/unquoted-symbol
- :string non-blank-string?
- :keyword keyword?))
+ :symbol ::schema/unquoted-symbol
+ :string non-blank-string?
+ :keyword keyword?))
;; ** CLJS Compiler Options
;; *** Commonly used Compiler Options
@@ -195,7 +195,7 @@ https://gist.github.com/swannodette/4fc9ccc13f62c66456daf19c47692799")
(s/def ::foreign-libs (s/every
- (spell/keys
+ (spell/keys
:req-un [::file]
:opt-un [::file-min
::provides
@@ -203,11 +203,11 @@ https://gist.github.com/swannodette/4fc9ccc13f62c66456daf19c47692799")
::module-type
::preprocess
::global-exports])
- :into []
- :kind sequential?))
+ :into []
+ :kind sequential?))
(def-spec-meta ::foreign-libs
:doc
- "Adds dependencies on foreign libraries. Be sure that the url returns a
+ "Adds dependencies on foreign libraries. Be sure that the url returns a
HTTP Code 200
Defaults to the empty vector []
@@ -261,7 +261,7 @@ keys have these semantics:
(s/def ::externs (s/every non-blank-string? :min-count 1 :into [] :kind sequential?))
(def-spec-meta ::externs
:doc
- "Configure externs files for external libraries.
+ "Configure externs files for external libraries.
For this option, and those below, you can find a very good explanation at:
http://lukevanderhart.com/2011/09/30/using-javascript-and-clojurescript.html
@@ -271,14 +271,14 @@ Defaults to the empty vector [].
:externs [\"jquery-externs.js\"]")
(s/def ::modules (s/map-of
- keyword?
- (spell/keys
+ keyword?
+ (spell/keys
:opt-un [::entries
:cljs.options-schema.modules/output-to
::depends-on])))
(def-spec-meta ::modules
:doc
- "A new option for emitting Google Closure Modules. Closure Modules
+ "A new option for emitting Google Closure Modules. Closure Modules
supports splitting up an optimized build into N different modules. If
:modules is supplied it replaces the single :output-to. A module needs
a name, an individual :output-to file path, :entries a set of
@@ -333,7 +333,7 @@ single source map to name.")
(s/def ::source-map-path string?)
(def-spec-meta ::source-map-path
:doc
- "Set the path to source files references in source maps to avoid
+ "Set the path to source files references in source maps to avoid
further web server configuration.
:source-map-path \"public/js\"")
@@ -341,7 +341,7 @@ further web server configuration.
(s/def ::source-map-asset-path string?)
(def-spec-meta ::source-map-asset-path
:doc
- "Provides fine grained control over the sourceMappingURL comment that
+ "Provides fine grained control over the sourceMappingURL comment that
is appended to generated JavaScript files when source mapping is enabled.
further web server configuration.
@@ -350,7 +350,7 @@ further web server configuration.
(s/def ::source-map-timestamp boolean?)
(def-spec-meta ::source-map-timestamp
:doc
- "Add cache busting timestamps to source map urls. This is helpful for
+ "Add cache busting timestamps to source map urls. This is helpful for
keeping source maps up to date when live reloading code.
:source-map-timestamp true")
@@ -358,7 +358,7 @@ keeping source maps up to date when live reloading code.
(s/def ::cache-analysis boolean?)
(def-spec-meta ::cache-analysis
:doc
- "Experimental. Cache compiler analysis to disk. This enables faster
+ "Experimental. Cache compiler analysis to disk. This enables faster
cold build and REPL start up times.
For REPLs, defaults to true. Otherwise, defaults to true if and only
@@ -370,7 +370,7 @@ if :optimizations is :none.
(s/def ::recompile-dependents boolean?)
(def-spec-meta ::recompile-dependents
:doc
- "For correctness the ClojureScript compiler now always recompiles
+ "For correctness the ClojureScript compiler now always recompiles
dependent namespaces when a parent namespace changes. This prevents
corrupted builds and swallowed warnings. However this can impact
compile times depending on the structure of the application. This
@@ -381,7 +381,7 @@ option defaults to true.
(s/def ::static-fns boolean?)
(def-spec-meta ::static-fns
:doc
- "Employs static dispatch to specific function arities in emitted
+ "Employs static dispatch to specific function arities in emitted
JavaScript, as opposed to making use of the call construct. Defaults
to false except under advanced optimizations. Useful to have set to
false at REPL development to facilitate function redefinition, and
@@ -395,7 +395,7 @@ compiled with :static-fns implicitly set to true.
(s/def ::load-tests boolean?)
(def-spec-meta ::load-tests
:doc
- "This flag will cause deftest from cljs.test to be ignored if false.
+ "This flag will cause deftest from cljs.test to be ignored if false.
Useful for production if deftest has been used in the production classpath.
@@ -406,7 +406,7 @@ Default is true. Has the same effect as binding cljs.analyzer/*load-tests*.
(s/def ::elide-asserts boolean?)
(def-spec-meta ::elide-asserts
:doc
- "This flag will cause all (assert x) calls to be removed during
+ "This flag will cause all (assert x) calls to be removed during
compilation, including implicit asserts associated with :pre and :post
conditions. Useful for production. Default is always false even in
advanced compilation. Does NOT specify goog.asserts.ENABLE_ASSERTS,
@@ -421,7 +421,7 @@ the elision.
(s/def ::pseudo-names boolean?)
(def-spec-meta ::pseudo-names
:doc
- "With :advanced mode optimizations, determines whether readable names
+ "With :advanced mode optimizations, determines whether readable names
are emitted. This can be useful when debugging issues in the optimized
JavaScript and can aid in finding missing externs. Defaults to false.
@@ -430,7 +430,7 @@ JavaScript and can aid in finding missing externs. Defaults to false.
(s/def ::print-input-delimiter boolean?)
(def-spec-meta ::print-input-delimiter
:doc
- "Determines whether comments will be output in the JavaScript that can
+ "Determines whether comments will be output in the JavaScript that can
be used to determine the original source of the compiled code.
Defaults to false.
@@ -440,7 +440,7 @@ Defaults to false.
(s/def ::output-wrapper boolean?)
(def-spec-meta ::output-wrapper
:doc
- "Wrap the JavaScript output in (function(){...};)() to avoid clobbering
+ "Wrap the JavaScript output in (function(){...};)() to avoid clobbering
globals. Defaults to false.
:output-wrapper false")
@@ -449,7 +449,7 @@ globals. Defaults to false.
(s/def ::libs (s/every string? :min-count 1 :into [] :kind sequential?))
(def-spec-meta ::libs
:doc
- "Adds dependencies on external js libraries, i.e. Google
+ "Adds dependencies on external js libraries, i.e. Google
Closure-compatible javascript files with correct goog.provides() and
goog.requires() calls. Note that files in these directories will be
watched and a rebuild will occur if they are modified.
@@ -467,7 +467,7 @@ Defaults to the empty vector []
(s/def ::preamble (s/every non-blank-string? :min-count 1 :into [] :kind sequential?))
(def-spec-meta ::preamble
:doc
- "Prepends the contents of the given files to each output file. Only
+ "Prepends the contents of the given files to each output file. Only
valid with optimizations other than :none.
Defaults to the empty vector []
@@ -478,7 +478,7 @@ Defaults to the empty vector []
(s/def ::hashbang boolean?)
(def-spec-meta ::hashbang
:doc
- "When using :target :nodejs the compiler will emit a shebang as the
+ "When using :target :nodejs the compiler will emit a shebang as the
first line of the compiled source, making it executable. When your
intention is to build a node.js module, instead of executable, use
this option to remove the shebang.
@@ -488,7 +488,7 @@ this option to remove the shebang.
(s/def ::compiler-stats boolean?)
(def-spec-meta ::compiler-stats
:doc
- "Report basic timing measurements on compiler activity.
+ "Report basic timing measurements on compiler activity.
Defaults to false.
@@ -531,7 +531,7 @@ Defaults to :ecmascript5
(s/def ::language-out ::closure-language-in-out-opts)
(def-spec-meta ::language-out
:doc
- "Configure the input and output languages for the closure library. May be:
+ "Configure the input and output languages for the closure library. May be:
* :ecmascript-next identical to :es-next
* :ecmascript-2017 identical to :es-2017
@@ -550,13 +550,13 @@ Defaults to :no-transpile
:language-out :ecmascript3")
(s/def ::closure-defines (s/map-of
- ::string-or-symbol
- (some-fn number?
- string?
- boolean?)))
+ ::string-or-symbol
+ (some-fn number?
+ string?
+ boolean?)))
(def-spec-meta ::closure-defines
:doc
- "Set the values of Closure libraries' variables annotated with @define
+ "Set the values of Closure libraries' variables annotated with @define
or with the cljs.core/goog-define helper macro. A common usage is
setting goog.DEBUG to false:
@@ -573,10 +573,10 @@ to work, and only goog-define defines are affected. :closure-defines
currently does not have any effect with :optimization :whitespace.")
(s/def ::npm-deps (s/or :map (s/map-of ::string-or-named string?)
- :false false?))
+ :false false?))
(def-spec-meta ::npm-deps
:doc
- "Declare NPM dependencies. A map of NPM package names to the desired
+ "Declare NPM dependencies. A map of NPM package names to the desired
versions or the Boolean value false. If false then any existing
node_modules directory will not be indexed nor used. See also
:install-deps.
@@ -586,7 +586,7 @@ node_modules directory will not be indexed nor used. See also
(s/def ::install-deps boolean?)
(def-spec-meta ::install-deps
:doc
- "When set to true, the Clojurescript compiler will handle downloading
+ "When set to true, the Clojurescript compiler will handle downloading
the Javascript dependencies defined in the :npm-deps section of the config.
:install-deps true")
@@ -595,7 +595,7 @@ the Javascript dependencies defined in the :npm-deps section of the config.
(s/every non-blank-string? :min-count 1 :into [] :kind sequential?))
(def-spec-meta ::closure-extra-annotations
:doc
- "Define extra JSDoc annotations that a closure library might use so
+ "Define extra JSDoc annotations that a closure library might use so
that they don't trigger compiler warnings.
:closure-extra-annotations #{\"api\"}")
@@ -603,7 +603,7 @@ that they don't trigger compiler warnings.
(s/def ::anon-fn-naming-policy #{:off :unmapped :mapped})
(def-spec-meta ::anon-fn-naming-policy
:doc
- "Strategies for how the Google Closure compiler does naming of
+ "Strategies for how the Google Closure compiler does naming of
anonymous functions that occur as r-values in assignments and variable
declarations. Defaults to :off.
@@ -625,7 +625,7 @@ The following values are supported:
(s/def ::optimize-constants boolean?)
(def-spec-meta ::optimize-constants
:doc
- "When set to true, constants, such as keywords and symbols, will only
+ "When set to true, constants, such as keywords and symbols, will only
be created once and will be written to a separate file called
constants_table.js. The compiler will emit a reference to the constant
as defined in the constants table instead of creating a new object for
@@ -638,19 +638,19 @@ Defaults to true under :advanced optimizations otherwise to false.
(s/def ::parallel-build boolean?)
(def-spec-meta ::parallel-build
:doc
- "When set to true, compile source in parallel, utilizing multiple cores.
+ "When set to true, compile source in parallel, utilizing multiple cores.
:parallel-build true")
;; XXX TODO
#_(s/def ::devcards boolean?)
#_(def-spec-meta :doc
- ` "Whether to include devcard 'defcard' definitions in the output of the compile.")
+ ` "Whether to include devcard 'defcard' definitions in the output of the compile.")
(s/def ::watch-fn fn?)
(def-spec-meta ::watch-fn
:doc
- "Is a function that will be called after a successful build.
+ "Is a function that will be called after a successful build.
Only available for cljs.build.api/watch
@@ -659,7 +659,7 @@ Only available for cljs.build.api/watch
(s/def ::process-shim boolean?)
(def-spec-meta ::process-shim
:doc
- "Defaults to true. Automatically provide a shim for Node.js process.env
+ "Defaults to true. Automatically provide a shim for Node.js process.env
containing a single Google Closure define, NODE_ENV with \"development\"
as the default value. In production NODE_ENV will be set to \"production\".
If set to false all of the stated behavior is disabled.
@@ -683,7 +683,7 @@ If set to false all of the stated behavior is disabled.
(s/def ::fn-invoke-direct boolean?)
(def-spec-meta ::fn-invoke-direct
:doc
- "Requires :static-fns true. This option emits slightly different
+ "Requires :static-fns true. This option emits slightly different
code that can speed up your code around 10-30%. Higher order
function that don’t implement the IFn protocol are normally called
with f.call(null, arg0, arg1 …​).
@@ -696,7 +696,7 @@ f(arg0, arg1 …​ instead.)
(s/def ::rewrite-polyfills boolean?)
(def-spec-meta ::rewrite-polyfills
:doc
- "If set to true, the google closure compiler will add polyfills (for example
+ "If set to true, the google closure compiler will add polyfills (for example
when you use native javascript Promise). This requires :language-in to be set
to :es6 or higher or it will silently be ignored!
@@ -706,16 +706,16 @@ to :es6 or higher or it will silently be ignored!
(s/def ::aot-cache boolean?)
(def-spec-meta ::aot-cache
:doc
- "A boolean value to disable or enable global caching of compiled assets.
+ "A boolean value to disable or enable global caching of compiled assets.
:aot-cache false")
(s/def ::checked-arrays (s/or :keyval #{:warn :error}
- :false false?
- :nil nil?))
+ :false false?
+ :nil nil?))
(def-spec-meta ::checked-arrays
:doc
- "If set to :warn or :error, checks inferred types and runtime values passed
+ "If set to :warn or :error, checks inferred types and runtime values passed
to aget and aset. Inferred type mismatches will result in the
:invalid-array-access warning being triggered. Logs when incorrect values
are passed if set to :warn, throws if set to :error. May be set to a
@@ -729,49 +729,49 @@ This setting does not apply if :optimizations is set to :advanced.
(s/def ::warnings
(s/or
- :bool boolean?
- :warnings-map-options
- (s/keys
- :opt-un
- [::dynamic
- ::extending-base-js-type
- ::extend-type-invalid-method-shape
- ::fn-var
- ::fn-arity
- ::fn-deprecated
- ::invalid-protocol-symbol
- ::invoke-ctor
- ::invalid-arithmetic
- ::invalid-array-access
- ::infer-warning
- ::js-shadowed-by-local
- ::multiple-variadic-overloads
- ::munged-namespace
- ::ns-var-clash
- ::overload-arity
- ::preamble-missing
- ::protocol-deprecated
- ::protocol-invalid-method
- ::protocol-duped-method
- ::protocol-multiple-impls
- ::protocol-with-variadic-method
- ::protocol-impl-with-variadic-method
- ::protocol-impl-recur-with-target
- ::redef
- ::redef-in-file
- ::single-segment-namespace
- ::unprovided
- ::undeclared-var
- ::undeclared-ns
- ::undeclared-ns-form
- ::undeclared-protocol-symbol
- ::unsupported-js-module-type
- ::unsupported-preprocess-value
- ::variadic-max-arity])))
+ :bool boolean?
+ :warnings-map-options
+ (s/keys
+ :opt-un
+ [::dynamic
+ ::extending-base-js-type
+ ::extend-type-invalid-method-shape
+ ::fn-var
+ ::fn-arity
+ ::fn-deprecated
+ ::invalid-protocol-symbol
+ ::invoke-ctor
+ ::invalid-arithmetic
+ ::invalid-array-access
+ ::infer-warning
+ ::js-shadowed-by-local
+ ::multiple-variadic-overloads
+ ::munged-namespace
+ ::ns-var-clash
+ ::overload-arity
+ ::preamble-missing
+ ::protocol-deprecated
+ ::protocol-invalid-method
+ ::protocol-duped-method
+ ::protocol-multiple-impls
+ ::protocol-with-variadic-method
+ ::protocol-impl-with-variadic-method
+ ::protocol-impl-recur-with-target
+ ::redef
+ ::redef-in-file
+ ::single-segment-namespace
+ ::unprovided
+ ::undeclared-var
+ ::undeclared-ns
+ ::undeclared-ns-form
+ ::undeclared-protocol-symbol
+ ::unsupported-js-module-type
+ ::unsupported-preprocess-value
+ ::variadic-max-arity])))
(def-spec-meta ::warnings
:doc
- "This flag will turn on/off compiler warnings for references to
+ "This flag will turn on/off compiler warnings for references to
undeclared vars, wrong function call arities, etc. Can be a boolean
for enabling/disabling common warnings, or a map of specific warning
keys with associated booleans. Defaults to true.
@@ -860,69 +860,69 @@ The following warnings are supported:
(s/def ::closure-warnings
(s/keys
- :opt-un
- [::access-controls
- ::ambiguous-function-decl
- ::analyzer-checks
- ::check-eventful-object-disposal
- ::check-regexp
- ::check-types
- ::check-useless-code
- ::check-variables
- ::closure-dep-method-usage-checks
- ::common-js-module-load
- ::conformance-violations
- ::const
- ::constant-property
- ::debugger-statement-present
- ::deprecated
- ::deprecated-annotations
- ::duplicate-message
- ::duplicate-vars
- ::es3
- ::es5-strict
- ::externs-validation
- ::extra-require
- ::fileoverview-jsdoc
- ::function-params
- ::global-this
- ::inferred-const-checks
- ::internet-explorer-checks
- ::invalid-casts
- ::j2cl-checks
- ::late-provide
- ::lint-checks
- ::message-descriptions
- ::misplaced-type-annotation
- ::missing-getcssname
- ::missing-override
- ::missing-polyfill
- ::missing-properties
- ::missing-provide
- ::missing-require
- ::missing-return
- ::non-standard-jsdoc
- ::report-unknown-types
- ::strict-missing-require
- ::strict-module-dep-check
- ::strict-requires
- ::suspicious-code
- ::tweaks
- ::type-invalidation
- ::undefined-names
- ::undefined-variables
- ::underscore
- ::unknown-defines
- ::unused-local-variable
- ::unused-private-property
- ::use-of-goog-base
- ::violated-module-dep
- ::visiblity])
+ :opt-un
+ [::access-controls
+ ::ambiguous-function-decl
+ ::analyzer-checks
+ ::check-eventful-object-disposal
+ ::check-regexp
+ ::check-types
+ ::check-useless-code
+ ::check-variables
+ ::closure-dep-method-usage-checks
+ ::common-js-module-load
+ ::conformance-violations
+ ::const
+ ::constant-property
+ ::debugger-statement-present
+ ::deprecated
+ ::deprecated-annotations
+ ::duplicate-message
+ ::duplicate-vars
+ ::es3
+ ::es5-strict
+ ::externs-validation
+ ::extra-require
+ ::fileoverview-jsdoc
+ ::function-params
+ ::global-this
+ ::inferred-const-checks
+ ::internet-explorer-checks
+ ::invalid-casts
+ ::j2cl-checks
+ ::late-provide
+ ::lint-checks
+ ::message-descriptions
+ ::misplaced-type-annotation
+ ::missing-getcssname
+ ::missing-override
+ ::missing-polyfill
+ ::missing-properties
+ ::missing-provide
+ ::missing-require
+ ::missing-return
+ ::non-standard-jsdoc
+ ::report-unknown-types
+ ::strict-missing-require
+ ::strict-module-dep-check
+ ::strict-requires
+ ::suspicious-code
+ ::tweaks
+ ::type-invalidation
+ ::undefined-names
+ ::undefined-variables
+ ::underscore
+ ::unknown-defines
+ ::unused-local-variable
+ ::unused-private-property
+ ::use-of-goog-base
+ ::violated-module-dep
+ ::visiblity])
)
(def-spec-meta ::closure-warnings
:doc
- "Configure warnings generated by the Closure compiler. A map from
+ "Configure warnings generated by the Closure compiler. A map from
Closure warning to configuration value, only :error, :warning and :off
are supported.
@@ -1054,81 +1054,81 @@ See the Closure Compiler Warning wiki for detailed descriptions.")
;; ** The Top level Options Map for the cljs/build fn
(s/def ::cljs-options
(spell/keys
- :opt-un
- [::main
- ::preloads
- ::asset-path
- ::output-to
- ::output-dir
- ::closure-warnings
- ::optimizations
- ::source-map
- ::verbose
- ::pretty-print
- ::target
- ::infer-externs
- ::foreign-libs
- ::externs
- ::modules
- ::source-map-path
- ::source-map-asset-path
- ::source-map-timestamp
- ::cache-analysis
- ::recompile-dependents
- ::static-fns
- ::load-tests
- ::elide-asserts
- ::pseudo-names
- ::print-input-delimiter
- ::output-wrapper
- ::libs
- ::preamble
- ::hashbang
- ::compiler-stats
- ::language-in
- ::language-out
- ::npm-deps
- ::install-deps
- ::closure-defines
- ::closure-extra-annotations
- ::anon-fn-naming-policy
- ::optimize-constants
- ::parallel-build
- ::devcards
- ::dump-core
- ::emit-constants
- ::warning-handlers
- ::source-map-inline
- ::ups-libs
- ::ups-externs
- ::ups-foreign-libs
- ::closure-output-charset
- ::external-config
- ::watch-fn
- ::process-shim
- ::warnings
- ::fn-invoke-direct
- ::rewrite-polyfills
- ::checked-arrays
- ::aot-cache
-
- ;; these need to be specified
- ::closure-variable-map-out
- ::closure-generate-exports
- ::closure-module-roots
- ::rename-prefix
- ::closure-property-map-in
- ::ignore-js-module-exts
- ::closure-property-map-out
- ::stable-names
- ::watch-error-fn
- ::browser-repl
- ::opts-cache
- ::watch
- ::cache-analysis-format
- ::rename-prefix-namespace
- ::closure-variable-map-in
- ::use-only-custom-externs
-
- ]
- ))
+ :opt-un
+ [::main
+ ::preloads
+ ::asset-path
+ ::output-to
+ ::output-dir
+ ::closure-warnings
+ ::optimizations
+ ::source-map
+ ::verbose
+ ::pretty-print
+ ::target
+ ::infer-externs
+ ::foreign-libs
+ ::externs
+ ::modules
+ ::source-map-path
+ ::source-map-asset-path
+ ::source-map-timestamp
+ ::cache-analysis
+ ::recompile-dependents
+ ::static-fns
+ ::load-tests
+ ::elide-asserts
+ ::pseudo-names
+ ::print-input-delimiter
+ ::output-wrapper
+ ::libs
+ ::preamble
+ ::hashbang
+ ::compiler-stats
+ ::language-in
+ ::language-out
+ ::npm-deps
+ ::install-deps
+ ::closure-defines
+ ::closure-extra-annotations
+ ::anon-fn-naming-policy
+ ::optimize-constants
+ ::parallel-build
+ ::devcards
+ ::dump-core
+ ::emit-constants
+ ::warning-handlers
+ ::source-map-inline
+ ::ups-libs
+ ::ups-externs
+ ::ups-foreign-libs
+ ::closure-output-charset
+ ::external-config
+ ::watch-fn
+ ::process-shim
+ ::warnings
+ ::fn-invoke-direct
+ ::rewrite-polyfills
+ ::checked-arrays
+ ::aot-cache
+
+ ;; these need to be specified
+ ::closure-variable-map-out
+ ::closure-generate-exports
+ ::closure-module-roots
+ ::rename-prefix
+ ::closure-property-map-in
+ ::ignore-js-module-exts
+ ::closure-property-map-out
+ ::stable-names
+ ::watch-error-fn
+ ::browser-repl
+ ::opts-cache
+ ::watch
+ ::cache-analysis-format
+ ::rename-prefix-namespace
+ ::closure-variable-map-in
+ ::use-only-custom-externs
+
+ ]
+ ))
diff --git a/src/figwheel/main/schema/config.clj b/src/figwheel/main/schema/config.clj
index 33552e0..cb5fd87 100644
--- a/src/figwheel/main/schema/config.clj
+++ b/src/figwheel/main/schema/config.clj
@@ -15,9 +15,9 @@
(s/def ::watch-dirs
(s/coll-of
- (s/and non-blank-string?
- directory-exists?
- ::schema/has-cljs-source-files)))
+ (s/and non-blank-string?
+ directory-exists?
+ ::schema/has-cljs-source-files)))
#_(exp/expound ::watch-dirs ["/Users/bhauman/workspace/temp/figtest/ouchy"])
@@ -67,7 +67,7 @@ Default: none
(def-spec-meta ::ring-server-options
:doc
- "All the options to forward to the `ring-jetty-adapter/run-jetty` function
+ "All the options to forward to the `ring-jetty-adapter/run-jetty` function
which figwheel.main uses to run its ring server.
All the available options are documented here:
@@ -138,7 +138,7 @@ and Figwheel will call `emacsclient` with the correct args."
(s/def ::figwheel-core boolean?)
(def-spec-meta ::figwheel-core
:doc
- "Whether to include the figwheel.core library in the build. This
+ "Whether to include the figwheel.core library in the build. This
enables hot reloading and client notification of compile time errors.
Default: true
@@ -148,7 +148,7 @@ and Figwheel will call `emacsclient` with the correct args."
(s/def ::hot-reload-cljs boolean?)
(def-spec-meta ::hot-reload-cljs
:doc
- "Whether or not figwheel.core should hot reload compiled
+ "Whether or not figwheel.core should hot reload compiled
ClojureScript. Only has meaning when :figwheel is true.
Default: true
@@ -158,7 +158,7 @@ Default: true
(s/def ::reload-dependents boolean?)
(def-spec-meta ::reload-dependents
:doc
- "Whether or not figwheel.core should reload the namespaces that
+ "Whether or not figwheel.core should reload the namespaces that
`depend` on the changed namespaces in addition to the changed
namespaces themselves. Only has meaning when :figwheel is true.
Default:true
@@ -169,7 +169,7 @@ Default:true
(s/def ::connect-url non-blank-string?)
(def-spec-meta ::connect-url
:doc
- "The url that the figwheel REPL client will use to connect back to
+ "The url that the figwheel REPL client will use to connect back to
the server.
This url is actually a template that will be filled in. For example
@@ -200,7 +200,7 @@ connection will be established. If the url starts with an http scheme
:false false?))
(def-spec-meta ::open-url
:doc
- "Either a boolean value `false` or a string that indicates the url
+ "Either a boolean value `false` or a string that indicates the url
that the figwheel REPL will open in the browser after the source code
has been compiled. A `false` value will disable this behavior.
@@ -221,7 +221,7 @@ For the server side:
:extension-coll (s/coll-of #{:clj :cljc})))
(def-spec-meta ::reload-clj-files
:doc
- "Figwheel naively reloads `clj` and `cljc` files on the `:source-paths`.
+ "Figwheel naively reloads `clj` and `cljc` files on the `:source-paths`.
It doesn't reload clj dependent files like tools.namspace.
Figwheel does note if there is a macro in the changed `clj` or `cljc` file
@@ -241,7 +241,7 @@ Or you can specify which suffixes will cause the reloading
(s/def ::log-file non-blank-string?)
(def-spec-meta ::log-file
:doc
- "The name of a file to redirect the figwheel.main logging to. This
+ "The name of a file to redirect the figwheel.main logging to. This
will only take effect when a REPL has been started.
:log-file \"figwheel-main.log\""
@@ -250,7 +250,7 @@ will only take effect when a REPL has been started.
(s/def ::log-level #{:error :info :debug :trace :all :off})
(def-spec-meta ::log-level
:doc
- "The level to set figwheel.main java.util.logger to.
+ "The level to set figwheel.main java.util.logger to.
Can be one of: `:error` `:info` `:debug` `:trace` `:all` `:off`
:log-level :error"
@@ -259,7 +259,7 @@ Can be one of: `:error` `:info` `:debug` `:trace` `:all` `:off`
(s/def ::client-log-level #{:severe :warning :info :config :fine :finer :finest})
(def-spec-meta ::client-log-level
:doc
- "The log level to set the client side goog.log.Logger to for
+ "The log level to set the client side goog.log.Logger to for
figwheel.repl and figwheel.core. Can be one of:
`:severe` `:warning` `:info` `:config` `:fine` `:finer` `:finest`
@@ -269,7 +269,7 @@ figwheel.repl and figwheel.core. Can be one of:
(s/def ::log-syntax-error-style #{:verbose :concise})
(def-spec-meta ::log-syntax-error-style
:doc
- "figwheel.main logging prints out compile time syntax errors which
+ "figwheel.main logging prints out compile time syntax errors which
includes displaying the erroneous code.
Setting `:log-syntax-error-style` to `:concise` will cause the logging to
not display the erroneous code.
@@ -282,7 +282,7 @@ Default: `:verbose`
(s/def ::load-warninged-code boolean?)
(def-spec-meta ::load-warninged-code
:doc
- "If there are warnings in your code emitted from the compiler, figwheel
+ "If there are warnings in your code emitted from the compiler, figwheel
does not refresh. If you would like Figwheel to load code even if
there are warnings generated set this to true.
Default: false
@@ -293,7 +293,7 @@ Default: false
(s/def ::ansi-color-output boolean?)
(def-spec-meta ::ansi-color-output
:doc
- "Figwheel makes an effort to provide colorful text output. If you need
+ "Figwheel makes an effort to provide colorful text output. If you need
to prevent ANSI color codes in figwheel output set `:ansi-color-output`
to false. Default: true
@@ -303,7 +303,7 @@ to false. Default: true
(s/def ::validate-config boolean?)
(def-spec-meta ::validate-config
:doc
- "Whether to validate the figwheel-main.edn and build config (i.e.\".cljs.edn\") files.
+ "Whether to validate the figwheel-main.edn and build config (i.e.\".cljs.edn\") files.
Default: true
:validate-config false"
@@ -312,7 +312,7 @@ Default: true
(s/def ::validate-cli boolean?)
(def-spec-meta ::validate-cli
:doc
- "Whether to validate the figwheel-main command line options
+ "Whether to validate the figwheel-main command line options
Default: true
:validate-cli false"
@@ -321,7 +321,7 @@ Default: true
(s/def ::target-dir non-blank-string?)
(def-spec-meta ::target-dir
:doc
- "A String that specifies the target directory component of the path
+ "A String that specifies the target directory component of the path
where figwheel.main outputs compiled ClojureScript
The default `:output-dir` is composed of:
@@ -575,15 +575,15 @@ on a Nodejs app in parallel with your main build.
(s/coll-of (s/or :keyword (s/and keyword? #{:main :watch-dirs})
:non-blank-string (s/and non-blank-string?
(s/or
- :file file-exists?
- :directory
- (s/and directory-exists?
- ::schema/has-cljs-source-files)))
+ :file file-exists?
+ :directory
+ (s/and directory-exists?
+ ::schema/has-cljs-source-files)))
:namespace ::schema/unquoted-symbol)))
(def-spec-meta ::build-inputs
:doc
- "Build inputs are passed as the first argument to the CLJS compiler.
+ "Build inputs are passed as the first argument to the CLJS compiler.
Build inputs are normally a list of sources (files and directories)
for the compiler to compile.
@@ -619,11 +619,11 @@ specific inputs you want to send to the compiler.
(s/def :figwheel.main.schema.config.testing/cljs-test-display boolean?)
(s/def ::auto-testing (s/or
- :bool boolean?
- :map (spell/strict-keys
- :opt-un
- [:figwheel.main.schema.config.testing/namespaces
- :figwheel.main.schema.config.testing/cljs-test-display])))
+ :bool boolean?
+ :map (spell/strict-keys
+ :opt-un
+ [:figwheel.main.schema.config.testing/namespaces
+ :figwheel.main.schema.config.testing/cljs-test-display])))
(def-spec-meta ::auto-testing
:doc
@@ -655,7 +655,7 @@ You can also disable `cljs-test-display` with:
(s/def ::cljsjs-resources boolean?)
(def-spec-meta ::cljsjs-resources
:doc
- "When you use libraries from http://cljsjs.github.io they sometimes
+ "When you use libraries from http://cljsjs.github.io they sometimes
come bundled with static resources (like CSS files) that you would
like to be served from the Figwheel server.
@@ -675,7 +675,7 @@ it via the Figwheel server at the path
(s/def ::client-print-to (s/coll-of #{:console :repl}))
(def-spec-meta ::client-print-to
:doc
- "The `figwheel.repl` client can direct printed (via pr) output to the
+ "The `figwheel.repl` client can direct printed (via pr) output to the
REPL and/or the console. `:client-print-to` is a list of where you
want print output directed. The output choices are `:console` and `:repl`
Default: [:console :repl]
@@ -688,7 +688,7 @@ Default: [:console :repl]
(def-spec-meta ::ring-stack
:doc
- "The figwheel server has a notion of a `:ring-stack`. The
+ "The figwheel server has a notion of a `:ring-stack`. The
`:ring-stack` is a composition of basic ring-middleware (think
sessions) to wrap around a supplied `:ring-handler`.
@@ -699,7 +699,7 @@ The default `:ring-stack` is a slightly modified
(s/def ::ring-stack-options map?)
(def-spec-meta ::ring-stack-options
:doc
- (str "The figwheel.repl server has a notion of a `:ring-stack`. The
+ (str "The figwheel.repl server has a notion of a `:ring-stack`. The
`:ring-stack` is a composition of basic ring-middleware to wrap around
a supplied `:ring-handler`.
@@ -714,7 +714,7 @@ The default options are slightly modified from `ring.middleware.defaults/site-de
```
" (when-let [opt (resolve 'figwheel.server.ring/default-options)]
(with-out-str (clojure.pprint/pprint (deref opt))))
-"```
+ "```
You can override these options by suppling your own to `:ring-stack-options`
@@ -737,7 +737,7 @@ Default: 50
(s/def ::mode #{:build-once :repl :serve})
(def-spec-meta ::mode
:doc
- "The `:mode` indicates the behavior that occurs after a compile.
+ "The `:mode` indicates the behavior that occurs after a compile.
Options: `:repl` `:serve` or `:build-once`
* `:repl` indicates that a REPL will be started
@@ -747,7 +747,7 @@ Options: `:repl` `:serve` or `:build-once`
This is mainly intended for use when you are launching figwheel.main from a script.
Normally defaults to `:repl`"
- :group :un-common)
+ :group :un-common)
(s/def ::broadcast-reload boolean?)
(def-spec-meta ::broadcast-reload
@@ -802,57 +802,57 @@ be useful for certain docker environments.
(s/def ::edn
(ensure-all-registered-keys-included
- #{::edn ::bundles}
- (spell/strict-keys
- :opt-un
- [::watch-dirs
- ::css-dirs
- ::ring-handler
- ::ring-server-options
- ::rebel-readline
- ::pprint-config
- ::open-file-command
- ::figwheel-core
- ::hot-reload-cljs
- ::reload-dependents
- ::connect-url
- ::open-url
- ::reload-clj-files
- ::log-file
- ::log-level
- ::client-log-level
- ::log-syntax-error-style
- ::load-warninged-code
- ::ansi-color-output
- ::validate-config
- ::validate-cli
- ::target-dir
-
- ::npm
- ::pre-build-hooks
- ::post-build-hooks
- ::extra-main-files
- ::build-inputs
- ::auto-testing
- ::launch-js
- ::cljsjs-resources
-
- ::helpful-classpaths
+ #{::edn ::bundles}
+ (spell/strict-keys
+ :opt-un
+ [::watch-dirs
+ ::css-dirs
+ ::ring-handler
+ ::ring-server-options
+ ::rebel-readline
+ ::pprint-config
+ ::open-file-command
+ ::figwheel-core
+ ::hot-reload-cljs
+ ::reload-dependents
+ ::connect-url
+ ::open-url
+ ::reload-clj-files
+ ::log-file
+ ::log-level
+ ::client-log-level
+ ::log-syntax-error-style
+ ::load-warninged-code
+ ::ansi-color-output
+ ::validate-config
+ ::validate-cli
+ ::target-dir
+
+ ::npm
+ ::pre-build-hooks
+ ::post-build-hooks
+ ::extra-main-files
+ ::build-inputs
+ ::auto-testing
+ ::launch-js
+ ::cljsjs-resources
+
+ ::helpful-classpaths
- ::launch-node
- ::inspect-node
- ::node-command
- ::cljs-devtools
-
- ::client-print-to
- ::ring-stack
- ::ring-stack-options
- ::wait-time-ms
- ::mode
- ::ring-server
- ::broadcast
- ::broadcast-reload
- ::repl-eval-timeout
- ::hawk-options
- ])))
+ ::launch-node
+ ::inspect-node
+ ::node-command
+ ::cljs-devtools
+
+ ::client-print-to
+ ::ring-stack
+ ::ring-stack-options
+ ::wait-time-ms
+ ::mode
+ ::ring-server
+ ::broadcast
+ ::broadcast-reload
+ ::repl-eval-timeout
+ ::hawk-options
+ ])))
diff --git a/src/figwheel/main/schema/core.clj b/src/figwheel/main/schema/core.clj
index ecca64e..89a68f1 100644
--- a/src/figwheel/main/schema/core.clj
+++ b/src/figwheel/main/schema/core.clj
@@ -69,17 +69,17 @@
(defn key-meta-for-problem [{:keys [via :spell-spec.alpha/likely-misspelling-of] :as prob}]
(or
- (when-let [n (first likely-misspelling-of)]
- (when-let [ns (namespace (first via))]
- (get @*spec-meta* (keyword ns (name n)))))
- (some->> (reverse via)
- (filter @*spec-meta*)
- ;; don't show the root docs
- (filter (complement
- #{:figwheel.main.schema.config/edn
- :figwheel.main.schema.cljs-options/cljs-options}))
- first
- (get @*spec-meta*))))
+ (when-let [n (first likely-misspelling-of)]
+ (when-let [ns (namespace (first via))]
+ (get @*spec-meta* (keyword ns (name n)))))
+ (some->> (reverse via)
+ (filter @*spec-meta*)
+ ;; don't show the root docs
+ (filter (complement
+ #{:figwheel.main.schema.config/edn
+ :figwheel.main.schema.cljs-options/cljs-options}))
+ first
+ (get @*spec-meta*))))
(let [expected-str (deref #'exp/expected-str)]
(defn expected-str-with-doc [_type spec-name val path problems opts]
@@ -87,15 +87,15 @@
(when-let [{:keys [key doc]} (key-meta-for-problem (first problems))]
(when doc
(str
- "\n\n-- Doc for " (pr-str (keyword (name key))) " -----\n\n"
- (printer/indent doc)))))))
+ "\n\n-- Doc for " (pr-str (keyword (name key))) " -----\n\n"
+ (printer/indent doc)))))))
(defn expound-string [spec form]
(when-let [explain-data (s/explain-data spec form)]
(with-redefs [exp/expected-str expected-str-with-doc]
(with-out-str
((exp/custom-printer
- {:print-specs? false})
+ {:print-specs? false})
explain-data)))))
(defn validate-config! [spec config-data context-msg]
@@ -105,8 +105,8 @@
true))
#_(expound-string
- :figwheel.main.schema.config/edn
- (read-string (slurp "figwheel-main.edn")))
+ :figwheel.main.schema.config/edn
+ (read-string (slurp "figwheel-main.edn")))
;; ------------------------------------------------------------
;; Spec validation
@@ -127,11 +127,11 @@
(defn markdown-option-docs [key-datas]
(string/join
- "\n\n"
- (mapv (fn [{:keys [key doc]}]
- (let [k (keyword (name key))]
- (format "## %s\n\n%s" (pr-str k) doc)))
- key-datas)))
+ "\n\n"
+ (mapv (fn [{:keys [key doc]}]
+ (let [k (keyword (name key))]
+ (format "## %s\n\n%s" (pr-str k) doc)))
+ key-datas)))
(defn markdown-docs []
(let [{:keys [common un-common]} (->> (vals @*spec-meta*)
diff --git a/src/figwheel/main/testing.cljc b/src/figwheel/main/testing.cljc
index 0b0edba..5d95cc4 100644
--- a/src/figwheel/main/testing.cljc
+++ b/src/figwheel/main/testing.cljc
@@ -12,104 +12,104 @@
#?(:cljs
(do
-(defonce test-result-data (atom nil))
-
-(defn on-finish-listener [ky listener]
- (add-watch test-result-data ky (fn [_ _ _ m] (listener m))))
-
-;; cljs-test-display
-(defmethod report [:cljs-test-display.core/default :end-run-tests] [m]
- (reset! test-result-data m))
-
-(defmethod report [:cljs.test/default :end-run-tests] [m]
- (reset! test-result-data m))
-
-(defn system-exit-on-fail []
- (on-finish-listener
- ::exit-on-fail
- #(async-result/send
- (if (cljs.test/successful? %)
- ::success
- (async-result/throw-ex
- (ex-info "ClojureScript async test run failed" %))))))
-
-(defn no-auto-tests-display-message [app-id]
- (if (nil? goog/global.document)
- (js/console.log "No tests yet")
- (let [el (gdom/getElement app-id)]
- (gdom/removeChildren el)
- (gdom/append
- el
- (gdom/createDom
- "div" #js {:style (str "margin: 100px auto; border: 1px solid #d0d0d0; color: #444; width: 400px; padding: 2em;"
- "border-radius: 5px; font-family:sans-serif; background-color: #fdfce2")}
- (gdom/createDom
- "h1" #js {:style ""}
- (gdom/createTextNode "No tests found."))
- (gdom/createDom
- "p" #js {:style ""}
- (gdom/createTextNode
- (str "Figwheel auto-testing sometimes isn't able to pick up your testing namespaces until "
- "after you have hot reloaded a source file at least once.")))
- (gdom/createDom
- "p" #js {:style ""}
- (gdom/createTextNode "For example: Try to open a source file with tests in it and save it."))
- (gdom/createDom
- "p" #js {:style ""}
- (gdom/createTextNode "Or maybe you haven't added the source directories for your tests to `:watch-dirs`?"))
- (gdom/createDom
- "p" #js {:style ""}
- (gdom/createTextNode "Or perhaps you haven't written any tests yet? Nah, that's not possible."))))))
+ (defonce test-result-data (atom nil))
+
+ (defn on-finish-listener [ky listener]
+ (add-watch test-result-data ky (fn [_ _ _ m] (listener m))))
+
+ ;; cljs-test-display
+ (defmethod report [:cljs-test-display.core/default :end-run-tests] [m]
+ (reset! test-result-data m))
+
+ (defmethod report [:cljs.test/default :end-run-tests] [m]
+ (reset! test-result-data m))
+
+ (defn system-exit-on-fail []
+ (on-finish-listener
+ ::exit-on-fail
+ #(async-result/send
+ (if (cljs.test/successful? %)
+ ::success
+ (async-result/throw-ex
+ (ex-info "ClojureScript async test run failed" %))))))
+
+ (defn no-auto-tests-display-message [app-id]
+ (if (nil? goog/global.document)
+ (js/console.log "No tests yet")
+ (let [el (gdom/getElement app-id)]
+ (gdom/removeChildren el)
+ (gdom/append
+ el
+ (gdom/createDom
+ "div" #js {:style (str "margin: 100px auto; border: 1px solid #d0d0d0; color: #444; width: 400px; padding: 2em;"
+ "border-radius: 5px; font-family:sans-serif; background-color: #fdfce2")}
+ (gdom/createDom
+ "h1" #js {:style ""}
+ (gdom/createTextNode "No tests found."))
+ (gdom/createDom
+ "p" #js {:style ""}
+ (gdom/createTextNode
+ (str "Figwheel auto-testing sometimes isn't able to pick up your testing namespaces until "
+ "after you have hot reloaded a source file at least once.")))
+ (gdom/createDom
+ "p" #js {:style ""}
+ (gdom/createTextNode "For example: Try to open a source file with tests in it and save it."))
+ (gdom/createDom
+ "p" #js {:style ""}
+ (gdom/createTextNode "Or maybe you haven't added the source directories for your tests to `:watch-dirs`?"))
+ (gdom/createDom
+ "p" #js {:style ""}
+ (gdom/createTextNode "Or perhaps you haven't written any tests yet? Nah, that's not possible."))))))
-)
+ )
-)
+ )
:clj
(do
-;; should only do this once the first time you cant find tests with
-;; the compiler env. This doesn't have to be super accurate because
-;; namespaces without tests will be ignored anyway
-(defn find-test-namespaces
- "Takes a list of directories and searches them for test source files
+ ;; should only do this once the first time you cant find tests with
+ ;; the compiler env. This doesn't have to be super accurate because
+ ;; namespaces without tests will be ignored anyway
+ (defn find-test-namespaces
+ "Takes a list of directories and searches them for test source files
and returns a list of namespaces that may have tests in them."
- [source-dirs]
- (->> source-dirs
- (mapv io/file)
- (filter #(.isDirectory %))
- (mapcat (comp file-seq io/file))
- (filter #(or (.endsWith (str %) ".cljs")
- (.endsWith (str %) ".cljc")))
- (filter #(when-let [content (try (slurp %) (catch Throwable t nil))]
- (.contains content "(deftest ")))
- (keep #(try (cljs.analyzer/parse-ns %) (catch Throwable t nil)))
- (mapv :ns)))
-
-#_(find-test-namespaces ["devel" "src"])
-
-;; speed this up by simply checking for cljs.test in the requires first
-;; or we could consider meta data on the ns as the indicator
-(defn namespace-has-test? [ns-sym]
- (some :test (vals (get-in @cljs.env/*compiler* [:cljs.analyzer/namespaces ns-sym :defs]))))
-
-(defn get-test-namespaces []
- (->> (get @cljs.env/*compiler* :cljs.analyzer/namespaces)
- (filter (fn [[_ v]] (some :test (vals (:defs v)))))
- (mapv first)))
-
-(defn ns? [x]
- (and (seq? x) (= (first x) 'quote)))
-
-(defn get-quoted-test-nses []
- (not-empty
- (map #(list 'quote %)
- (or (not-empty (get-test-namespaces))
- (and cljs.analyzer/*cljs-ns*
- [cljs.analyzer/*cljs-ns*])))))
-
-(defmacro run-tests
- "Differs from `cljs.test/run-tests` in that this macro by finds all
+ [source-dirs]
+ (->> source-dirs
+ (mapv io/file)
+ (filter #(.isDirectory %))
+ (mapcat (comp file-seq io/file))
+ (filter #(or (.endsWith (str %) ".cljs")
+ (.endsWith (str %) ".cljc")))
+ (filter #(when-let [content (try (slurp %) (catch Throwable t nil))]
+ (.contains content "(deftest ")))
+ (keep #(try (cljs.analyzer/parse-ns %) (catch Throwable t nil)))
+ (mapv :ns)))
+
+ #_(find-test-namespaces ["devel" "src"])
+
+ ;; speed this up by simply checking for cljs.test in the requires first
+ ;; or we could consider meta data on the ns as the indicator
+ (defn namespace-has-test? [ns-sym]
+ (some :test (vals (get-in @cljs.env/*compiler* [:cljs.analyzer/namespaces ns-sym :defs]))))
+
+ (defn get-test-namespaces []
+ (->> (get @cljs.env/*compiler* :cljs.analyzer/namespaces)
+ (filter (fn [[_ v]] (some :test (vals (:defs v)))))
+ (mapv first)))
+
+ (defn ns? [x]
+ (and (seq? x) (= (first x) 'quote)))
+
+ (defn get-quoted-test-nses []
+ (not-empty
+ (map #(list 'quote %)
+ (or (not-empty (get-test-namespaces))
+ (and cljs.analyzer/*cljs-ns*
+ [cljs.analyzer/*cljs-ns*])))))
+
+ (defmacro run-tests
+ "Differs from `cljs.test/run-tests` in that this macro by finds all
the available namespaces in the local sources to test and tests
them.
@@ -130,25 +130,25 @@
(run-tests 'example.core-tests) ;;
;; run tests in 'example.core-tests and display with cljs-test-display
(run-tests (cljs-test-display.core/init!) 'example.core-tests)"
- ([] `(run-tests (cljs.test/empty-env)))
- ([env-or-ns]
- (if (ns? env-or-ns)
- `(run-tests (cljs.test.empty-env) ~env-or-ns)
- (when-let [test-nses (get-quoted-test-nses)]
- `(run-tests ~env-or-ns ~@test-nses))))
- ([env-or-ns & namespaces]
- `(do (cljs.test/run-tests ~env-or-ns ~@namespaces)
- (if (cljs.test/successful? @figwheel.main.testing/test-result-data)
- ::success
- (throw
- (ex-info
- "ClojureScript test run failed"
- @figwheel.main.testing/test-result-data))))))
-
-;; this helps if you are running async tests and you have a custom
-;; reporter
-(defmacro run-tests-async
- "This is only supported when run in conjunction with the
+ ([] `(run-tests (cljs.test/empty-env)))
+ ([env-or-ns]
+ (if (ns? env-or-ns)
+ `(run-tests (cljs.test.empty-env) ~env-or-ns)
+ (when-let [test-nses (get-quoted-test-nses)]
+ `(run-tests ~env-or-ns ~@test-nses))))
+ ([env-or-ns & namespaces]
+ `(do (cljs.test/run-tests ~env-or-ns ~@namespaces)
+ (if (cljs.test/successful? @figwheel.main.testing/test-result-data)
+ ::success
+ (throw
+ (ex-info
+ "ClojureScript test run failed"
+ @figwheel.main.testing/test-result-data))))))
+
+ ;; this helps if you are running async tests and you have a custom
+ ;; reporter
+ (defmacro run-tests-async
+ "This is only supported when run in conjunction with the
`figwheel.main`'s `--main` CLI option.
Differs from `cljs.test/run-tests` in that this macro by finds all
@@ -179,124 +179,124 @@
(run-tests-async 5000 'example.core-tests) ;;
;; run tests in 'example.core-tests and display with cljs-test-display
(run-tests-async 5000 (cljs-test-display.core/init!) 'example.core-tests)"
- ([timeout]
- `(run-tests-async ~timeout (cljs.test/empty-env)))
- ([timeout env-or-ns]
- (if (ns? env-or-ns)
- `(run-tests-async ~timeout (cljs.test/empty-env) ~env-or-ns)
- (when-let [test-nses (get-quoted-test-nses)]
- `(run-tests-async ~timeout ~env-or-ns ~@test-nses))))
- ([timeout env-or-ns & namespaces]
- `(do
- (figwheel.main.testing/system-exit-on-fail)
- ~(if (ns? env-or-ns)
- `(cljs.test/run-tests ~env-or-ns ~@namespaces)
- `(let [reporter# (:reporter ~env-or-ns)]
- (when-not (#{:cljs.test/default :cljs-test-display.core/default} reporter#)
- (defmethod cljs.test/report [reporter# :end-run-tests] [m#]
- (reset! figwheel.main.testing/test-result-data m#)))
- (cljs.test/run-tests ~env-or-ns ~@namespaces)))
- [:figwheel.main.async-result/wait ~timeout])))
-
-
-;; we need to generate a testing file
-
-(defn genned-test-ns [build-id]
- (symbol (format "figwheel.main.generated.%s-auto-test-runner" (name build-id))))
-
-(defn testing-file-content [{:keys [test-ns libs run-tests-args]
- :or {test-ns (genned-test-ns "unknown")
- libs []
- run-tests-args []}}]
- (format "(ns %s
+ ([timeout]
+ `(run-tests-async ~timeout (cljs.test/empty-env)))
+ ([timeout env-or-ns]
+ (if (ns? env-or-ns)
+ `(run-tests-async ~timeout (cljs.test/empty-env) ~env-or-ns)
+ (when-let [test-nses (get-quoted-test-nses)]
+ `(run-tests-async ~timeout ~env-or-ns ~@test-nses))))
+ ([timeout env-or-ns & namespaces]
+ `(do
+ (figwheel.main.testing/system-exit-on-fail)
+ ~(if (ns? env-or-ns)
+ `(cljs.test/run-tests ~env-or-ns ~@namespaces)
+ `(let [reporter# (:reporter ~env-or-ns)]
+ (when-not (#{:cljs.test/default :cljs-test-display.core/default} reporter#)
+ (defmethod cljs.test/report [reporter# :end-run-tests] [m#]
+ (reset! figwheel.main.testing/test-result-data m#)))
+ (cljs.test/run-tests ~env-or-ns ~@namespaces)))
+ [:figwheel.main.async-result/wait ~timeout])))
+
+
+ ;; we need to generate a testing file
+
+ (defn genned-test-ns [build-id]
+ (symbol (format "figwheel.main.generated.%s-auto-test-runner" (name build-id))))
+
+ (defn testing-file-content [{:keys [test-ns libs run-tests-args]
+ :or {test-ns (genned-test-ns "unknown")
+ libs []
+ run-tests-args []}}]
+ (format "(ns %s
(:require [cljs.test :refer-macros [run-tests]]
%s))
(run-tests %s)"
- (str test-ns)
- (string/join " " (map pr-str libs))
- (string/join " " (map pr-str run-tests-args))))
+ (str test-ns)
+ (string/join " " (map pr-str libs))
+ (string/join " " (map pr-str run-tests-args))))
-(defn no-namespaces-content [{:keys [test-ns app-id] :or {test-ns (genned-test-ns "unknown")
- app-id "app-auto-testing"}}]
- (format "(ns %s
+ (defn no-namespaces-content [{:keys [test-ns app-id] :or {test-ns (genned-test-ns "unknown")
+ app-id "app-auto-testing"}}]
+ (format "(ns %s
(:require [figwheel.main.testing]))
(figwheel.main.testing/no-auto-tests-display-message %s)"
- (pr-str test-ns)
- (pr-str app-id)))
-
-#_(testing-file-content {:test-ns (genned-test-ns "dev")
- :libs '[[cljs-test-display.core]]
- :run-tests-args '[(cljs-test-display.core/init!)]})
-
-(defn test-file-output-to [output-dir]
- (str (io/file output-dir "generated-input-files" "gen_test_runner.cljs")))
-
-#_(test-file-output-to "target/cljs-out/dev")
-
-
-;; todo generate a different file when there are no namespaces to test
-;; or create a macro to help in this case
-(defn pre-hook [{:keys [output-to test-display? initial-namespaces]}]
- (fn [cfg]
- (let [namespaces
- (or (when-let [auto-testing (get-in cfg [:figwheel.main/config :auto-testing])]
- (and (map? auto-testing)
- (:namespaces auto-testing)))
- (not-empty (get-test-namespaces))
- initial-namespaces)]
- (let [id (-> cfg :figwheel.main/build :id)
- args (cond-> {:test-ns (genned-test-ns id)}
- test-display?
- (->
- (update :libs conj '[cljs-test-display.core])
- (update :run-tests-args conj '(cljs-test-display.core/init! "app-auto-testing")))
- (not-empty namespaces)
- (->
- (update :libs concat (map vector namespaces))
- (update :run-tests-args concat (map #(list 'quote %) namespaces))))
- content (if (not-empty namespaces)
- (testing-file-content args)
- (no-namespaces-content (assoc args :app-id "app-auto-testing")))]
- (log/debug output-to)
- (log/debug content)
- (let [f (io/file output-to)]
- (io/make-parents f)
- (spit f content)
- (log/debug (.isFile f)))
+ (pr-str test-ns)
+ (pr-str app-id)))
+
+ #_(testing-file-content {:test-ns (genned-test-ns "dev")
+ :libs '[[cljs-test-display.core]]
+ :run-tests-args '[(cljs-test-display.core/init!)]})
+
+ (defn test-file-output-to [output-dir]
+ (str (io/file output-dir "generated-input-files" "gen_test_runner.cljs")))
+
+ #_(test-file-output-to "target/cljs-out/dev")
+
+
+ ;; todo generate a different file when there are no namespaces to test
+ ;; or create a macro to help in this case
+ (defn pre-hook [{:keys [output-to test-display? initial-namespaces]}]
+ (fn [cfg]
+ (let [namespaces
+ (or (when-let [auto-testing (get-in cfg [:figwheel.main/config :auto-testing])]
+ (and (map? auto-testing)
+ (:namespaces auto-testing)))
+ (not-empty (get-test-namespaces))
+ initial-namespaces)]
+ (let [id (-> cfg :figwheel.main/build :id)
+ args (cond-> {:test-ns (genned-test-ns id)}
+ test-display?
+ (->
+ (update :libs conj '[cljs-test-display.core])
+ (update :run-tests-args conj '(cljs-test-display.core/init! "app-auto-testing")))
+ (not-empty namespaces)
+ (->
+ (update :libs concat (map vector namespaces))
+ (update :run-tests-args concat (map #(list 'quote %) namespaces))))
+ content (if (not-empty namespaces)
+ (testing-file-content args)
+ (no-namespaces-content (assoc args :app-id "app-auto-testing")))]
+ (log/debug output-to)
+ (log/debug content)
+ (let [f (io/file output-to)]
+ (io/make-parents f)
+ (spit f content)
+ (log/debug (.isFile f)))
- ))))
-
-(defn add-extra-main [cfg]
- (let [id (-> cfg :figwheel.main/build :id)
- ns' (genned-test-ns id)]
- (assoc-in cfg [:figwheel.main/config :extra-main-files :auto-testing] {:main ns'})))
-
-(defn add-auto-testing? [{:keys [options :figwheel.main/config] :as cfg}]
- (and
- (= :none (get options :optimizations :none))
- (get config :auto-testing false)))
-
-(defn cljs-test-display? [cfg]
- (let [auto-testing (get-in cfg [:figwheel.main/config :auto-testing])]
- (and (nil? (get-in cfg [:options :target]))
- (not (and (map? auto-testing) (false? (:cljs-test-display auto-testing)))))))
-
-(defn add-file-gen [{:keys [options :figwheel.main/config] :as cfg}]
- (let [output-to (test-file-output-to (:output-dir options))]
- (-> cfg
- ;; add prehook
- (update :figwheel.main/pre-build-hooks
- conj (pre-hook {:output-to output-to
- :test-display? (cljs-test-display? cfg)
- :initial-namespaces (find-test-namespaces (:watch-dirs config))}))
- ;; add build input
- (update-in [:figwheel.main/config :figwheel.main/build-inputs] conj output-to))))
-
-(defn plugin [cfg]
- (cond-> cfg
- (add-auto-testing? cfg)
- (-> add-extra-main add-file-gen)))
-
-))
+ ))))
+
+ (defn add-extra-main [cfg]
+ (let [id (-> cfg :figwheel.main/build :id)
+ ns' (genned-test-ns id)]
+ (assoc-in cfg [:figwheel.main/config :extra-main-files :auto-testing] {:main ns'})))
+
+ (defn add-auto-testing? [{:keys [options :figwheel.main/config] :as cfg}]
+ (and
+ (= :none (get options :optimizations :none))
+ (get config :auto-testing false)))
+
+ (defn cljs-test-display? [cfg]
+ (let [auto-testing (get-in cfg [:figwheel.main/config :auto-testing])]
+ (and (nil? (get-in cfg [:options :target]))
+ (not (and (map? auto-testing) (false? (:cljs-test-display auto-testing)))))))
+
+ (defn add-file-gen [{:keys [options :figwheel.main/config] :as cfg}]
+ (let [output-to (test-file-output-to (:output-dir options))]
+ (-> cfg
+ ;; add prehook
+ (update :figwheel.main/pre-build-hooks
+ conj (pre-hook {:output-to output-to
+ :test-display? (cljs-test-display? cfg)
+ :initial-namespaces (find-test-namespaces (:watch-dirs config))}))
+ ;; add build input
+ (update-in [:figwheel.main/config :figwheel.main/build-inputs] conj output-to))))
+
+ (defn plugin [cfg]
+ (cond-> cfg
+ (add-auto-testing? cfg)
+ (-> add-extra-main add-file-gen)))
+
+ ))
diff --git a/src/figwheel/main/util.clj b/src/figwheel/main/util.clj
index b25afec..6503207 100644
--- a/src/figwheel/main/util.clj
+++ b/src/figwheel/main/util.clj
@@ -55,14 +55,14 @@
(defn require-resolve-var-or-error [handler]
(when handler
(reduce
- (fn [v f]
- (try (f v)
- (catch Throwable t
- (reduced {:stage (fn->error f)
- :value v
- :exception t}))))
- handler
- [symbol->parts require-it resolve-it]))))
+ (fn [v f]
+ (try (f v)
+ (catch Throwable t
+ (reduced {:stage (fn->error f)
+ :value v
+ :exception t}))))
+ handler
+ [symbol->parts require-it resolve-it]))))
(defn require-resolve-handler-or-error [handler]
(when handler
@@ -75,18 +75,18 @@
(defn static-classpath []
(mapv
- #(.getCanonicalPath (io/file %))
- (string/split (System/getProperty "java.class.path")
- (java.util.regex.Pattern/compile (System/getProperty "path.separator")))))
+ #(.getCanonicalPath (io/file %))
+ (string/split (System/getProperty "java.class.path")
+ (java.util.regex.Pattern/compile (System/getProperty "path.separator")))))
(defn dynamic-classpath []
(mapv
- #(.getCanonicalPath (io/file (.getFile %)))
- (mapcat
- #(try (.getURLs %)
- (catch Throwable t
- nil))
- (take-while some? (iterate #(.getParent %) (.getContextClassLoader (Thread/currentThread)))))))
+ #(.getCanonicalPath (io/file (.getFile %)))
+ (mapcat
+ #(try (.getURLs %)
+ (catch Throwable t
+ nil))
+ (take-while some? (iterate #(.getParent %) (.getContextClassLoader (Thread/currentThread)))))))
#_((set (dynamic-classpath)) (.getCanonicalPath (io/file "src")))
#_(add-classpath! (.toURL (io/file "src")))
@@ -97,14 +97,14 @@
(defn dir-on-current-classpath? [dir]
((into #{}
(concat
- (static-classpath)
- (dynamic-classpath))) (.getCanonicalPath (io/file dir))))
+ (static-classpath)
+ (dynamic-classpath))) (.getCanonicalPath (io/file dir))))
(defn root-dynclass-loader []
(last
- (take-while
- #(instance? clojure.lang.DynamicClassLoader %)
- (iterate #(.getParent ^java.lang.ClassLoader %) (.getContextClassLoader (Thread/currentThread))))))
+ (take-while
+ #(instance? clojure.lang.DynamicClassLoader %)
+ (iterate #(.getParent ^java.lang.ClassLoader %) (.getContextClassLoader (Thread/currentThread))))))
(defn ensure-dynclass-loader! []
(let [cl (.getContextClassLoader (Thread/currentThread))]
@@ -139,8 +139,8 @@
(->> (file-seq (io/file "."))
(map str)
(filter
- #(or (string/ends-with? % (str sep cljs-path))
- (string/ends-with? % (str sep cljc-path))))
+ #(or (string/ends-with? % (str sep cljs-path))
+ (string/ends-with? % (str sep cljc-path))))
(filter valid-source-path?)
(sort-by count)
first)))
@@ -170,8 +170,8 @@
(try (bapi/ns->location ns)
(catch java.lang.IllegalArgumentException e
(throw (ex-info
- (str "ClojureScript Namespace " ns " was not found on the classpath.")
- {:figwheel.main/error true})))))
+ (str "ClojureScript Namespace " ns " was not found on the classpath.")
+ {:figwheel.main/error true})))))
(defn safe-ns->location [ns]
(try (bapi/ns->location ns)
@@ -192,11 +192,11 @@
(defn source-file-types-in-dir [dir]
(into
- #{}
- (map
- #(last (string/split % #"\."))
- (keep
- #(last (path-parts (str %)))
- (filter
- #(.isFile %)
- (file-seq (io/file dir)))))))
+ #{}
+ (map
+ #(last (string/split % #"\."))
+ (keep
+ #(last (path-parts (str %)))
+ (filter
+ #(.isFile %)
+ (file-seq (io/file dir)))))))
diff --git a/test/figwheel/main/test/utils.clj b/test/figwheel/main/test/utils.clj
index 3d5e3b4..da823f1 100644
--- a/test/figwheel/main/test/utils.clj
+++ b/test/figwheel/main/test/utils.clj
@@ -59,7 +59,7 @@ Example:
(fn [] ~@body)))
#_(with-edn-files
- {"hithere" {:hi :there}}
+ {"hithere" {:hi :there}}
(slurp "hithere"))
(defmacro with-err-str
diff --git a/test/figwheel/main_test.clj b/test/figwheel/main_test.clj
index 39ed5e9..4cf6696 100644
--- a/test/figwheel/main_test.clj
+++ b/test/figwheel/main_test.clj
@@ -39,11 +39,11 @@
(deftest noargs-uses-temp-dir-when-not-in-root-dir
(with-redefs [fm/should-add-temp-dir? (fn [_] true)]
(with-edn-files {:scripty-test.cljs "(println (+ 1 2 3))"}
- (uses-temp-dir? (:options (main->config)))
- (uses-temp-dir? (:options (main->config "-r")))
- (uses-temp-dir? (:options (main->config "-m" "figwheel.main")))
- (uses-temp-dir? (:options (main->config "scripty-test.cljs")))
- (uses-temp-dir? (:options (main->config "-"))))))
+ (uses-temp-dir? (:options (main->config)))
+ (uses-temp-dir? (:options (main->config "-r")))
+ (uses-temp-dir? (:options (main->config "-m" "figwheel.main")))
+ (uses-temp-dir? (:options (main->config "scripty-test.cljs")))
+ (uses-temp-dir? (:options (main->config "-"))))))
;; FIX logging output capture
(deftest auto-adds-target-classpath-for-compile
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment