This namespace contains all the functions we need to handle accessing the filesystem as well as resources inside the project itself.
(ns sidenotes.fs (:require [clojure.string :as string] [clojure.java.io :as io]))
Check if the given path points to an existing file.
(defn file? [path] (let [file (java.io.File. path)] (and (.exists file) (.isFile file))))
Performs roughly the same task as the UNIX ls
. That is, returns a seq of the filenames at a given directory. If a path to a file is supplied, then the seq contains only the original path given.
(defn ls [path] (let [file (java.io.File. path)] (if (.isDirectory file) (seq (.list file)) (when (.exists file) [path]))))
Create a directory for the given path.
(defn mkdir [path] (.mkdirs (io/file path)))
Ensure that the directory specified by path
exists. If not then make it so. Here is a snowman ☃
(defn ensure-directory! [path] (when-not (ls path) (mkdir path)))
Many Marginalia fns use dir? to recursively search a filepath.
(defn dir? [path] (.isDirectory (java.io.File. path)))
Shorten full file path by removing current dir prefix.
(defn shorten [path] (let [pwd (.getAbsolutePath (java.io.File. ""))] (if (.startsWith path pwd) (.substring path (inc (count pwd))) path)))
Returns a string containing the files extension.
(defn file-extension [filename] (second (re-find #"\\.([^.]+)\$" filename)))
Returns a string containing the files extension for a File instance.
(defn find-file-extension [^java.io.File file] (file-extension (.getName file)))
Predicate. Returns true for "normal" files with a file extension which passes the provided predicate.
(defn processable-file? [pred ^java.io.File file] (when (.isFile file) (-> file find-file-extension pred)))
Returns a seq of processable file paths (strings) in alphabetical order by namespace.
(defn find-processable-file-paths [dir pred] (->> (io/file dir) (file-seq) (filter (partial processable-file? pred)) (sort) (map #(.getCanonicalPath %))))
(def ^:private file-extensions #{"clj" "cljs" "cljx" "cljc"})
Given a collection of filepaths, returns a lazy sequence of filepaths to all .clj, .cljs, .cljx, and .cljc files on those paths: directory paths will be searched recursively for files.
(defn find-sources [sources] (if (nil? sources) (find-processable-file-paths "./src" file-extensions) (->> sources (mapcat #(if (dir? %) (find-processable-file-paths % file-extensions) [(.getCanonicalPath (io/file %))])))))
Try to find the readme file.
(defn find-readme [] (first (filter #(.startsWith (string/lower-case %) "readme") (ls "."))))
Load the readme file if possible.
(defn load-readme [] (let [readme (find-readme)] (if (nil? readme) {:has-readme false} {:has-readme true :file readme :type (string/lower-case (find-file-extension (io/file readme))) :content (slurp readme)})))
Find the name of the project from current folder.
(defn project-folder [] (last (clojure.string/split (str (io/as-url (io/file ""))) #"/")))
Stolen from leiningen
(defn slurp-resource [resource-name] (try (-> (.getContextClassLoader (Thread/currentThread)) (.getResourceAsStream resource-name) (java.io.InputStreamReader.) (slurp)) (catch java.lang.NullPointerException npe (println (str "Could not locate resources at " resource-name)) (println " ... attempting to fix.") (let [resource-name resource-name] (try (-> (.getContextClassLoader (Thread/currentThread)) (.getResourceAsStream resource-name) (java.io.InputStreamReader.) (slurp)) (catch java.lang.NullPointerException npe (println (str " STILL could not locate resources at " resource-name ". Giving up!"))))))))
Load a resource and spit it to the output folder.
(defn spit-resource [resource from to] (ensure-directory! (str to "/" (string/join "/" (butlast (string/split resource #"/"))))) (dorun (println (str "\\t" resource " to " to))) (spit (str to "/" resource) (slurp-resource (str from "/" resource))))
Copy a file to the output folder.
(defn copy-file [file from to] (ensure-directory! (str to "/" (string/join "/" (butlast (string/split file #"/"))))) (dorun (println (str "\\t" file " to " to))) (io/copy (io/file (str from "/" file)) (io/file (str to "/" file))))