<commit_before>(ns figwheel-sidecar.components.cljs-autobuild
  (:require
   [figwheel-sidecar.config :refer [prep-build prepped?]]
   [figwheel-sidecar.build-utils :as butils]
   [figwheel-sidecar.watching :as watching]
   [figwheel-sidecar.utils :as utils]
   [figwheel-sidecar.cljs-utils.exception-parsing :as cljs-ex]
   [figwheel-sidecar.config-check.ansi :refer [with-color with-color-when color-text]]
   
      ;; build hooks
   [figwheel-sidecar.build-middleware.injection :as injection]
   [figwheel-sidecar.build-middleware.notifications :as notifications]
   [figwheel-sidecar.build-middleware.clj-reloading :as clj-reloading]
   [figwheel-sidecar.build-middleware.javascript-reloading :as javascript-reloading]
   [figwheel-sidecar.build-middleware.stamp-and-clean :as stamp-and-clean]
   
   [com.stuartsierra.component :as component]
   [cljs.closure]
   [cljs.build.api :as bapi]
   [clojure.java.io :as io]
   [clojure.java.shell :refer [sh]]
   [clojure.java.browse]))

;; TODO can I run this without a figwheel server??
;; that would make this component much more useful

(defn cljs-build [{:keys [build-config]}]
  (bapi/build
   (apply bapi/inputs (:source-paths build-config))
   (:build-options build-config)
   (:compiler-env build-config)))

(defn time-elapsed [started-at]
  (let [elapsed-us (- (System/currentTimeMillis) started-at)]
    (with-precision 2
      (str (/ (double elapsed-us) 1000) " seconds"))))

(defn figwheel-start-and-end-messages [build-fn]
  (fn [{:keys [figwheel-server build-config changed-files] :as build-state}]
    (let [started-at (System/currentTimeMillis)
          {:keys [build-options source-paths]} build-config
            {:keys [output-to]} build-options]
      ;; print start message
      (println (color-text (str "Compiling \"" output-to
                       "\" from " (pr-str source-paths) "...")
                :none))
      (try
        (build-fn build-state)
        (println (color-text (str "Successfully compiled \"" output-to
                               "\" in " (time-elapsed started-at) ".")
                              :green))
        (catch Throwable e
          (println (color-text (str 
                                "Failed to compile \""
                                output-to
                                "\" in " (time-elapsed started-at) ".")
                               :red))
          (throw e))
        (finally (flush))))))

(defn handle-notify-command [build-state s]
  (when-let [notify-command (-> build-state :build-config :notify-command)]
    (apply sh (concat notify-command [s]))))

(defn notify-command-hook [build-fn]
  (fn [build-state]
    (try
      (build-fn build-state)
      (handle-notify-command build-state (str "Successfully compiled ClojureScript build: "
                                              (name (-> build-state :build-config :id))))
      (catch Throwable e
        (handle-notify-command build-state (str "Failed compiling ClojureScript build: "
                                                (name (-> build-state :build-config :id))))
        (throw e)))))

(defn color-output [build-fn]
  (fn [{:keys [figwheel-server] :as build-state}]
    (with-color-when (-> figwheel-server :ansi-color-output)
      (build-fn build-state))))

(def figwheel-build
  (-> cljs-build
      injection/hook
      notify-command-hook
      clj-reloading/hook
      javascript-reloading/hook
      figwheel-start-and-end-messages
      notifications/hook
      color-output))

(def figwheel-build-without-javascript-reloading
  (-> cljs-build
      injection/hook
      notify-command-hook      
      clj-reloading/hook
      figwheel-start-and-end-messages
      notifications/hook
      color-output))

(def figwheel-build-without-clj-reloading
  (-> cljs-build
      injection/hook
      notify-command-hook      
      javascript-reloading/hook
      figwheel-start-and-end-messages
      notifications/hook
      color-output))

