mirror of
https://git.freetards.xyz/array.in.a.matrix/TexLiLy.git
synced 2025-04-02 13:21:42 -04:00
[ADD] Add basic support for custom styles in LaTeX
I still need to fix that syncing issue.
This commit is contained in:
parent
1f49413e18
commit
dff9dd2683
4 changed files with 73 additions and 15 deletions
27
callbacks.py
27
callbacks.py
|
@ -1,21 +1,21 @@
|
||||||
from nio import *
|
from nio import *
|
||||||
|
|
||||||
import utils
|
|
||||||
|
|
||||||
|
latex_regex = r'((?:\$[^\$]+\$)|(?:\$\$[^\$]+\$\$)|(?:\\\[[^\]]+\\\]))'
|
||||||
|
|
||||||
# Our message callback. It should be passed through a router.
|
# Our message callback. It should be passed through a router.
|
||||||
async def msg_cb(room: MatrixRoom, event: RoomMessageText) -> None:
|
async def msg_cb(room: MatrixRoom, event: RoomMessageText) -> None:
|
||||||
import re
|
|
||||||
import latex
|
import latex
|
||||||
|
import utils
|
||||||
|
import re
|
||||||
|
|
||||||
client = utils.get_client()
|
client = utils.get_client()
|
||||||
if event.sender == client.user_id:
|
if event.sender == client.user_id:
|
||||||
return
|
return
|
||||||
print("ae", client)
|
|
||||||
|
|
||||||
for tex in re.findall(r'((?:\$[^\$]+\$)|(?:\$\$[^\$]+\$\$)|(?:\\\[[^\]]+\\\]))', event.body, re.M):
|
for tex in re.findall(latex_regex, event.body, re.M):
|
||||||
print("Text:", tex)
|
|
||||||
try:
|
try:
|
||||||
filename = latex.render("", tex)
|
filename = latex.render(event.sender, tex)
|
||||||
await utils.send_png(room, filename)
|
await utils.send_png(room, filename)
|
||||||
except FileNotFoundError as e:
|
except FileNotFoundError as e:
|
||||||
content = {
|
content = {
|
||||||
|
@ -35,5 +35,20 @@ async def msg_cb(room: MatrixRoom, event: RoomMessageText) -> None:
|
||||||
|
|
||||||
# Our file callback.
|
# Our file callback.
|
||||||
async def file_cb(room: MatrixRoom, event: RoomMessageFile) -> None:
|
async def file_cb(room: MatrixRoom, event: RoomMessageFile) -> None:
|
||||||
|
import utils
|
||||||
|
import os
|
||||||
|
|
||||||
url = event.url
|
url = event.url
|
||||||
filename = event.body
|
filename = event.body
|
||||||
|
|
||||||
|
if filename.endswith(".sty"):
|
||||||
|
# Download file and save it for user.
|
||||||
|
client = utils.get_client()
|
||||||
|
directory = utils.create_user_dir(event.sender)
|
||||||
|
response = await client.download(url, filename)
|
||||||
|
|
||||||
|
if not isinstance(response, DownloadResponse):
|
||||||
|
return
|
||||||
|
|
||||||
|
with open(os.path.join(directory, filename), 'wb') as f:
|
||||||
|
f.write(response.body)
|
||||||
|
|
25
latex.py
25
latex.py
|
@ -1,10 +1,12 @@
|
||||||
# Converts a TeX file into a PNG/SVG file.
|
# Converts a TeX file into a PNG/SVG file.
|
||||||
template = r"""
|
template = r"""
|
||||||
\documentclass[utf8,preview]{{standalone}}
|
\documentclass[utf8,preview,varwidth]{{standalone}}
|
||||||
\usepackage{{amsmath}}
|
\usepackage{{amsmath}}
|
||||||
\usepackage[active,tightpage]{{preview}}
|
\usepackage[active]{{preview}}
|
||||||
\usepackage[utf8]{{inputenc}}
|
\usepackage[utf8]{{inputenc}}
|
||||||
|
\usepackage{{tikz}}
|
||||||
% TODO: Add user packages here.
|
% TODO: Add user packages here.
|
||||||
|
{packages}
|
||||||
\begin{{document}}
|
\begin{{document}}
|
||||||
% The user content goes here.
|
% The user content goes here.
|
||||||
{content}
|
{content}
|
||||||
|
@ -16,13 +18,25 @@ template = r"""
|
||||||
def render(user: str, source: str, png: bool = True) -> str:
|
def render(user: str, source: str, png: bool = True) -> str:
|
||||||
import tempfile
|
import tempfile
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import utils
|
||||||
|
import os
|
||||||
|
|
||||||
|
# Put the user's packages in the format too.
|
||||||
|
directory = utils.create_user_dir(user)
|
||||||
|
pkgs = ""
|
||||||
|
|
||||||
fmt = template.format(content=source)
|
for f in os.listdir(directory):
|
||||||
|
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)
|
||||||
|
|
||||||
tmp = tempfile.NamedTemporaryFile(delete=False)
|
tmp = tempfile.NamedTemporaryFile(delete=False)
|
||||||
tmp.write(bytes(fmt, encoding="utf8"))
|
tmp.write(bytes(fmt, encoding="utf8"))
|
||||||
tmp.close()
|
tmp.close()
|
||||||
print(tmp.name)
|
|
||||||
# Parse our templated file thru' LaTeX and dvipng.
|
# Parse our templated file thru' LaTeX and dvipng.
|
||||||
# TODO: Allow arbitrary DPI and foreground color.
|
# 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)
|
||||||
|
@ -30,8 +44,7 @@ def render(user: str, source: str, png: bool = True) -> str:
|
||||||
raise FileNotFoundError(ret.stdout.decode())
|
raise FileNotFoundError(ret.stdout.decode())
|
||||||
|
|
||||||
if png:
|
if png:
|
||||||
print("PNG")
|
subprocess.run(["dvipng", "-D", "5000", tmp.name + ".dvi", "-bg", "Transparent",
|
||||||
subprocess.run(["dvipng", "-D", "2000", tmp.name + ".dvi", "-bg", "Transparent",
|
|
||||||
"-fg", "rgb 1 1 1", "-o", tmp.name + ".png"], cwd="/tmp")
|
"-fg", "rgb 1 1 1", "-o", tmp.name + ".png"], cwd="/tmp")
|
||||||
|
|
||||||
return tmp.name + ".png"
|
return tmp.name + ".png"
|
||||||
|
|
7
main.py
7
main.py
|
@ -18,7 +18,8 @@ async def main() -> None:
|
||||||
homeserver = str(config["homeserver"])
|
homeserver = str(config["homeserver"])
|
||||||
user = str(config["user"])
|
user = str(config["user"])
|
||||||
token = str(config["token"])
|
token = str(config["token"])
|
||||||
# path = str(config["path"]) # not used
|
path = str(config["data"]) # Unused there, required.
|
||||||
|
utils.set_config(config)
|
||||||
# if config file does not exist, quit
|
# if config file does not exist, quit
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
print("No config file found.")
|
print("No config file found.")
|
||||||
|
@ -32,8 +33,8 @@ async def main() -> None:
|
||||||
client.access_token = token
|
client.access_token = token
|
||||||
client.user_id = user
|
client.user_id = user
|
||||||
|
|
||||||
# Bad kludge!
|
# TODO: Fix this hot mess before merging onto main.
|
||||||
await client.sync(timeout=3000)
|
client.sync(timeout=10000)
|
||||||
|
|
||||||
# Register all of the callbacks
|
# Register all of the callbacks
|
||||||
utils.set_client(client)
|
utils.set_client(client)
|
||||||
|
|
29
utils.py
29
utils.py
|
@ -1,12 +1,41 @@
|
||||||
from nio import *
|
from nio import *
|
||||||
|
|
||||||
|
|
||||||
def set_client(c: AsyncClient) -> None:
|
def set_client(c: AsyncClient) -> None:
|
||||||
global client
|
global client
|
||||||
client = c
|
client = c
|
||||||
|
|
||||||
|
|
||||||
def get_client() -> AsyncClient:
|
def get_client() -> AsyncClient:
|
||||||
return client
|
return client
|
||||||
|
|
||||||
|
|
||||||
|
def set_config(c: dict) -> None:
|
||||||
|
global config
|
||||||
|
config = c
|
||||||
|
|
||||||
|
|
||||||
|
def get_config() -> dict:
|
||||||
|
return config
|
||||||
|
|
||||||
|
def create_user_dir(user: str) -> str:
|
||||||
|
import hashlib
|
||||||
|
import os
|
||||||
|
|
||||||
|
# NOTE: I would have used the user directly, but the Spec allows MXIDs
|
||||||
|
# with '/' and UNIX-based OSes will **not** like that.
|
||||||
|
sha = hashlib.sha256(bytes(user, 'ascii')).hexdigest()
|
||||||
|
|
||||||
|
path = os.path.join(get_config()["data"], sha)
|
||||||
|
if not os.path.exists(path):
|
||||||
|
os.makedirs(path)
|
||||||
|
|
||||||
|
return os.path.abspath(path)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
async def send_png(room: MatrixRoom, filename: str) -> None:
|
async def send_png(room: MatrixRoom, filename: str) -> None:
|
||||||
import imagesize
|
import imagesize
|
||||||
import os
|
import os
|
||||||
|
|
Loading…
Add table
Reference in a new issue