83 lines
2.3 KiB
Clojure
83 lines
2.3 KiB
Clojure
(ns net.deertopia.doerg.tex.temml
|
|
(:require [babashka.process :as p]
|
|
[net.deertopia.doerg.common :as common]
|
|
[net.deertopia.doerg.config :as cfg]
|
|
[clj-cbor.core :as cbor]
|
|
[clojure.java.io :as io]
|
|
[clojure.string :as str]
|
|
[clojure.tools.logging :as l]
|
|
[babashka.fs :as fs]
|
|
[net.deertopia.doerg :as-alias doerg])
|
|
(:import (java.io ByteArrayOutputStream)))
|
|
|
|
(def ^:dynamic *worker-timeout-duration*
|
|
"Number of milliseconds to wait before killing the external Uniorg
|
|
process."
|
|
(* 10 1000))
|
|
|
|
(def ^:dynamic *worker*)
|
|
|
|
(def ^:private prelude-file
|
|
(fs/create-temp-file {:prefix "doerg-prelude-"
|
|
:suffix ".tex"}))
|
|
|
|
(defn worker []
|
|
(let [doerg-temml-worker (-> cfg/*cfg* ::doerg/doerg-temml-worker)]
|
|
(when-not (fs/exists? prelude-file)
|
|
(-> "net/deertopia/doerg/prelude.tex"
|
|
io/resource
|
|
io/input-stream
|
|
(io/copy prelude-file)))
|
|
(p/process
|
|
{:shutdown p/destroy-tree
|
|
:err (l/log-stream :info "temml/err")}
|
|
doerg-temml-worker
|
|
"--preamble" prelude-file)))
|
|
|
|
(defn close-worker [tw]
|
|
(.close (:in tw)))
|
|
|
|
(defmacro with-worker [tw & body]
|
|
`(let [~tw (worker)]
|
|
(try
|
|
(do ~@body)
|
|
(finally
|
|
(close-worker ~tw)
|
|
(p/destroy-tree ~tw)))))
|
|
|
|
(defmacro binding-worker [& body]
|
|
`(binding [*worker* (worker)]
|
|
(try
|
|
~@body
|
|
(finally
|
|
(close-worker *worker*)))))
|
|
|
|
(defn command-worker [x]
|
|
(cbor/encode cbor/default-codec (:in *worker*) x)
|
|
(.flush (:in *worker*))
|
|
(cbor/decode cbor/default-codec (:out *worker*)))
|
|
|
|
(defn render-inline [s]
|
|
(command-worker s))
|
|
|
|
(defn render-display [s]
|
|
(command-worker [s]))
|
|
|
|
(defn render [s]
|
|
(let [s (str/trim s)]
|
|
(if-let [[_ inner] (re-matches #"(?s)\\\[(.*)\\]" s)]
|
|
(render-display inner)
|
|
(if (re-matches #"(?s)\\begin\{.+?}(.*?)\\end\{.+?}" s)
|
|
(render-display s)
|
|
(if-let [[_ inner] (re-matches #"(?s)\\\((.*)\\\)" s)]
|
|
(render-inline inner)
|
|
(throw (IllegalArgumentException.
|
|
(ex-info
|
|
(str "`net.deertopia.doerg.tex.temml` argument should"
|
|
" be enclosed in math delimiters.")
|
|
{:arg s}))))))))
|
|
|
|
;; hackky....
|
|
(defn erroneous-output? [s]
|
|
(re-find #"(#b22222|temml-error)" s))
|