Compare commits

...

6 Commits

Author SHA1 Message Date
Folkert Kevelam
ba456a9b8b Add tikz pipeline 2025-09-12 17:21:54 +02:00
Folkert Kevelam
ed3f218dfb add buffer change event callback 2025-09-12 17:21:05 +02:00
Folkert Kevelam
c495c3384c Add Intersect predicate 2025-09-12 17:19:21 +02:00
Folkert Kevelam
c6df4d3b6a Add table styling 2025-09-12 17:18:44 +02:00
Folkert Kevelam
4bee54740b Add tikz and circuitikz to pipeline 2025-09-12 17:18:13 +02:00
Folkert Kevelam
7deef247f0 Add Roadmap 2025-09-12 17:17:11 +02:00
7 changed files with 191 additions and 19 deletions

View File

@ -5,6 +5,8 @@
1. Add circuitikz pipeline
2. Add notes link, and follow command
3. Change `render_pipeline` to use async
4. Modularize pythonn server
5. Formalize API of lua plugin
6. Formalize API of python server
4. Add sagemath pipeline
5. Add ngspice pipeline
6. Modularize pythonn server
7. Formalize API of lua plugin
8. Formalize API of python server

View File

@ -21,6 +21,7 @@ from .pandoc import Pandoc, Div, Span, Header, Attr, Plain, PString, Inline, Ima
from .admonition import blockquote_filter, create_warning, create_information, Theorem, Proof
from .penrose import Penrose
from .tikz import Tikz, Circuitikz
from .image import ImageFilter
def parse_title(content):
@ -236,6 +237,12 @@ async def main(base_path):
codeblock.AddCallback("penrose", pen)
t = Tikz(base_path)
c = Circuitikz(base_path)
codeblock.AddCallback("tikz", t)
codeblock.AddCallback("circuitikz", c)
pipeline.AddCallback('BlockQuote', blockquote, replace=True)
pipeline.AddCallback('CodeBlock', codeblock, replace=True)

View File

@ -0,0 +1,114 @@
from .render_pipeline import CallbackClass
from .pandoc import Attr, Image, Plain
import hashlib
import subprocess
import tempfile
import os
import re
from pathlib import Path
class Tikz(CallbackClass):
def __init__(self, base_path):
self.data_path = base_path + "/data/tikz/"
self.script_path = base_path + "/scripts/tex/tex2svg.sh"
self.image_cache = dict()
def run(self, output_dir, input_dir, name):
return subprocess.run(
[self.script_path, output_dir, input_dir, name],
text=True,
capture_output=True)
def __call__(self, content):
hashinput = re.sub(r"\s+", "", content['c'][1], flags=re.UNICODE).encode("utf-8")
hash = hashlib.md5()
hash.update(hashinput)
digest = hash.hexdigest()
if digest in self.image_cache:
return self.image_cache[digest]
preamble = """\\documentclass[class=minimal,crop=true,out=\\jobname.svg]{standalone}
\\usepackage{tikz}
\\begin{document}
\\begin{tikzpicture}[scale=2]"""
postamble = """\\end{tikzpicture}
\\end{document}"""
handle, file_path = tempfile.mkstemp(suffix=".tex", text=True)
text = content['c'][1]
with os.fdopen(handle, 'w') as f:
f.write(preamble)
f.write("\n")
f.write(text)
f.write("\n")
f.write(postamble)
stem = Path(file_path).stem
data = self.run("/tmp", "/tmp", stem)
img_attr = Attr("")
new_content = Image(img_attr, [{'t' : 'Str', 'c' : 'Tikz'}], "/generated/{}.svg".format(stem)).toJson()
wrapper = Plain(new_content).toJson()
self.image_cache[digest] = wrapper
return wrapper
class Circuitikz(CallbackClass):
def __init__(self, base_path):
self.data_path = base_path + "/data/tikz/"
self.script_path = base_path + "/scripts/tex/tex2svg.sh"
self.image_cache = dict()
def run(self, output_dir, input_dir, name):
return subprocess.run(
[self.script_path, output_dir, input_dir, name],
text=True,
capture_output=True)
def __call__(self, content):
hashinput = re.sub(r"\s+", "", content['c'][1], flags=re.UNICODE).encode("utf-8")
hash = hashlib.md5()
hash.update(hashinput)
digest = hash.hexdigest()
if digest in self.image_cache:
return self.image_cache[digest]
preamble = """\\documentclass[class=minimal,crop=true,out=\\jobname.svg]{standalone}
\\usepackage{circuitikz}
\\begin{document}
\\begin{circuitikz}[scale=2, transform shape, line width=1pt]"""
postamble = """\\end{circuitikz}
\\end{document}"""
handle, file_path = tempfile.mkstemp(suffix=".tex", text=True)
text = content['c'][1]
with os.fdopen(handle, 'w') as f:
f.write(preamble)
f.write("\n")
f.write(text)
f.write("\n")
f.write(postamble)
stem = Path(file_path).stem
data = self.run("/tmp", "/tmp", stem)
img_attr = Attr("")
new_content = Image(img_attr, [{'t' : 'Str', 'c' : 'Circuitikz'}], "/generated/{}.svg".format(stem)).toJson()
wrapper = Plain(new_content).toJson()
self.image_cache[digest] = wrapper
return wrapper

