<commit_before>(ns less4clj.api
  (:require [less4clj.watcher :as watcher]
            [less4clj.core :as core]
            [clojure.java.io :as io]
            [clojure.spec.alpha :as s]))

(defn main-file? [file]
  (.endsWith (.getName file) ".main.less"))

(defn find-main-files [source-paths]
  (mapcat (fn [source-path]
            (let [file (io/file source-path)]
              (->> (file-seq file)
                   (filter main-file?)
                   (map (fn [x] [(.getPath x) (.toString (.relativize (.toURI file) (.toURI x)))])))))
          source-paths))

(defn print-warning [warning]
  (println (format "WARN: %s %s\n" (:message warning)
                   (str (if (:uri (:source warning))
                          (str "on file "
                               (:uri (:source warning))
                               (if (:line warning)
                                 (str " at line " (:line warning) " character " (:char warning)))))))))

(defn compile-less [main-files {:keys [auto target-path] :as options}]
  (try
    (doseq [[path relative-path] main-files]
      (println (format "Compiling {less}... %s" relative-path))
      (let [result
            (try
              (core/less-compile-to-file
                path
                (.getPath (io/file target-path))
                relative-path
                (dissoc options :target-path :source-paths))
              (catch Exception e
                (if auto
                  (println (.getMessage e))
                  (throw e))))]
        (doseq [warning (:warnings result)]
          (print-warning warning))))
    (catch Exception e
      (if (= :less4clj.core/error (:type (ex-data e)))
        (println (.getMessage e))
        (throw e)))))

(s/def ::source-paths (s/coll-of string? :into vec))
(s/def ::auto boolean?)
(s/def ::help boolean?)
(s/def ::target-path string?)
(s/def ::compression boolean?)
(s/def ::source-map boolean?)
(s/def ::inline-javascript boolean?)
(s/def ::verbosity #{1 2})
(s/def ::options (s/keys :req-un [::source-paths ::target-path]
                         :opt-un [::auto ::help ::compression ::source-map
                                  ::inline-javascript ::verbosity]))

(defn build [{:keys [source-paths auto] :as options}]
  (when-not (s/valid? ::options options)
    (s/explain-out (s/explain-data ::options options)))
  (let [options (dissoc options :source-paths)]
    (if auto
      (watcher/start source-paths (fn [& _]
                                    (let [main-files (find-main-files source-paths)]
                                      (compile-less main-files options))))
      (let [main-files (find-main-files source-paths)]
        (compile-less main-files options)))))

(defn start [options]
  (build (assoc options :auto true)))

(defn stop [this]
  (if this
    (watcher/stop this)))
<commit_msg>Add notice if no mail files are found<commit_after>(ns less4clj.api
  (:require [less4clj.watcher :as watcher]
            [less4clj.core :as core]
            [clojure.java.io :as io]
            [clojure.spec.alpha :as s]))

(defn main-file? [file]
  (.endsWith (.getName file) ".main.less"))

(defn find-main-files [source-paths]
  (mapcat (fn [source-path]
            (let [file (io/file source-path)]
              (->> (file-seq file)
                   (filter main-file?)
                   (map (fn [x] [(.getPath x) (.toString (.relativize (.toURI file) (.toURI x)))])))))
          source-paths))

(defn print-warning [warning]
  (println (format "WARN: %s %s\n" (:message warning)
                   (str (if (:uri (:source warning))
                          (str "on file "
                               (:uri (:source warning))
                               (if (:line warning)
                                 (str " at line " (:line warning) " character " (:char warning)))))))))

(defn compile-less [main-files {:keys [auto target-path] :as options}]
  (try
    (doseq [[path relative-path] main-files]
      (println (format "Compiling {less}... %s" relative-path))
      (let [result
            (try
              (core/less-compile-to-file
                path
                (.getPath (io/file target-path))
                relative-path
                (dissoc options :target-path :source-paths))
              (catch Exception e
                (if auto
                  (println (.getMessage e))
                  (throw e))))]
        (doseq [warning (:warnings result)]
          (print-warning warning))))
    (catch Exception e
      (if (= :less4clj.core/error (:type (ex-data e)))
        (println (.getMessage e))
        (throw e)))))

(s/def ::source-paths (s/coll-of string? :into vec))
(s/def ::auto boolean?)
(s/def ::help boolean?)
(s/def ::target-path string?)
(s/def ::compression boolean?)
(s/def ::source-map boolean?)
(s/def ::inline-javascript boolean?)
(s/def ::verbosity #{1 2})
(s/def ::options (s/keys :req-un [::source-paths ::target-path]
                         :opt-un [::auto ::help ::compression ::source-map
                                  ::inline-javascript ::verbosity]))

(defn- find-files-and-compile [source-paths options]
  (let [main-files (find-main-files source-paths)]
    (when-not (seq main-files)
      (println "No files with a \".main.less\" suffix found."))
    (compile-less main-files options)))

(defn build [{:keys [source-paths auto] :as options}]
  (when-not (s/valid? ::options options)
    (s/explain-out (s/explain-data ::options options)))
  (let [options (dissoc options :source-paths)]
    (if auto
      (watcher/start source-paths (fn [& _]
                                    (find-files-and-compile source-paths options)))
      (find-files-and-compile source-paths options))))

(defn start [options]
  (build (assoc options :auto true)))

(defn stop [this]
  (if this
    (watcher/stop this)))

{'fraction_non_alphanumeric': 0.15879534565366188, 'fraction_numerical': 0.002053388090349076, 'mean_word_length': 1.9094076655052266, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4852507', 'n_tokens_mistral': 1832, 'n_tokens_neox': 1752, 'n_words': 493}