From 29d5cdc85a8ee876e05ce3d111a4eec1f85fc687 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Madeleine=20Sydney=20=C5=9Alaga?= Date: Sun, 22 Mar 2026 13:24:59 -0600 Subject: [PATCH] feat: o pona e ijo Config kepeken lipu Library --- doerg/default.nix | 18 +++- doerg/deps.edn | 3 +- doerg/doerg-parser/default.nix | 1 + doerg/doerg-temml-worker/default.nix | 1 + .../net/deertopia/doerg/default-config.edn | 13 +++ doerg/src/net/deertopia/doerg/config.clj | 95 ++++++++++++------- doerg/src/net/deertopia/doerg/element.clj | 3 +- doerg/src/net/deertopia/doerg/html.clj | 1 - doerg/src/net/deertopia/doerg/repl.clj | 12 +-- doerg/src/net/deertopia/doerg/tex/native.clj | 7 +- doerg/src/net/deertopia/doerg/tex/temml.clj | 5 +- .../test/net/deertopia/doerg/config_test.clj | 8 -- publisher/default.nix | 4 +- publisher/deps.edn | 3 +- publisher/override_deps.bb | 5 +- .../net/deertopia/publisher/config.edn | 5 + .../src/net/deertopia/publisher/config.clj | 29 ++++-- .../src/net/deertopia/publisher/roam.clj | 3 +- .../src/net/deertopia/publisher/server.clj | 5 +- 19 files changed, 146 insertions(+), 75 deletions(-) create mode 100644 doerg/resources/net/deertopia/doerg/default-config.edn delete mode 100644 doerg/test/net/deertopia/doerg/config_test.clj create mode 100644 publisher/resources/net/deertopia/publisher/config.edn diff --git a/doerg/default.nix b/doerg/default.nix index 5c24894..e10fdb9 100644 --- a/doerg/default.nix +++ b/doerg/default.nix @@ -7,6 +7,7 @@ , fake-git , our-tex ? callPackage ./our-tex.nix {} , makeWrapper +, writeText }: let @@ -23,11 +24,21 @@ let plex = ibm-plex-web.override { families = [ "math" "serif" "sans" "sans-kr" ]; }; + bin-path = lib.makeBinPath [ doerg-parser our-tex doerg-temml-worker ]; + + doerg-config = writeText "doerg-extra-config.edn" '' + #:net.deertopia.doerg + {:ibm-plex-web "${ibm-plex-web}" + :latex "${lib.getExe' our-tex "xelatex"}" + :dvisvgm "${lib.getExe' our-tex "dvisvgm"}" + :doerg-temml-worker "${lib.getExe doerg-temml-worker}" + :doerg-parser "${lib.getExe doerg-parser}"} + ''; in mkCljBin' { name = "net.deertopia/doerg"; version = "0.1.0"; @@ -50,12 +61,11 @@ in mkCljBin' { plex our-tex ]; + preBuild = '' + cp ${doerg-config} resources/net/deertopia/doerg/extra-config.edn + ''; doCheck = true; checkPhase = '' clojure -M:test ''; - postInstall = '' - wrapProgram $out/bin/doerg \ - --prefix PATH : ${bin-path} - ''; } diff --git a/doerg/deps.edn b/doerg/deps.edn index f71a480..3c5ce17 100644 --- a/doerg/deps.edn +++ b/doerg/deps.edn @@ -10,7 +10,8 @@ lambdaisland/deep-diff2 {:mvn/version "2.12.219"} mvxcvi/clj-cbor {:mvn/version "1.1.1"} ch.qos.logback/logback-classic {:mvn/version "1.1.3"} - org.clojure/test.check {:mvn/version "1.1.3"}} + org.clojure/test.check {:mvn/version "1.1.3"} + aero/aero {:mvn/version "1.1.6"}} :paths ["src" "resources" "test"] :aliases {:test {:extra-deps {lambdaisland/kaocha {:mvn/version "1.91.1392"}} diff --git a/doerg/doerg-parser/default.nix b/doerg/doerg-parser/default.nix index cb76bdd..ed3fd04 100644 --- a/doerg/doerg-parser/default.nix +++ b/doerg/doerg-parser/default.nix @@ -10,4 +10,5 @@ buildNpmPackage { npmDeps = importNpmLock { npmRoot = ./.; }; npmConfigHook = importNpmLock.npmConfigHook; dontNpmBuild = true; + meta.mainProgram = "doerg-parser"; } diff --git a/doerg/doerg-temml-worker/default.nix b/doerg/doerg-temml-worker/default.nix index f57aa33..4980605 100644 --- a/doerg/doerg-temml-worker/default.nix +++ b/doerg/doerg-temml-worker/default.nix @@ -18,4 +18,5 @@ buildNpmPackage { npmDeps = importNpmLock { npmRoot = ./.; }; npmConfigHook = importNpmLock.npmConfigHook; dontNpmBuild = true; + meta.mainProgram = "doerg-temml-worker"; } diff --git a/doerg/resources/net/deertopia/doerg/default-config.edn b/doerg/resources/net/deertopia/doerg/default-config.edn new file mode 100644 index 0000000..175b83a --- /dev/null +++ b/doerg/resources/net/deertopia/doerg/default-config.edn @@ -0,0 +1,13 @@ +#:net.deertopia.doerg +{:ibm-plex-web #or [#xdg-data-dir "ibm-plex-web" + #env IBM_PLEX_WEB] + :latex "xelatex" + :dvisvgm "dvisvgm" + :doerg-temml-worker + #profile {:dev-publisher "../doerg/doerg-temml-worker/index.js" + :dev-doerg "./doerg-temml-worker/index.js" + :default "doerg-temml-worker"} + :doerg-parser + #profile {:dev-publisher "../doerg/doerg-parser/index.js" + :dev-doerg "./doerg-parser/index.js" + :default "doerg-parser"}} diff --git a/doerg/src/net/deertopia/doerg/config.clj b/doerg/src/net/deertopia/doerg/config.clj index f9c6806..b4d900d 100644 --- a/doerg/src/net/deertopia/doerg/config.clj +++ b/doerg/src/net/deertopia/doerg/config.clj @@ -1,42 +1,73 @@ (ns net.deertopia.doerg.config (:require [clojure.spec.alpha :as s] [babashka.fs :as fs] - [spec-dict.main :refer [dict]])) + [spec-dict.main :refer [dict]] + [aero.core :as aero] + [net.deertopia.doerg :as-alias d] + [clojure.java.io :as io])) -(s/def ::config - (s/keys :req [::ibm-plex-web - ::latex - ::dvisvgm - ::doerg-temml-worker - ::doerg-parser])) +(s/def ::d/config + (s/keys :req [::d/ibm-plex-web + ::d/latex + ::d/dvisvgm + ::d/doerg-temml-worker + ::d/doerg-parser])) -(s/def ::file - (s/conformer (comp fs/file fs/absolutize fs/expand-home))) +(s/def ::d/directory + (s/conformer #(fs/file %))) -(s/def ::executable #(or (fs/executable? %) - (and (fs/relative? %) - (fs/which %)))) +(s/def ::d/file + (s/conformer #(-> % fs/expand-home fs/file))) + +(s/def ::d/executable + (s/conformer + ;; I'd love to use `fs/which` here, but it's fairly problematic to + ;; check `fs/executable?` at… build time (which `fs/which` does)? + ;; Wait… what? Do I know how Clojure compilation works? + #(or #_(some-> % fs/expand-home fs/which fs/file) + (some-> % fs/expand-home fs/file) + ::s/invalid))) + +(s/def ::d/ibm-plex-web ::d/directory) + +(s/def ::d/latex ::d/executable) + +(s/def ::d/dvisvgm ::d/executable) + +(s/def ::d/doerg-temml-worker ::d/executable) + +(s/def ::d/doerg-parser ::d/executable) + +(defmethod aero/reader 'xdg-data-dir + [_opts tag value] + "Aero tag to search for a directory on $XDG_DATA_DIRS." + (some #(let [x (fs/path % value)] + (and (fs/exists? x) x)) + (fs/split-paths (System/getenv "XDG_DATA_DIRS")))) + +(defn make-read-config [spec] + (fn [& files] + (let [r (->> files + (filter identity) + (map aero/read-config) + (apply merge)) + conformed (s/conform spec r)] + (if-not (s/invalid? conformed) + conformed + (throw (IllegalArgumentException. + "bad config" + (ex-info "couldn't conform" + (s/explain-data spec r)))))))) + +(def read-config (make-read-config ::d/config)) (def default - {::ibm-plex-web - (fs/file (some #(let [x (fs/path % "ibm-plex-web")] - (and (fs/exists? x) x)) - (fs/split-paths (System/getenv "XDG_DATA_DIRS")))) - ::latex "xelatex" - ::dvisvgm "dvisvgm" - ;; TODO: Can we automatically set this to "./doerg-temml-worker/index.js" in - ;; a development environment? - ::doerg-temml-worker "doerg-temml-worker" - ::doerg-parser "doerg-parser"}) + (read-config + ;; Default config. + (io/resource "net/deertopia/doerg/default-config.edn") + ;; Defaults set at build time, if any. + (io/resource "net/deertopia/doerg/extra-config.edn") + ;; Config set at runtime. + (System/getenv "DOERG_CONFIG"))) (def ^:dynamic *cfg* default) - -(s/def ::ibm-plex-web ::file) - -(s/def ::latex ::executable) - -(s/def ::dvisvgm ::executable) - -(s/def ::doerg-temml-worker ::executable) - -(s/def ::doerg-parser ::executable) diff --git a/doerg/src/net/deertopia/doerg/element.clj b/doerg/src/net/deertopia/doerg/element.clj index 8a4dda6..7ab7b11 100644 --- a/doerg/src/net/deertopia/doerg/element.clj +++ b/doerg/src/net/deertopia/doerg/element.clj @@ -4,6 +4,7 @@ [babashka.process :as p] [cheshire.core :as json] [clojure.core.match :refer [match]] + [net.deertopia.doerg :as-alias doerg] [clojure.java.io :as io] [clojure.set :as set] [clojure.spec.alpha :as s] @@ -36,7 +37,7 @@ :or {in *in*}}] (let [r (-> (p/process {:in in :out :string} - (::cfg/doerg-parser cfg/*cfg*)) + (-> cfg/*cfg* ::doerg/doerg-parser str)) (common/deref-with-timeout *uniorg-timeout-duration*))] (when (zero? (:exit r)) (-> r :out (json/parse-string (comp keyword camel->kebab)))))) diff --git a/doerg/src/net/deertopia/doerg/html.clj b/doerg/src/net/deertopia/doerg/html.clj index 0a17511..d7d9cd3 100644 --- a/doerg/src/net/deertopia/doerg/html.clj +++ b/doerg/src/net/deertopia/doerg/html.clj @@ -1,7 +1,6 @@ (ns net.deertopia.doerg.html "Common HTML elements and utilities" (:require [clojure.java.io :as io] - [net.deertopia.doerg.config :as cfg] [babashka.fs :as fs])) #_ diff --git a/doerg/src/net/deertopia/doerg/repl.clj b/doerg/src/net/deertopia/doerg/repl.clj index 7da4afa..9a76170 100644 --- a/doerg/src/net/deertopia/doerg/repl.clj +++ b/doerg/src/net/deertopia/doerg/repl.clj @@ -5,7 +5,8 @@ [clojure.java.io :as io] [hiccup2.core :as h] [clojure.pprint] - [babashka.fs :as fs])) + [babashka.fs :as fs] + [net.deertopia.doerg :as-alias doerg])) (def some-org-file #_ @@ -27,19 +28,12 @@ (fs/delete-if-exists path) (fs/create-sym-link path target)) -(defn reconfigure-doerg! [] - (alter-var-root - #'cfg/*cfg* - #(assoc % - ::cfg/doerg-temml-worker "./doerg-temml-worker/index.js" - ::cfg/doerg-parser "./doerg-parser/index.js"))) - (defn render-html [& {:keys [src dest] :or {src some-org-file dest "/tmp/doerg-test"}}] (fs/create-dirs dest) (force-create-sym-link (fs/file dest "ibm-plex-web") - (-> cfg/*cfg* ::cfg/ibm-plex-web)) + (-> cfg/*cfg* ::doerg/ibm-plex-web)) (force-create-sym-link (fs/file dest "deerstar.css") (io/resource "net/deertopia/doerg/deerstar.css")) (force-create-sym-link (fs/file dest "tuftesque.css") diff --git a/doerg/src/net/deertopia/doerg/tex/native.clj b/doerg/src/net/deertopia/doerg/tex/native.clj index 90832e6..bba01c2 100644 --- a/doerg/src/net/deertopia/doerg/tex/native.clj +++ b/doerg/src/net/deertopia/doerg/tex/native.clj @@ -7,7 +7,8 @@ [clojure.string :as str] [clojure.tools.logging :as l] [babashka.fs :as fs] - [net.deertopia.doerg.config :as cfg]) + [net.deertopia.doerg.config :as cfg] + [net.deertopia.doerg :as-alias doerg]) (:import (java.io ByteArrayOutputStream))) (def ^:private scale-divisor 66873.46948423679) @@ -82,14 +83,14 @@ acc)))) (defn- invoke-latex [& {:keys [file output-dir]}] - (let [latex (::cfg/latex cfg/*cfg*)] + (let [latex (-> cfg/*cfg* ::doerg/latex)] (invoke {:dir output-dir} latex "-no-pdf" "-interaction" "nonstopmode" "-output-directory" output-dir file))) (defn- invoke-dvisvgm [& {:keys [file output-dir]}] - (let [dvisvgm (::cfg/dvisvgm cfg/*cfg*)] + (let [dvisvgm (-> cfg/*cfg* ::doerg/dvisvgm)] (invoke {:dir output-dir} dvisvgm "--page=1-" "--optimize" "--clipjoin" diff --git a/doerg/src/net/deertopia/doerg/tex/temml.clj b/doerg/src/net/deertopia/doerg/tex/temml.clj index c45752a..22082fb 100644 --- a/doerg/src/net/deertopia/doerg/tex/temml.clj +++ b/doerg/src/net/deertopia/doerg/tex/temml.clj @@ -6,7 +6,8 @@ [clojure.java.io :as io] [clojure.string :as str] [clojure.tools.logging :as l] - [babashka.fs :as fs]) + [babashka.fs :as fs] + [net.deertopia.doerg :as-alias doerg]) (:import (java.io ByteArrayOutputStream))) (def ^:dynamic *worker-timeout-duration* @@ -21,7 +22,7 @@ :suffix ".tex"})) (defn worker [] - (let [doerg-temml-worker (::cfg/doerg-temml-worker cfg/*cfg*)] + (let [doerg-temml-worker (-> cfg/*cfg* ::doerg/doerg-temml-worker)] (when-not (fs/exists? prelude-file) (-> "net/deertopia/doerg/prelude.tex" io/resource diff --git a/doerg/test/net/deertopia/doerg/config_test.clj b/doerg/test/net/deertopia/doerg/config_test.clj deleted file mode 100644 index e7902eb..0000000 --- a/doerg/test/net/deertopia/doerg/config_test.clj +++ /dev/null @@ -1,8 +0,0 @@ -(ns net.deertopia.doerg.config-test - (:require [net.deertopia.doerg.config :as sut] - [clojure.test :as t] - [clojure.spec.alpha :as s])) - -(t/deftest default-config-is-config - (t/testing "default config is valid" - (t/is (s/valid? ::sut/config sut/default)))) diff --git a/publisher/default.nix b/publisher/default.nix index 9f757d9..f8da10b 100644 --- a/publisher/default.nix +++ b/publisher/default.nix @@ -9,7 +9,9 @@ mkCljBin { projectSrc = ./.; lockfile = ../deps-lock.json; main-ns = "net.deertopia.publisher.main"; - buildInputs = []; + buildInputs = [ + doerg + ]; nativeBuildInputs = [ babashka ]; diff --git a/publisher/deps.edn b/publisher/deps.edn index 1bbb4e8..f603fb7 100644 --- a/publisher/deps.edn +++ b/publisher/deps.edn @@ -11,5 +11,6 @@ net.deertopia/doerg {:local/root "../doerg"} metosin/reitit {:mvn/version "0.10.1"} http-kit/http-kit {:mvn/version "2.8.0"} - instaparse/instaparse {:mvn/version "1.5.0"}} + instaparse/instaparse {:mvn/version "1.5.0"} + aero/aero {:mvn/version "1.1.6"}} :paths ["src" "resources" "test"]} diff --git a/publisher/override_deps.bb b/publisher/override_deps.bb index 3a0899a..afcbc4f 100644 --- a/publisher/override_deps.bb +++ b/publisher/override_deps.bb @@ -20,7 +20,10 @@ (loop [os (seq overrides) loc zloc] (if-some [[[k v] & xs] os] - (recur xs (z/assoc loc k v)) + (do (binding [*out* *err*] + (printf "override dep %s with %s\n" + (pr-str k) (pr-str v))) + (recur xs (z/assoc loc k v))) loc))) (defn args->overrides [args] diff --git a/publisher/resources/net/deertopia/publisher/config.edn b/publisher/resources/net/deertopia/publisher/config.edn new file mode 100644 index 0000000..d467e9c --- /dev/null +++ b/publisher/resources/net/deertopia/publisher/config.edn @@ -0,0 +1,5 @@ +#:net.deertopia.publisher +{:state-directory #join [#or [#env XDG_STATE_HOME + #envf ["%s/.local/share" HOME]] + "/doerg-publisher"] + :org-roam-db-path #join [#env HOME "/.cache/emacs/org-roam.db"]} diff --git a/publisher/src/net/deertopia/publisher/config.clj b/publisher/src/net/deertopia/publisher/config.clj index c1328c1..67745ab 100644 --- a/publisher/src/net/deertopia/publisher/config.clj +++ b/publisher/src/net/deertopia/publisher/config.clj @@ -1,17 +1,28 @@ (ns net.deertopia.publisher.config (:require [babashka.fs :as fs] [clojure.spec.alpha :as s] - [net.deertopia.doerg.config :as doerg])) + [net.deertopia.doerg.config :as doerg-config] + [net.deertopia.doerg :as-alias doerg] + [net.deertopia.publisher :as-alias p] + [aero.core :as aero] + [clojure.java.io :as io])) -(s/def ::config - (s/keys :req [::state-directory - ::org-roam-db-path])) +(s/def ::p/config + (s/keys :req [::p/state-directory + ::p/org-roam-db-path])) + +(s/def ::p/state-directory ::doerg/file) +(s/def ::p/org-roam-db-path ::doerg/file) + +(def read-config (doerg-config/make-read-config ::p/config)) (def default - {::state-directory (fs/xdg-state-home "doerg-publisher") - ::org-roam-db-path (fs/file (fs/home) ".cache" "emacs" "org-roam.db")}) + (read-config + ;; Default config. + (io/resource "net/deertopia/publisher/config.edn") + ;; Defaults set at build time, if any. + (io/resource "net/deertopia/publisher/extra-config.edn") + ;; Config set at runtime. + (System/getenv "DOERG_PUBLISHER_CONFIG"))) (def ^:dynamic *cfg* default) - -(s/def ::state-directory ::doerg/file) -(s/def ::org-roam-db-path ::doerg/file) diff --git a/publisher/src/net/deertopia/publisher/roam.clj b/publisher/src/net/deertopia/publisher/roam.clj index 765bb45..f34f650 100644 --- a/publisher/src/net/deertopia/publisher/roam.clj +++ b/publisher/src/net/deertopia/publisher/roam.clj @@ -3,6 +3,7 @@ [net.deertopia.publisher.config :as cfg] [net.deertopia.publisher.elisp :as elisp] [net.deertopia.publisher.slug :as slug] + [net.deertopia.publisher :as-alias publisher] [next.jdbc :as sql]) (:import (java.util UUID))) @@ -11,7 +12,7 @@ (defonce ^:dynamic *use-db-cache?* true) -(def db-path (-> cfg/*cfg* ::cfg/org-roam-db-path +(def db-path (-> cfg/*cfg* ::publisher/org-roam-db-path fs/expand-home str)) (def db {:dbtype "sqlite" diff --git a/publisher/src/net/deertopia/publisher/server.clj b/publisher/src/net/deertopia/publisher/server.clj index 6373d7c..20c600d 100644 --- a/publisher/src/net/deertopia/publisher/server.clj +++ b/publisher/src/net/deertopia/publisher/server.clj @@ -18,7 +18,10 @@ [reitit.spec] [reitit.dev.pretty] [clojure.spec.alpha :as s] - [net.deertopia.doerg.render :as doerg-render])) + [net.deertopia.doerg.render :as doerg-render] + [net.deertopia.publisher.cached-file :as cached-file] + [babashka.fs :as fs] + [aero.core :as aero])) ;;; Routes