View File

@ -312,3 +312,9 @@ th {
background-color: var(--caribbean-current);
color: white;
}
img {
max-width: 100%;
margin: auto;
display: block;
}

View File

@ -1,4 +1,5 @@
type Set
predicate SubSet(Set s1, Set s2)
predicate Disjoint(Set s1, Set s2)
symmetric predicate Disjoint(Set s1, Set s2)
symmetric predicate Intersect(Set s1, Set s2)

View File

@ -21,6 +21,14 @@ where SubSet(x, y) {
layer x.icon above y.icon
}
forall Set x; Set y
where Intersect(x,y) {
ensure disjoint(x.text, y.icon, 5.0)
ensure disjoint(y.text, x.icon, 5.0)
ensure overlapping(x.icon, y.icon, 5.0)
layer x.icon above y.icon
}
forall Set x; Set y
where Disjoint(x, y) {
ensure disjoint(x.icon, y.icon)

View File

@ -20,23 +20,12 @@ function module.setup()
server_connection = client.setup()
end
function module.open()
augroup = nvim_create_augroup("MarkdownPreviewActiveAugroup", {clear = true})
server_connection:init(function()
augroup = nvim_del_augroup_by_id(augroup)
end)
local bufnr = vim.api.nvim_get_current_buf()
server_connection:base(vim.fn.fnamemodify(vim.uri_to_fname(vim.uri_from_bufnr(bufnr)), 'p:h'))
server_connection:show(get_buf_content(bufnr))
server_connection:scroll(vim.fn.line('.'))
local function SetAutoCmd(augroup, server, bufnr)
nvim_create_autocmd("BufWritePost", {
group = augroup,
buffer = bufnr,
callback = function()
server_connection:show(get_buf_content(bufnr))
server:show(get_buf_content(bufnr))
end,
})
@ -44,12 +33,12 @@ function module.open()
group = augroup,
buffer = bufnr,
callback = function()
server_connection:scroll({vim.fn.line('.'), vim.fn.line('$')})
server:scroll({vim.fn.line('.'), vim.fn.line('$')})
end,
})
local function show()
server_connection:show(get_buf_content(bufnr))
server:show(get_buf_content(bufnr))
end
nvim_create_autocmd({"TextChanged", "TextChangedI", "TextChangedP" }, {
@ -59,7 +48,52 @@ function module.open()
throttle.run_fn(show)
end,
})
end
local function FirstSend(server, bufnr)
print("Sending data to server from buffer " .. bufnr)
server:base(vim.fn.fnamemodify(vim.uri_to_fname(vim.uri_from_bufnr(bufnr)), 'p:h'))
server:show(get_buf_content(bufnr))
server:scroll(vim.fn.line('.'))
end
function module.open()
augroup = nvim_create_augroup("MarkdownPreviewActiveAugroup", {clear = true})
chgbuffergroup = nvim_create_augroup("MarkdownChangeBufferActiveAugroup", {clear = true})
server_connection:init(function()
if augroup then
augroup = nvim_del_augroup_by_id(augroup)
end
if chgbuffergroup then
chgbuffergroup = nvim_del_augroup_by_id(chgbuffergroup)
end
end)
local bufnr = vim.api.nvim_get_current_buf()
FirstSend(server_connection, bufnr)
SetAutoCmd(augroup, server_connection, bufnr)
nvim_create_autocmd("BufEnter", {
group = chgbuffergroup,
callback = function()
local new_buf_nr = vim.api.nvim_get_current_buf()
local ft = vim.api.nvim_buf_get_option(new_buf_nr, "filetype")
if ft == "markdown" then
print("filetype new buffer: " .. ft)
FirstSend(server_connection, new_buf_nr)
if augroup then
augroup = nvim_del_augroup_by_id(augroup)
end
augroup = nvim_create_augroup("MarkdownPreviewActiveAugroup", {clear = True})
SetAutoCmd(augroup, server_connection, new_buf_nr)
else
print("Not a markdown buffer")
augroup = nvim_del_augroup_by_id(augroup)
end
end,
})
end
function module.close()