(defn source-paths-that-affect-build [{:keys [build-options source-paths]}]
  (let [{:keys [libs foreign-libs]} build-options]
    (concat
     source-paths<commit_msg>javascript and clj reloading hooks were misplaced<commit_after>(ns figwheel-sidecar.components.cljs-autobuild
  (:require
   [figwheel-sidecar.config :refer [prep-build prepped?]]
   [figwheel-sidecar.build-utils :as butils]
   [figwheel-sidecar.watching :as watching]
   [figwheel-sidecar.utils :as utils]
   [figwheel-sidecar.cljs-utils.exception-parsing :as cljs-ex]
   [figwheel-sidecar.config-check.ansi :refer [with-color with-color-when color-text]]
   
      ;; build hooks
   [figwheel-sidecar.build-middleware.injection :as injection]
   [figwheel-sidecar.build-middleware.notifications :as notifications]
   [figwheel-sidecar.build-middleware.clj-reloading :as clj-reloading]
   [figwheel-sidecar.build-middleware.javascript-reloading :as javascript-reloading]
   [figwheel-sidecar.build-middleware.stamp-and-clean :as stamp-and-clean]
   
   [com.stuartsierra.component :as component]
   [cljs.closure]
   [cljs.build.api :as bapi]
   [clojure.java.io :as io]
   [clojure.java.shell :refer [sh]]
   [clojure.java.browse]))

;; TODO can I run this without a figwheel server??
;; that would make this component much more useful

(defn cljs-build [{:keys [build-config]}]
  (bapi/build
   (apply bapi/inputs (:source-paths build-config))
   (:build-options build-config)
   (:compiler-env build-config)))

(defn time-elapsed [started-at]
  (let [elapsed-us (- (System/currentTimeMillis) started-at)]
    (with-precision 2
      (str (/ (double elapsed-us) 1000) " seconds"))))

(defn figwheel-start-and-end-messages [build-fn]
  (fn [{:keys [figwheel-server build-config changed-files] :as build-state}]
    (let [started-at (System/currentTimeMillis)
          {:keys [build-options source-paths]} build-config
            {:keys [output-to]} build-options]
      ;; print start message
      (println (color-text (str "Compiling \"" output-to
                       "\" from " (pr-str source-paths) "...")
                :none))
      (try
        (build-fn build-state)
        (println (color-text (str "Successfully compiled \"" output-to
                               "\" in " (time-elapsed started-at) ".")
                              :green))
        (catch Throwable e
          (println (color-text (str 
                                "Failed to compile \""
                                output-to
                                "\" in " (time-elapsed started-at) ".")
                               :red))
          (throw e))
        (finally (flush))))))

(defn handle-notify-command [build-state s]
  (when-let [notify-command (-> build-state :build-config :notify-command)]
    (apply sh (concat notify-command [s]))))

(defn notify-command-hook [build-fn]
  (fn [build-state]
    (try
      (build-fn build-state)
      (handle-notify-command build-state (str "Successfully compiled ClojureScript build: "
                                              (name (-> build-state :build-config :id))))
      (catch Throwable e
        (handle-notify-command build-state (str "Failed compiling ClojureScript build: "
                                                (name (-> build-state :build-config :id))))
        (throw e)))))

(defn color-output [build-fn]
  (fn [{:keys [figwheel-server] :as build-state}]
    (with-color-when (-> figwheel-server :ansi-color-output)
      (build-fn build-state))))

;; !! assume nothing about the order of middleware !!
;; if the order changes re-verify the function of each part
(def figwheel-build
  (-> cljs-build
      injection/hook
      notify-command-hook
      figwheel-start-and-end-messages
      notifications/hook
      ;; the following two hooks have to be called before the notifications
      ;; a they modify the message on the way down
      clj-reloading/hook
      javascript-reloading/hook      
      color-output))

(def figwheel-build-without-javascript-reloading
  (-> cljs-build
      injection/hook
      notify-command-hook      
      figwheel-start-and-end-messages
      notifications/hook
      clj-reloading/hook
      color-output))

(def figwheel-build-without-clj-reloading
  (-> cljs-build
      injection/hook
      notify-command-hook      
      figwheel-start-and-end-messages
      notifications/hook
      javascript-reloading/hook
      color-output))

(defn source-paths-that-affect-build [{:keys [build-options source-paths]}]
  (let [{:keys [libs foreign-libs]} build-options]
    (concat
     source-paths
{'fraction_non_alphanumeric': 0.13100385649176113, 'fraction_numerical': 0.001168633867009466, 'mean_word_length': 2.3600314095013744, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 14, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7057027', 'n_tokens_mistral': 2679, 'n_tokens_neox': 2611, 'n_words': 570}