mirror of
https://git.freetards.xyz/array.in.a.matrix/TexLiLy.git
synced 2025-04-02 13:21:42 -04:00
[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>
This commit is contained in:
parent
3ebc41fddb
commit
4d4aa7d5ab
5 changed files with 89 additions and 7 deletions
22
callbacks.py
22
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)
|
||||
|
|
3
latex.py
3
latex.py
|
@ -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())
|
||||
|
||||
|
|
11
lilypond.py
11
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"
|
||||
|
|
53
parser.py
Normal file
53
parser.py
Normal file
|
@ -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…
Add table
Reference in a new issue