[ADD] Allow more complex expressions in code tags.

Now you can put long LilyPond stuff! And text-mode LaTeX!

Signed-off-by: LoaD Accumulator <lda@freetards.xyz>
dev
LoaD Accumulator 12 months ago
parent 3ebc41fddb
commit 4d4aa7d5ab
Signed by: lda
GPG Key ID: 6898757653ABE3E6

@ -31,12 +31,34 @@ async def msg_cb(room: MatrixRoom, event: RoomMessageText) -> None:
args = shlex.split(event.body[4:])
if len(args) >= 1:
await tex_router.handle_command(args[0], room.room_id, event, args[1:])
return
if event.body.startswith("lily!"):
import router
args = shlex.split(event.body[5:])
if len(args) >= 1:
await lily_router.handle_command(args[0], room.room_id, event, args[1:])
return
if event.formatted_body is not None:
import lilypond
import parser
code = parser.CodeParser()
code.feed(event.formatted_body)
code.close()
for block in code.blocks:
content = block['content']
if block['lang'] == 'tex':
filename = latex.render(event.sender, content)
await utils.send_png(room.room_id, filename)
if block['lang'] == 'ly':
filename = lilypond.render(event.sender, content, template=False)
await utils.send_png(room.room_id, filename)
for tex in re.findall(latex_regex, event.body, re.M):
try:
filename = latex.render(event.sender, tex)

@ -20,7 +20,7 @@ def render(user: str, source: str, png: bool = True) -> str:
import subprocess
import utils
import os
# Put the user's packages in the format too.
directory = utils.create_user_dir(user)
pkgs = ""
@ -38,7 +38,8 @@ def render(user: str, source: str, png: bool = True) -> str:
# Parse our templated file thru' LaTeX and dvipng.
# TODO: Allow arbitrary DPI and foreground color.
ret = subprocess.run(["latex", "-halt-on-error", tmp.name], cwd="/tmp", capture_output=True)
ret = subprocess.run(["latex", "-halt-on-error", tmp.name],
cwd="/tmp", capture_output=True)
if ret.returncode != 0:
raise FileNotFoundError(ret.stdout.decode())

@ -5,23 +5,26 @@ template = r"""
{content}
"""
def render(user: str, source: str, png: bool = True) -> str:
def render(user: str, source: str, png: bool = True, template: bool = False) -> str:
import tempfile
import subprocess
import utils
import os
fmt = template.format(content=source)
fmt = template.format(content=source) if template else source
tmp = tempfile.NamedTemporaryFile(delete=False)
tmp.write(bytes(fmt, encoding="utf8"))
tmp.close()
if png:
ret = subprocess.run(["lilypond", "-d", "preview", "--png", "-dresolution=500", tmp.name], cwd="/tmp", capture_output=True)
ret = subprocess.run(["lilypond", "-d", "preview", "--png",
"-dresolution=500", tmp.name], cwd="/tmp", capture_output=True)
if ret.returncode != 0:
raise FileNotFoundError(ret.stderr.decode())
return tmp.name + ".preview.png"
subprocess.run(["lilypond", "-d", "preview", "--svg", tmp.name], cwd="/tmp")
subprocess.run(["lilypond", "-d", "preview",
"--svg", tmp.name], cwd="/tmp")
return tmp.name + "preview.svg"

@ -0,0 +1,53 @@
from html.parser import HTMLParser
STATE_NONE = 0
STATE_PRE = 1
STATE_CODE = 2
class CodeParser(HTMLParser):
def __init__(self, **kwargs):
super().__init__()
# This shall be a list of dictionnaries, which
# look like this:
# [
# {'lang': 'ly', 'content': '...'},
# {'lang': 'ly', 'content': '...'},
# {'lang': 'tex', 'content': '...'},
# ...
# ]
self.blocks = []
# Yes, this thing acts kinda like a state machine.
self.state = STATE_NONE
self.language = ''
self.data = ''
def handle_starttag(self, tag, attrs):
if self.state == STATE_NONE and tag == "pre":
self.state = STATE_PRE
elif self.state == STATE_PRE and tag == "code":
self.state = STATE_CODE
for val in attrs:
v = val[1]
if val[0] == "class":
if v == "language-lilypond":
self.language = 'ly'
if v == "language-tex" or v == "language-latex":
self.language = 'tex'
def handle_endtag(self, tag):
if self.state == STATE_CODE and tag == "pre":
self.blocks.append({'lang': self.language, 'content': self.data})
self.state = STATE_NONE
self.data = ''
self.language = ''
def handle_data(self, data):
if self.state == STATE_CODE:
self.data += data

@ -45,3 +45,6 @@ async def route_lshow(router: Router, client: Client, room: str, event: RoomMess
"formatted_body": f"Couldn't parse LilyPond correctly.<br><code><pre>{e.args[0]}</pre></code>",
}
await client.room_send(room, message_type="m.room.message", content=content)
except Exception:
# ???
pass

Loading…
Cancel
Save