(import glob [glob]) (import subprocess [check-output]) (import os [mkdir stat]) (import os.path [isfile :as file? isdir :as dir?]) (import templates *) (import utils *) (import hy.compiler [hy-eval]) (require hyrule.control [defmain]) (require hyrule.argmove [->]) (setv local-scope (locals)) (setv global-scope (globals)) (defmacro inherit [#* names] (lfor name names `(setx ~name (get local-scope (str (get '(~name) 0)))))) (defmacro enshrine [#* names] (lfor name names `(setv (get local-scope (str (get '(~name) 0))) ~name))) (defn last-changed [file] (getattr (stat file) "st_ctime")) (defn last-changed-prev-compile [file] (getattr (stat (-> file (.replace ".hy" ".html") (.replace "./pages/" "../site/html/"))) "st_ctime")) (defmain [] (setv last-compile-time (last-changed "../site")) (setv data-dir-changed? (> (last-changed "data") last-compile-time)) (setv last-commit-newer (> (-> (check-output #[[git log -1 --format="%at"]] :shell True) (.decode) (.strip) (int)) last-compile-time)) (print f"last compiled: {last-compile-time :.0f}") (when (not (dir? "output")) (mkdir "output")) (for [path (glob "./pages/**/*" :recursive True)] (when (in "__pycache__" path) (continue)) (cond (and (dir? path) (not (dir? (.replace path "pages" "output")))) (do (print f"creating {path}") (mkdir (.replace path "pages" "output"))) (file? path) ;; only recompile pages when: ;; - the source page is newer than the output ;; - the `src/data` directory is newer than the output ;; - the latest commit is newer than the output (if (or (> (last-changed path) (last-changed-prev-compile path)) data-dir-changed? last-commit-newer) (do (print f"building {path}") (setv page-name (.split (cut path 2 -3) "/")) (enshrine page-name) (with [target (open (+ "./output/" (.join "/" (cut page-name 1 None)) ".html") "w")] (.write target (form->html (hy-eval (hy.read (with [source (open path "r")] (.read source))) :locals local-scope :globals global-scope))))) (print f"{(.replace path #[[./pages/]] #[[../site/html/]])} more recent, skipping")))))