feat: tex rendering via temml
This commit is contained in:
@@ -7,5 +7,6 @@
|
||||
{:git/sha "531d629b7f05f37232261cf9e8927a4b5915714f"}
|
||||
hiccup/hiccup {:mvn/version "2.0.0-RC4"}
|
||||
com.rpl/specter {:mvn/version "1.1.6"}
|
||||
lambdaisland/deep-diff2 {:mvn/version "2.12.219"}}
|
||||
lambdaisland/deep-diff2 {:mvn/version "2.12.219"}
|
||||
mvxcvi/clj-cbor {:mvn/version "1.1.1"}}
|
||||
:paths ["src" "resources" "test"]}
|
||||
|
||||
1
doerg/doerg-tex/README.org
Normal file
1
doerg/doerg-tex/README.org
Normal file
@@ -0,0 +1 @@
|
||||
#+title: doerg-tex
|
||||
19
doerg/doerg-tex/default.nix
Normal file
19
doerg/doerg-tex/default.nix
Normal file
@@ -0,0 +1,19 @@
|
||||
{ buildNpmPackage
|
||||
, importNpmLock
|
||||
, makeWrapper
|
||||
, ibm-plex
|
||||
, callPackage
|
||||
, our-tex ? callPackage ./our-tex.nix {}
|
||||
}:
|
||||
|
||||
buildNpmPackage {
|
||||
pname = "doerg-tex";
|
||||
version = "0.1.0";
|
||||
src = ./.;
|
||||
npmDeps = importNpmLock { npmRoot = ./.; };
|
||||
npmConfigHook = importNpmLock.npmConfigHook;
|
||||
dontNpmBuild = true;
|
||||
buildInputs = [
|
||||
our-tex
|
||||
];
|
||||
}
|
||||
55
doerg/doerg-tex/index.js
Executable file
55
doerg/doerg-tex/index.js
Executable file
@@ -0,0 +1,55 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const commandLineArgs = require ("command-line-args")
|
||||
const temml = require ("temml")
|
||||
const fs = require ("node:fs")
|
||||
const path = require ("node:path")
|
||||
const { DecoderStream, EncoderStream } = require ("cbor-x")
|
||||
const { Transform } = require('node:stream')
|
||||
|
||||
const cli_spec =
|
||||
[ { name: "preamble" }
|
||||
]
|
||||
|
||||
function load_preambles (preamble) {
|
||||
const data = fs.readFileSync (preamble, "utf8") .toString ()
|
||||
return temml.definePreamble (data)
|
||||
}
|
||||
|
||||
let macros = {}
|
||||
|
||||
function is_render_command (cmd) {
|
||||
return cmd instanceof Array
|
||||
&& cmd.length === 1
|
||||
&& typeof cmd[0] === "string"
|
||||
}
|
||||
|
||||
function do_command (cmd) {
|
||||
try {
|
||||
if (typeof cmd === "string") {
|
||||
return temml.renderToString (cmd, {macros})
|
||||
} else if (is_render_command (cmd)) {
|
||||
return temml.renderToString (cmd[0], {displayMode: true,macros})
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
} catch (e) {
|
||||
return e
|
||||
}
|
||||
}
|
||||
|
||||
function main () {
|
||||
const options = commandLineArgs (cli_spec)
|
||||
console.error (options)
|
||||
macros = load_preambles (options.preamble)
|
||||
const decoder = new DecoderStream ()
|
||||
const encoder = new EncoderStream ()
|
||||
process.stdin.pipe (decoder)
|
||||
const command_responses = decoder.map (do_command)
|
||||
decoder
|
||||
.map (do_command)
|
||||
.pipe (encoder)
|
||||
.pipe (process.stdout)
|
||||
}
|
||||
|
||||
main ()
|
||||
43
doerg/doerg-tex/our-tex.nix
Normal file
43
doerg/doerg-tex/our-tex.nix
Normal file
@@ -0,0 +1,43 @@
|
||||
{ texlive
|
||||
, syd-plex-latex
|
||||
}:
|
||||
|
||||
texlive.combine {
|
||||
inherit syd-plex-latex;
|
||||
inherit (texlive)
|
||||
scheme-basic
|
||||
xkeyval
|
||||
changepage
|
||||
fancyhdr
|
||||
geometry
|
||||
natbib
|
||||
paralist
|
||||
placeins
|
||||
ragged2e
|
||||
setspace
|
||||
textcase
|
||||
titlesec
|
||||
xcolor
|
||||
hardwrap
|
||||
xifthen
|
||||
catchfile
|
||||
fontspec
|
||||
latexmk
|
||||
xetex
|
||||
dvisvgm dvipng wrapfig # For Org-mode previews/export.
|
||||
amsmath # Essential for mathematics.
|
||||
spath3 # TikZ dependency?
|
||||
ulem hyperref
|
||||
capt-of
|
||||
pgf # Includes TikZ.
|
||||
tikz-cd # Commutative diagrams w/ TikZ.
|
||||
quiver # Commutative diagrams w/ TikZ & q.uiver.app.
|
||||
bookmark
|
||||
metafont
|
||||
preview # For new-gen org-latex-preview.
|
||||
mylatexformat # For new-gen org-latex-preview.
|
||||
collection-fontsrecommended # Essential fonts.
|
||||
etoolbox # For Org-mode exports.
|
||||
caption
|
||||
;
|
||||
}
|
||||
227
doerg/doerg-tex/package-lock.json
generated
Normal file
227
doerg/doerg-tex/package-lock.json
generated
Normal file
@@ -0,0 +1,227 @@
|
||||
{
|
||||
"name": "doerg-tex",
|
||||
"version": "0.1.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "doerg-tex",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"cbor-x": "^1.6.0",
|
||||
"command-line-args": "^6.0.1",
|
||||
"temml": "^0.13.1"
|
||||
},
|
||||
"bin": {
|
||||
"doerg-tex": "index.js"
|
||||
}
|
||||
},
|
||||
"node_modules/@cbor-extract/cbor-extract-darwin-arm64": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-darwin-arm64/-/cbor-extract-darwin-arm64-2.2.0.tgz",
|
||||
"integrity": "sha512-P7swiOAdF7aSi0H+tHtHtr6zrpF3aAq/W9FXx5HektRvLTM2O89xCyXF3pk7pLc7QpaY7AoaE8UowVf9QBdh3w==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/@cbor-extract/cbor-extract-darwin-x64": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-darwin-x64/-/cbor-extract-darwin-x64-2.2.0.tgz",
|
||||
"integrity": "sha512-1liF6fgowph0JxBbYnAS7ZlqNYLf000Qnj4KjqPNW4GViKrEql2MgZnAsExhY9LSy8dnvA4C0qHEBgPrll0z0w==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/@cbor-extract/cbor-extract-linux-arm": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-linux-arm/-/cbor-extract-linux-arm-2.2.0.tgz",
|
||||
"integrity": "sha512-QeBcBXk964zOytiedMPQNZr7sg0TNavZeuUCD6ON4vEOU/25+pLhNN6EDIKJ9VLTKaZ7K7EaAriyYQ1NQ05s/Q==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@cbor-extract/cbor-extract-linux-arm64": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-linux-arm64/-/cbor-extract-linux-arm64-2.2.0.tgz",
|
||||
"integrity": "sha512-rQvhNmDuhjTVXSPFLolmQ47/ydGOFXtbR7+wgkSY0bdOxCFept1hvg59uiLPT2fVDuJFuEy16EImo5tE2x3RsQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@cbor-extract/cbor-extract-linux-x64": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-linux-x64/-/cbor-extract-linux-x64-2.2.0.tgz",
|
||||
"integrity": "sha512-cWLAWtT3kNLHSvP4RKDzSTX9o0wvQEEAj4SKvhWuOVZxiDAeQazr9A+PSiRILK1VYMLeDml89ohxCnUNQNQNCw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@cbor-extract/cbor-extract-win32-x64": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-win32-x64/-/cbor-extract-win32-x64-2.2.0.tgz",
|
||||
"integrity": "sha512-l2M+Z8DO2vbvADOBNLbbh9y5ST1RY5sqkWOg/58GkUPBYou/cuNZ68SGQ644f1CvZ8kcOxyZtw06+dxWHIoN/w==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/array-back": {
|
||||
"version": "6.2.2",
|
||||
"resolved": "https://registry.npmjs.org/array-back/-/array-back-6.2.2.tgz",
|
||||
"integrity": "sha512-gUAZ7HPyb4SJczXAMUXMGAvI976JoK3qEx9v1FTmeYuJj0IBiaKttG1ydtGKdkfqWkIkouke7nG8ufGy77+Cvw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12.17"
|
||||
}
|
||||
},
|
||||
"node_modules/cbor-extract": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/cbor-extract/-/cbor-extract-2.2.0.tgz",
|
||||
"integrity": "sha512-Ig1zM66BjLfTXpNgKpvBePq271BPOvu8MR0Jl080yG7Jsl+wAZunfrwiwA+9ruzm/WEdIV5QF/bjDZTqyAIVHA==",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"node-gyp-build-optional-packages": "5.1.1"
|
||||
},
|
||||
"bin": {
|
||||
"download-cbor-prebuilds": "bin/download-prebuilds.js"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@cbor-extract/cbor-extract-darwin-arm64": "2.2.0",
|
||||
"@cbor-extract/cbor-extract-darwin-x64": "2.2.0",
|
||||
"@cbor-extract/cbor-extract-linux-arm": "2.2.0",
|
||||
"@cbor-extract/cbor-extract-linux-arm64": "2.2.0",
|
||||
"@cbor-extract/cbor-extract-linux-x64": "2.2.0",
|
||||
"@cbor-extract/cbor-extract-win32-x64": "2.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/cbor-x": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/cbor-x/-/cbor-x-1.6.0.tgz",
|
||||
"integrity": "sha512-0kareyRwHSkL6ws5VXHEf8uY1liitysCVJjlmhaLG+IXLqhSaOO+t63coaso7yjwEzWZzLy8fJo06gZDVQM9Qg==",
|
||||
"license": "MIT",
|
||||
"optionalDependencies": {
|
||||
"cbor-extract": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/command-line-args": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-6.0.1.tgz",
|
||||
"integrity": "sha512-Jr3eByUjqyK0qd8W0SGFW1nZwqCaNCtbXjRo2cRJC1OYxWl3MZ5t1US3jq+cO4sPavqgw4l9BMGX0CBe+trepg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"array-back": "^6.2.2",
|
||||
"find-replace": "^5.0.2",
|
||||
"lodash.camelcase": "^4.3.0",
|
||||
"typical": "^7.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.20"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@75lb/nature": "latest"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@75lb/nature": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/detect-libc": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
|
||||
"integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
|
||||
"license": "Apache-2.0",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/find-replace": {
|
||||
"version": "5.0.2",
|
||||
"resolved": "https://registry.npmjs.org/find-replace/-/find-replace-5.0.2.tgz",
|
||||
"integrity": "sha512-Y45BAiE3mz2QsrN2fb5QEtO4qb44NcS7en/0y9PEVsg351HsLeVclP8QPMH79Le9sH3rs5RSwJu99W0WPZO43Q==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@75lb/nature": "latest"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@75lb/nature": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/lodash.camelcase": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
|
||||
"integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/node-gyp-build-optional-packages": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.1.1.tgz",
|
||||
"integrity": "sha512-+P72GAjVAbTxjjwUmwjVrqrdZROD4nf8KgpBoDxqXXTiYZZt/ud60dE5yvCSr9lRO8e8yv6kgJIC0K0PfZFVQw==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"detect-libc": "^2.0.1"
|
||||
},
|
||||
"bin": {
|
||||
"node-gyp-build-optional-packages": "bin.js",
|
||||
"node-gyp-build-optional-packages-optional": "optional.js",
|
||||
"node-gyp-build-optional-packages-test": "build-test.js"
|
||||
}
|
||||
},
|
||||
"node_modules/temml": {
|
||||
"version": "0.13.1",
|
||||
"resolved": "https://registry.npmjs.org/temml/-/temml-0.13.1.tgz",
|
||||
"integrity": "sha512-/fL1utq8QUD9YpcLeZHPRnp9Cbzbexq5hZl5uSBhf8mNYiKkcS4eYbLidDB+/nF8C+RHAcBQbKw2bKoS83mz1Q==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/typical": {
|
||||
"version": "7.3.0",
|
||||
"resolved": "https://registry.npmjs.org/typical/-/typical-7.3.0.tgz",
|
||||
"integrity": "sha512-ya4mg/30vm+DOWfBg4YK3j2WD6TWtRkCbasOJr40CseYENzCUby/7rIvXA99JGsQHeNxLbnXdyLLxKSv3tauFw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12.17"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
6
doerg/doerg-tex/package.json
Normal file
6
doerg/doerg-tex/package.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{"dependencies":{"temml":"^0.13.1"
|
||||
,"command-line-args":"^6.0.1"
|
||||
,"cbor-x":"^1.6.0"}
|
||||
,"name":"doerg-tex"
|
||||
,"version":"0.1.0"
|
||||
,"bin":{"doerg-tex":"index.js"}}
|
||||
16
doerg/doerg-tex/serialise.clj
Normal file
16
doerg/doerg-tex/serialise.clj
Normal file
@@ -0,0 +1,16 @@
|
||||
(ns serialise
|
||||
(:require [clj-cbor.core :as cbor]
|
||||
[clojure.string :as str]))
|
||||
|
||||
(defn w [x]
|
||||
(cbor/encode cbor/default-codec System/out x))
|
||||
|
||||
(defn c [x]
|
||||
(->> x cbor/encode (map #(format "%02x" %)) (str/join " ")))
|
||||
|
||||
(w "\\naturalto")
|
||||
|
||||
#_#_#_
|
||||
(w "c = \\sqrt{a^2 + y^2}")
|
||||
(w "c = \\sqrt{a^ + y^2")
|
||||
(w "\\alpha^\\beta")
|
||||
153
doerg/resources/net/deertopia/doerg/prelude.tex
Normal file
153
doerg/resources/net/deertopia/doerg/prelude.tex
Normal file
@@ -0,0 +1,153 @@
|
||||
% Of the highest importance:
|
||||
\renewcommand{\phi}{\varphi}
|
||||
\renewcommand{\epsilon}{\varepsilon}
|
||||
|
||||
% Saner abbreviations for font faces (take an argument rather than
|
||||
% applying to the current context).
|
||||
\renewcommand{\rm}[1]{\mathrm{#1}}
|
||||
\newcommand{\bb}[1]{\mathbb{#1}}
|
||||
\renewcommand{\bf}[1]{\mathbf{#1}}
|
||||
|
||||
% \cA … \cZ
|
||||
\newcommand{\cA}{\mathcal{A}}
|
||||
\newcommand{\cB}{\mathcal{B}}
|
||||
\newcommand{\cC}{\mathcal{C}}
|
||||
\newcommand{\cD}{\mathcal{D}}
|
||||
\newcommand{\cE}{\mathcal{E}}
|
||||
\newcommand{\cF}{\mathcal{F}}
|
||||
\newcommand{\cG}{\mathcal{G}}
|
||||
\newcommand{\cH}{\mathcal{H}}
|
||||
\newcommand{\cI}{\mathcal{I}}
|
||||
\newcommand{\cJ}{\mathcal{J}}
|
||||
\newcommand{\cK}{\mathcal{K}}
|
||||
\newcommand{\cL}{\mathcal{L}}
|
||||
\newcommand{\cM}{\mathcal{M}}
|
||||
\newcommand{\cN}{\mathcal{N}}
|
||||
\newcommand{\cO}{\mathcal{O}}
|
||||
\newcommand{\cP}{\mathcal{P}}
|
||||
\newcommand{\cQ}{\mathcal{Q}}
|
||||
\newcommand{\cR}{\mathcal{R}}
|
||||
\newcommand{\cS}{\mathcal{S}}
|
||||
\newcommand{\cT}{\mathcal{T}}
|
||||
\newcommand{\cU}{\mathcal{U}}
|
||||
\newcommand{\cV}{\mathcal{V}}
|
||||
\newcommand{\cW}{\mathcal{W}}
|
||||
\newcommand{\cX}{\mathcal{X}}
|
||||
\newcommand{\cY}{\mathcal{Y}}
|
||||
\newcommand{\cZ}{\mathcal{Z}}
|
||||
|
||||
% \bA … \bZ
|
||||
\newcommand{\bA}{\mathbb{A}}
|
||||
\newcommand{\bB}{\mathbb{B}}
|
||||
\newcommand{\bC}{\mathbb{C}}
|
||||
\newcommand{\bD}{\mathbb{D}}
|
||||
\newcommand{\bE}{\mathbb{E}}
|
||||
\newcommand{\bF}{\mathbb{F}}
|
||||
\newcommand{\bG}{\mathbb{G}}
|
||||
\newcommand{\bH}{\mathbb{H}}
|
||||
\newcommand{\bI}{\mathbb{I}}
|
||||
\newcommand{\bJ}{\mathbb{J}}
|
||||
\newcommand{\bK}{\mathbb{K}}
|
||||
\newcommand{\bL}{\mathbb{L}}
|
||||
\newcommand{\bM}{\mathbb{M}}
|
||||
\newcommand{\bN}{\mathbb{N}}
|
||||
\newcommand{\bO}{\mathbb{O}}
|
||||
\newcommand{\bP}{\mathbb{P}}
|
||||
\newcommand{\bQ}{\mathbb{Q}}
|
||||
\newcommand{\bR}{\mathbb{R}}
|
||||
\newcommand{\bS}{\mathbb{S}}
|
||||
\newcommand{\bT}{\mathbb{T}}
|
||||
\newcommand{\bU}{\mathbb{U}}
|
||||
\newcommand{\bV}{\mathbb{V}}
|
||||
\newcommand{\bW}{\mathbb{W}}
|
||||
\newcommand{\bX}{\mathbb{X}}
|
||||
\newcommand{\bY}{\mathbb{Y}}
|
||||
\newcommand{\bZ}{\mathbb{Z}}
|
||||
|
||||
% Notation for lambda abstractions and function application. $~$
|
||||
% is the spacing that should be used between arguments.
|
||||
\newcommand{\lam}[2]{\lambda #1.\ #2}
|
||||
|
||||
% Notation for paths, the interval, and its operations.
|
||||
\newcommand{\PathP}[3]{\rm{PathP}~ {#1}~ {#2}~ {#3}}
|
||||
\newcommand{\Path}[3]{\rm{Path}~ {#1}~ {#2}~ {#3}}
|
||||
\newcommand{\Square}[4]{\rm{Square}~ {#1}~ {#2}~ {#3}~ {#4}}
|
||||
\newcommand{\ap}[2]{\rm{ap}~ {#1}~ {#2}}
|
||||
|
||||
\newcommand{\subst}{\operatorname{subst}}
|
||||
\newcommand{\ua}{\operatorname{ua}}
|
||||
|
||||
\newcommand{\iZ}{\rm{i0}}
|
||||
\newcommand{\iO}{\rm{i1}}
|
||||
|
||||
\newcommand{\ineg}{\lnot}
|
||||
\newcommand{\imin}{\land}
|
||||
\newcommand{\imax}{\lor}
|
||||
|
||||
\newcommand{\transport}[2]{\rm{transport}~ #1~ #2}
|
||||
\newcommand{\transp}[3]{\rm{transp}~ #1~ #2~ #3}
|
||||
\newcommand{\Partial}[2]{\rm{Partial}~ #1~ #2}
|
||||
\newcommand{\dcomp}{\mathrel{\cdot\cdot}}
|
||||
\newcommand{\Extn}[2]{{#1}[#2]}
|
||||
|
||||
\newcommand{\thecat}[1]{\mathbf{#1}} % Names of "concrete" categories
|
||||
\newcommand{\ca}[1]{\mathcal{#1}} % Names of variable categories
|
||||
|
||||
%% \newcommand{\knowncat}[1]{\newcommand{\csname #1\endcsname}{\thecat{#1}}}
|
||||
%% \newcommand{\knownbicat}[1]{\newcommand{\csname #1\endcsname}{\thebicat{#1}}}
|
||||
|
||||
\newcommand{\ty}{\rm{Type}}
|
||||
%% \newcommand{\set}{\rm{Set}}
|
||||
\newcommand{\prop}{\rm{Prop}}
|
||||
|
||||
%% \DeclareMathOperator{\id}{id}
|
||||
%% \DeclareMathOperator{\Id}{Id}
|
||||
|
||||
%% \knowncat{Sets}
|
||||
%% \knowncat{Ab}
|
||||
%% \knowncat{Graphs}
|
||||
%% \knowncat{MarkedGraphs}
|
||||
%% \knowncat{Props}
|
||||
%% \knowncat{FinSets}
|
||||
%% \knowncat{Rings}
|
||||
%% \knowncat{Grp}
|
||||
%% \knowncat{Rel}
|
||||
%% \knowncat{Par}
|
||||
%% \knowncat{Pos}
|
||||
|
||||
\renewcommand{\Set}{\thecat{Set}}
|
||||
|
||||
% "Postfix" operators that have a subscript and are annoying to write
|
||||
% out:
|
||||
\newcommand{\inv}{^{-1}}
|
||||
\renewcommand{\op}{^{\rm{op}}}
|
||||
|
||||
\newcommand{\eps}{\varepsilon}
|
||||
|
||||
\newcommand{\B}[1]{\mathbf{B} #1}
|
||||
\newcommand{\point}[1]{\bullet_{#1}}
|
||||
\newcommand{\List}[1]{\operatorname{List}(#1)}
|
||||
|
||||
\renewcommand{\hom}{\mathbf{Hom}}
|
||||
|
||||
\newcommand{\refl}{\mathrm{refl}}
|
||||
|
||||
\DeclareMathOperator{\isiso}{is-iso}
|
||||
\DeclareMathOperator{\isequiv}{is-equiv}
|
||||
|
||||
% Relations
|
||||
\newcommand{\pathto}{\equiv}
|
||||
\newcommand{\is}{\pathto}
|
||||
\newcommand{\definedto}{≔}
|
||||
\newcommand{\equivto}{\simeq}
|
||||
\newcommand{\homotopicto}{\sim}
|
||||
\newcommand{\naturalto}{\Rightarrow}
|
||||
\newcommand{\isoto}{\cong}
|
||||
\newcommand{\monicto}{\rightarrowtail}
|
||||
\newcommand{\epicto}{\twoheadrightarrow}
|
||||
|
||||
% Category names
|
||||
\newcommand{\C}[1]{\mathbf{#1}}
|
||||
|
||||
\newcommand{\homset}[3]{{{#1} \left[ {#2} \to {#3} \right]}}
|
||||
\newcommand{\horizontalcompose}{\ast}
|
||||
@@ -105,8 +105,8 @@ p,
|
||||
dl,
|
||||
ol,
|
||||
ul {
|
||||
font-size: 1.4rem;
|
||||
line-height: 2rem;
|
||||
font-size: 1.2rem;
|
||||
line-height: 1.5rem;
|
||||
}
|
||||
|
||||
p {
|
||||
|
||||
18
doerg/src/net/deertopia/doerg/common.clj
Normal file
18
doerg/src/net/deertopia/doerg/common.clj
Normal file
@@ -0,0 +1,18 @@
|
||||
(ns net.deertopia.doerg.common
|
||||
(:require [babashka.process :as p]
|
||||
[clojure.string :as str]))
|
||||
|
||||
(defn deref-with-timeout [process ms]
|
||||
(let [p (promise)
|
||||
process-future (future (deliver p @process))
|
||||
timeout-future (future (Thread/sleep ms)
|
||||
(future-cancel process-future)
|
||||
(p/destroy-tree process)
|
||||
(deliver p ::timed-out))]
|
||||
(if (= @p ::timed-out)
|
||||
(throw (ex-info (format "external command `%s' timed out after %.2fs."
|
||||
(str/join " " (:cmd process))
|
||||
(/ (double ms) 1000))
|
||||
{:process process
|
||||
:timed-out-after-milliseconds ms}))
|
||||
@p)))
|
||||
@@ -1,5 +1,6 @@
|
||||
(ns net.deertopia.doerg.element
|
||||
(:require [babashka.process :as p]
|
||||
[net.deertopia.doerg.common :as common]
|
||||
[clojure.string :as str]
|
||||
[clojure.zip]
|
||||
[babashka.fs :as fs]
|
||||
@@ -16,24 +17,11 @@
|
||||
|
||||
(defonce ^:private uniorg-script-path-atom (atom nil))
|
||||
|
||||
(def ^:dynamic *uniorg-timeout-after-milliseconds*
|
||||
(def ^:dynamic *uniorg-timeout-duration*
|
||||
"Number of milliseconds to wait before killing the external Uniorg
|
||||
process."
|
||||
(* 10 1000))
|
||||
|
||||
(defn deref-with-timeout [process ms]
|
||||
(let [p (promise)
|
||||
process-future (future (deliver p @process))
|
||||
timeout-future (future (Thread/sleep ms)
|
||||
(future-cancel process-future)
|
||||
(p/destroy-tree process)
|
||||
(deliver p ::timed-out))]
|
||||
(if (= @p ::timed-out)
|
||||
(throw (ex-info (format "external command `%s' timed out after %.2fs."
|
||||
(str/join " " (:cmd process))
|
||||
(/ (double ms) 1000))
|
||||
{:process process
|
||||
:timed-out-after-milliseconds ms}))
|
||||
@p)))
|
||||
|
||||
(defn- camel->kebab [s]
|
||||
(->> (str/split s #"(?<=[a-z])(?=[A-Z])")
|
||||
(map str/lower-case)
|
||||
@@ -44,7 +32,7 @@
|
||||
(let [r (-> (p/process
|
||||
{:in in :out :string}
|
||||
"doerg-parser")
|
||||
(deref-with-timeout *uniorg-timeout-after-milliseconds*))]
|
||||
(common/deref-with-timeout *uniorg-timeout-duration*))]
|
||||
(if (zero? (:exit r))
|
||||
(-> r :out (json/parse-string (comp keyword camel->kebab))))))
|
||||
|
||||
|
||||
@@ -7,7 +7,9 @@
|
||||
[clojure.tools.logging.readable :as lr]
|
||||
[com.rpl.specter :as sp]
|
||||
[net.deertopia.doerg.html :as doerg-html]
|
||||
[hiccup2.core :as hiccup]
|
||||
[clojure.pprint]
|
||||
[net.deertopia.doerg.tex :as tex]
|
||||
[clojure.zip :as z]))
|
||||
|
||||
;;; Top-level API
|
||||
@@ -43,15 +45,16 @@
|
||||
(defn org-element-recursive
|
||||
"Recursively render an Org-mode element to Hiccup."
|
||||
[e]
|
||||
(->> e
|
||||
;; gather-footnotes
|
||||
(sp/transform
|
||||
(tex/binding-tex-worker
|
||||
(->> e
|
||||
;; gather-footnotes
|
||||
(sp/transform
|
||||
[element/postorder-walker view-children-as-seq]
|
||||
(fn [node]
|
||||
(try (org-element node)
|
||||
(catch Throwable e
|
||||
(lr/error e "Error in renderer" {:node node})
|
||||
(render-renderer-error e)))))))
|
||||
(render-renderer-error e))))))))
|
||||
|
||||
(defn org-document
|
||||
"Recursively render an Org-mode document to Hiccup."
|
||||
@@ -276,11 +279,16 @@
|
||||
(defmethod org-element "citation-reference" [{:keys [key]}]
|
||||
(str "@" key))
|
||||
|
||||
(defmethod org-element "latex-fragment" [{:keys [value]}]
|
||||
[:span.latex-fragment value])
|
||||
(defmethod org-element "latex-fragment" [{:keys [contents value] :as e}]
|
||||
(let [display? (str/starts-with? value "\\[")]
|
||||
#_
|
||||
(render-pprint (assoc e :display? display?))
|
||||
[:span.latex-fragment
|
||||
(hiccup/raw (tex/render contents :display? display?))]))
|
||||
|
||||
(defmethod org-element "latex-environment" [{:keys [value]}]
|
||||
[:pre [:code value]])
|
||||
[:span.latex-fragment
|
||||
(hiccup/raw (tex/render value :display? true))])
|
||||
|
||||
(defmethod org-element "example-block" [{:keys [value]}]
|
||||
[:pre value])
|
||||
|
||||
49
doerg/src/net/deertopia/doerg/tex.clj
Normal file
49
doerg/src/net/deertopia/doerg/tex.clj
Normal file
@@ -0,0 +1,49 @@
|
||||
(ns net.deertopia.doerg.tex
|
||||
(:require [babashka.process :as p]
|
||||
[net.deertopia.doerg.common :as common]
|
||||
[clj-cbor.core :as cbor]
|
||||
[clojure.java.io :as io]))
|
||||
|
||||
(def ^:dynamic *tex-worker-timeout-duration*
|
||||
"Number of milliseconds to wait before killing the external Uniorg
|
||||
process."
|
||||
(* 10 1000))
|
||||
|
||||
(def ^:dynamic *worker*)
|
||||
|
||||
(defn tex-worker [& {:keys [preamble]}]
|
||||
(p/process
|
||||
{:shutdown p/destroy-tree
|
||||
:err :inherit}
|
||||
#_"doerg-tex"
|
||||
"./doerg-tex/index.js"
|
||||
"--preamble"
|
||||
"resources/net/deertopia/doerg/prelude.tex"))
|
||||
|
||||
(defn finish [tw]
|
||||
(.close (:in tw)))
|
||||
|
||||
(defmacro with-tex-worker [tw & body]
|
||||
`(let [~tw (tex-worker)]
|
||||
(try
|
||||
(do ~@body)
|
||||
(finally
|
||||
(finish ~tw)
|
||||
(p/destroy-tree ~tw)))))
|
||||
|
||||
(defmacro binding-tex-worker [& body]
|
||||
`(binding [*worker* (tex-worker)]
|
||||
(try
|
||||
~@body
|
||||
(finally
|
||||
(finish *worker*)))))
|
||||
|
||||
(defn command [x]
|
||||
(cbor/encode cbor/default-codec (:in *worker*) x)
|
||||
(.flush (:in *worker*))
|
||||
(cbor/decode cbor/default-codec (:out *worker*)))
|
||||
|
||||
(defn render [s & {:keys [display?]}]
|
||||
(if display?
|
||||
(command [s])
|
||||
(command s)))
|
||||
32
doerg/test/net/deertopia/doerg/common_test.clj
Normal file
32
doerg/test/net/deertopia/doerg/common_test.clj
Normal file
@@ -0,0 +1,32 @@
|
||||
(ns net.deertopia.doerg.common-test
|
||||
(:require [net.deertopia.doerg.common :as sut]
|
||||
[babashka.process :as p]
|
||||
[clojure.test :as t]))
|
||||
|
||||
(defn sleep-vs-timeout [& {:keys [sleep timeout]}]
|
||||
(sut/deref-with-timeout
|
||||
(p/process "sleep" (format "%ds" sleep))
|
||||
(* timeout 1000)))
|
||||
|
||||
;; Ideally we would test the following property:
|
||||
;;
|
||||
;; For natural numbers n and m, evaluating the form
|
||||
;; (sut/deref-with-timeout
|
||||
;; (p/process "sleep" (format "%ds" n))
|
||||
;; (* m 1000))
|
||||
;; will throw an exception iff n < m (probably with some margin of
|
||||
;; error lol).
|
||||
;;
|
||||
;; But, this is not something that we want to run dozens-to-hundreds
|
||||
;; of times. }:p
|
||||
|
||||
(t/deftest long-sleep-vs-short-timeout
|
||||
(t/testing "long sleep vs. short timeout"
|
||||
(t/is (thrown-with-msg?
|
||||
Exception #".*timed out.*"
|
||||
(sleep-vs-timeout :sleep 5 :timeout 1)))))
|
||||
|
||||
(t/deftest short-sleep-vs-long-timeout
|
||||
(t/testing "short sleep vs. long timeout"
|
||||
(t/is (instance? babashka.process.Process
|
||||
(sleep-vs-timeout :sleep 1 :timeout 5)))))
|
||||
@@ -6,34 +6,6 @@
|
||||
[clojure.java.io :as io]
|
||||
[com.rpl.specter :as sp]))
|
||||
|
||||
(defn sleep-vs-timeout [& {:keys [sleep timeout]}]
|
||||
(sut/deref-with-timeout
|
||||
(p/process "sleep" (format "%ds" sleep))
|
||||
(* timeout 1000)))
|
||||
|
||||
;; Ideally we would test the following property:
|
||||
;;
|
||||
;; For natural numbers n and m, evaluating the form
|
||||
;; (sut/deref-with-timeout
|
||||
;; (p/process "sleep" (format "%ds" n))
|
||||
;; (* m 1000))
|
||||
;; will throw an exception iff n < m (probably with some margin of
|
||||
;; error lol).
|
||||
;;
|
||||
;; But, this is not something that we want to run dozens-to-hundreds
|
||||
;; of times. }:p
|
||||
|
||||
(t/deftest long-sleep-vs-short-timeout
|
||||
(t/testing "long sleep vs. short timeout"
|
||||
(t/is (thrown-with-msg?
|
||||
Exception #".*timed out.*"
|
||||
(sleep-vs-timeout :sleep 5 :timeout 1)))))
|
||||
|
||||
(t/deftest short-sleep-vs-long-timeout
|
||||
(t/testing "short sleep vs. long timeout"
|
||||
(t/is (instance? babashka.process.Process
|
||||
(sleep-vs-timeout :sleep 1 :timeout 5)))))
|
||||
|
||||
(defn- first-child-of-type [parent type]
|
||||
(some #(and (sut/of-type? % type) %) (:children parent)))
|
||||
|
||||
|
||||
37
flake.lock
generated
37
flake.lock
generated
@@ -143,11 +143,46 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_3": {
|
||||
"locked": {
|
||||
"lastModified": 1750386251,
|
||||
"narHash": "sha256-1ovgdmuDYVo5OUC5NzdF+V4zx2uT8RtsgZahxidBTyw=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "076e8c6678d8c54204abcb4b1b14c366835a58bb",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixpkgs-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"clj-nix": "clj-nix",
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": "nixpkgs_2"
|
||||
"nixpkgs": "nixpkgs_2",
|
||||
"sydpkgs": "sydpkgs"
|
||||
}
|
||||
},
|
||||
"sydpkgs": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs_3"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1767975357,
|
||||
"narHash": "sha256-MDVh3/aVhkD1bh/r8c0gs9DL4e78CrUbUxOZHWlCwLM=",
|
||||
"owner": "msyds",
|
||||
"repo": "sydpkgs",
|
||||
"rev": "233479ab277d47b1dbda202eafca50e61c659151",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "msyds",
|
||||
"repo": "sydpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
|
||||
15
flake.nix
15
flake.nix
@@ -3,7 +3,7 @@
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
flake-utils.url = "github:numtide/flake-utils";
|
||||
clj-nix.url = "github:jlesquembre/clj-nix";
|
||||
# clj-nix.url = "path:///home/msyds/git/clj-nix";
|
||||
sydpkgs.url = "github:msyds/sydpkgs";
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs, clj-nix, ... }@inputs:
|
||||
@@ -19,6 +19,7 @@
|
||||
pkgs = import nixpkgs {
|
||||
inherit system;
|
||||
overlays = [
|
||||
inputs.sydpkgs.overlays.default
|
||||
clj-nix.overlays.default
|
||||
self.overlays.default
|
||||
];
|
||||
@@ -31,7 +32,7 @@
|
||||
_pkgs = each-system ({ pkgs, ... }: pkgs);
|
||||
|
||||
packages = each-system ({ pkgs, ... }: {
|
||||
inherit (pkgs) publisher doerg doerg-parser;
|
||||
inherit (pkgs) publisher doerg doerg-parser doerg-tex;
|
||||
default = pkgs.publisher;
|
||||
});
|
||||
|
||||
@@ -42,7 +43,8 @@
|
||||
inherit (vendored) ibm-plex-web;
|
||||
publisher = final.callPackage ./publisher/package.nix {};
|
||||
doerg = final.callPackage ./doerg/package.nix {};
|
||||
doerg-parser = final.callPackage ./doerg/doerg-parser/package.nix {};
|
||||
doerg-parser = final.callPackage ./doerg/doerg-parser {};
|
||||
doerg-tex = final.callPackage ./doerg/doerg-tex {};
|
||||
};
|
||||
|
||||
checks = each-system ({ pkgs, system, ... }: {
|
||||
@@ -54,10 +56,15 @@
|
||||
|
||||
devShells = each-system ({ pkgs, system, ... }: {
|
||||
default = pkgs.mkShell {
|
||||
inputsFrom = [ pkgs.doerg ];
|
||||
inputsFrom = [
|
||||
pkgs.doerg
|
||||
pkgs.doerg-parser
|
||||
pkgs.doerg-tex
|
||||
];
|
||||
packages = with pkgs; [
|
||||
clojure-lsp
|
||||
doerg-parser
|
||||
doerg-tex
|
||||
# wahhh ibm-plex-web is a dependency of doerg... why must
|
||||
# i specify it hereeee.
|
||||
# ibm-plex-web
|
||||
|
||||
Reference in New Issue
Block a user