From 60278db59e4bea77f72867ec9bf8262507e13fdd Mon Sep 17 00:00:00 2001 From: LoaD Accumulator Date: Wed, 14 Jun 2023 13:01:27 +0200 Subject: [PATCH] [ADD] Add basic LilyPond support. Right now, it's using the lily!show command, which might change (check out #4) --- callbacks.py | 21 +++++++++++++++++++-- latex.py | 1 - lilypond.py | 24 ++++++++++++++++++++++++ main.py | 11 +++++++---- router.py | 25 ++++++++++++++----------- routes.py | 21 ++++++++++++++++----- utils.py | 12 +++++++----- 7 files changed, 87 insertions(+), 28 deletions(-) create mode 100644 lilypond.py diff --git a/callbacks.py b/callbacks.py index a9994ae..4b82768 100644 --- a/callbacks.py +++ b/callbacks.py @@ -1,8 +1,20 @@ +from router import Router +from routes import * from nio import * latex_regex = r'((?:\$[^\$]+\$)|(?:\$\$[^\$]+\$\$)|(?:\\\[[^\]]+\\\]))' +tex_router = Router("tex") +lily_router = Router("lily") + +def init_routes() -> None: + tex_router.add_route("help", "This very help menu.", route_help) + tex_router.add_route("delete", "Removes a TeX style file.", route_delete) + + lily_router.add_route("help", "This very help menu.", route_help) + lily_router.add_route("show", "Shows an in-line LilyPond expression", route_lshow) + # Our message callback. It should be passed through a router. async def msg_cb(room: MatrixRoom, event: RoomMessageText) -> None: import latex @@ -18,12 +30,17 @@ async def msg_cb(room: MatrixRoom, event: RoomMessageText) -> None: import router args = shlex.split(event.body[4:]) if len(args) >= 1: - await router.handle_command(args[0], room.room_id, event, args[1:]) + await tex_router.handle_command(args[0], room.room_id, event, args[1:]) + 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:]) for tex in re.findall(latex_regex, event.body, re.M): try: filename = latex.render(event.sender, tex) - await utils.send_png(room, filename) + await utils.send_png(room.room_id, filename) except FileNotFoundError as e: content = { "msgtype": "m.text", diff --git a/latex.py b/latex.py index 2f5f71c..7abac90 100644 --- a/latex.py +++ b/latex.py @@ -29,7 +29,6 @@ def render(user: str, source: str, png: bool = True) -> str: if f.endswith(".sty"): base = os.path.join(directory, f[:-4]) pkgs += "\\usepackage{{{base}}}\n ".format(base=base) - print(pkgs) fmt = template.format(content=source, packages=pkgs) diff --git a/lilypond.py b/lilypond.py new file mode 100644 index 0000000..0054081 --- /dev/null +++ b/lilypond.py @@ -0,0 +1,24 @@ +template = r""" +\header {{ + tagline = "" +}} +{content} +""" + +def render(user: str, source: str, png: bool = True) -> str: + import tempfile + import subprocess + import utils + import os + + fmt = template.format(content=source) + + tmp = tempfile.NamedTemporaryFile(delete=False) + tmp.write(bytes(fmt, encoding="utf8")) + tmp.close() + if png: + subprocess.run(["lilypond", "-d", "preview", "--png", tmp.name], cwd="/tmp") + return tmp.name + ".preview.png" + + subprocess.run(["lilypond", "-d", "preview", "--svg", tmp.name], cwd="/tmp") + return tmp.name + "preview.svg" diff --git a/main.py b/main.py index be4cdff..4d296ea 100644 --- a/main.py +++ b/main.py @@ -3,13 +3,13 @@ from nio import * import asyncio import utils - - async def main() -> None: import callbacks + import router import yaml - # Load our config file. + + # Load our config file. config = {} try: with open('texlily.yaml', 'r') as conf: @@ -33,8 +33,11 @@ async def main() -> None: client.access_token = token client.user_id = user + # Add routes. + callbacks.init_routes() + # TODO: Fix this hot mess before merging onto main. - client.sync(timeout=10000) + await client.sync(timeout=10000) # Register all of the callbacks utils.set_client(client) diff --git a/router.py b/router.py index c011676..6e25f7f 100644 --- a/router.py +++ b/router.py @@ -1,16 +1,19 @@ from nio import RoomMessageText import typing -routes = {} -helptxt = {} -def add_route(cmd: str, hlp: str, func: typing.Callable) -> None: - if cmd not in routes.keys(): - routes[cmd] = func - helptxt[cmd] = hlp +class Router(): + def __init__(self, name: str): + self.routes = {} + self.helptxt = {} + self.name = name -async def handle_command(command: str, room: str, event: RoomMessageText, args: list): - import utils - if command in routes.keys(): - await routes[command](utils.get_client(), room, event, args) - + def add_route(self, cmd: str, hlp: str, func: typing.Callable) -> None: + if cmd not in self.routes: + self.routes[cmd] = func + self.helptxt[cmd] = hlp + + async def handle_command(self, command: str, room: str, event: RoomMessageText, args: list): + import utils + if command in self.routes.keys(): + await self.routes[command](self, utils.get_client(), room, event, args) diff --git a/routes.py b/routes.py index ed67b1e..889fb27 100644 --- a/routes.py +++ b/routes.py @@ -1,17 +1,21 @@ +from router import Router from nio import * -async def route_help(client: Client, room: str, event: RoomMessageText, args: list) -> None: +async def route_help(r: Router, client: Client, room: str, event: RoomMessageText, args: list) -> None: import router import utils - + txt = "Commands for TeXLily:\n" - for cmd in router.routes.keys(): - txt += f"\ttxt!{cmd}: {router.helptxt[cmd]}\n" + print(r) + + for cmd in r.routes: + txt += f" {r.name}!{cmd}: {r.helptxt[cmd]}\n" await utils.send_msg(client, room, txt) -async def route_delete(client: Client, room: str, event: RoomMessageText, args: list) -> None: + +async def route_delete(router: Router, client: Client, room: str, event: RoomMessageText, args: list) -> None: if len(args) == 1: import utils import os @@ -26,3 +30,10 @@ async def route_delete(client: Client, room: str, event: RoomMessageText, args: except FileNotFoundError: await utils.send_msg(client, room, f"Couldn't delete style {args[0]}") pass + +async def route_lshow(router: Router, client: Client, room: str, event: RoomMessageText, args: list) -> None: + import lilypond + import utils + if len(args) == 1: + file = lilypond.render("", args[0]) + await utils.send_png(room, file) diff --git a/utils.py b/utils.py index dc1cddb..a3ebb4d 100644 --- a/utils.py +++ b/utils.py @@ -18,6 +18,11 @@ def set_config(c: dict) -> None: def get_config() -> dict: return config +async def send_msg(client: Client, room: str, msg: str): + content = {"msgtype": "m.text", "body": msg} + + await client.room_send(room, message_type="m.room.message", content=content) + def create_user_dir(user: str) -> str: import hashlib import os @@ -33,10 +38,7 @@ def create_user_dir(user: str) -> str: return os.path.abspath(path) - - - -async def send_png(room: MatrixRoom, filename: str) -> None: +async def send_png(room: str, filename: str) -> None: import imagesize import os basename = os.path.basename(filename) @@ -63,4 +65,4 @@ async def send_png(room: MatrixRoom, filename: str) -> None: } file.close() - await client.room_send(room.room_id, message_type="m.room.message", content=content) + await client.room_send(room, message_type="m.room.message", content=content)