diff --git a/callbacks.py b/callbacks.py
index b96b24c..05cc87b 100644
--- a/callbacks.py
+++ b/callbacks.py
@@ -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)
diff --git a/latex.py b/latex.py
index 7abac90..713bdd8 100644
--- a/latex.py
+++ b/latex.py
@@ -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())
diff --git a/lilypond.py b/lilypond.py
index b1652d0..8d08bb4 100644
--- a/lilypond.py
+++ b/lilypond.py
@@ -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"
diff --git a/parser.py b/parser.py
new file mode 100644
index 0000000..2d08f84
--- /dev/null
+++ b/parser.py
@@ -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
+
+
diff --git a/routes.py b/routes.py
index 02594c0..3c351ad 100644
--- a/routes.py
+++ b/routes.py
@@ -45,3 +45,6 @@ async def route_lshow(router: Router, client: Client, room: str, event: RoomMess
"formatted_body": f"Couldn't parse LilyPond correctly.
{e.args[0]}
",
}
await client.room_send(room, message_type="m.room.message", content=content)
+ except Exception:
+ # ???
+ pass