2022-04-16 14:37:28 +08:00
|
|
|
from __future__ import annotations
|
|
|
|
|
2022-04-12 19:19:59 +08:00
|
|
|
import os
|
2022-05-21 15:56:03 +08:00
|
|
|
import re
|
2018-08-10 15:12:49 -07:00
|
|
|
|
2021-02-07 21:38:19 +08:00
|
|
|
from manimlib.config import get_custom_config
|
2022-05-21 15:56:03 +08:00
|
|
|
from manimlib.constants import PRESET_PREAMBLE
|
2021-10-07 17:37:10 +08:00
|
|
|
from manimlib.logger import log
|
2022-04-12 19:19:59 +08:00
|
|
|
from manimlib.utils.directories import get_tex_dir
|
2022-05-21 15:56:03 +08:00
|
|
|
from manimlib.utils.simple_functions import hash_string
|
2018-05-09 14:10:04 -07:00
|
|
|
|
|
|
|
|
2022-05-21 15:56:03 +08:00
|
|
|
class LatexError(Exception):
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
class TexTemplate:
|
|
|
|
def __init__(self, preamble_type: str | None = None):
|
|
|
|
tex_config = get_custom_config()["tex"]
|
|
|
|
self.executable = tex_config["executable"]
|
|
|
|
self.dvi_ext = tex_config["intermediate_filetype"]
|
|
|
|
if preamble_type is None:
|
|
|
|
preamble_type = tex_config["preamble"]
|
|
|
|
self.preamble = list(PRESET_PREAMBLE.get(
|
|
|
|
preamble_type, PRESET_PREAMBLE["default"]
|
|
|
|
))
|
|
|
|
|
|
|
|
def __hash__(self) -> int:
|
|
|
|
return hash(self.get_tex_file_content(""))
|
|
|
|
|
|
|
|
def get_tex_file_content(self, content: str) -> str:
|
|
|
|
return "\n\n".join((
|
|
|
|
"\\documentclass[preview]{standalone}",
|
|
|
|
"\n".join(self.preamble),
|
|
|
|
"\\begin{document}",
|
|
|
|
content,
|
|
|
|
"\\end{document}"
|
|
|
|
)) + "\n"
|
|
|
|
|
|
|
|
def get_svg_file_path(self, content: str) -> str:
|
|
|
|
full_tex = self.get_tex_file_content(content)
|
|
|
|
hash_code = hash_string(full_tex)
|
|
|
|
tex_dir = get_tex_dir()
|
|
|
|
root = os.path.join(tex_dir, hash_code)
|
|
|
|
svg_file_path = root + ".svg"
|
|
|
|
if os.path.exists(svg_file_path):
|
|
|
|
return svg_file_path
|
|
|
|
|
2021-01-03 11:29:09 -08:00
|
|
|
# If svg doesn't exist, create it
|
2022-05-21 15:56:03 +08:00
|
|
|
replaced_content = content.replace("\n", " ")
|
|
|
|
displayed_msg = f"Writing \"{replaced_content}\""
|
|
|
|
max_characters = os.get_terminal_size().columns - 1
|
|
|
|
if len(displayed_msg) > max_characters:
|
|
|
|
displayed_msg = displayed_msg[:max_characters - 3] + "..."
|
|
|
|
print(displayed_msg, end="\r")
|
|
|
|
|
|
|
|
with open(root + ".tex", "w", encoding="utf-8") as tex_file:
|
|
|
|
tex_file.write(full_tex)
|
|
|
|
|
|
|
|
# tex to dvi
|
|
|
|
if os.system(" ".join((
|
|
|
|
self.executable,
|
2018-09-26 21:09:04 +08:00
|
|
|
"-interaction=batchmode",
|
|
|
|
"-halt-on-error",
|
2022-05-21 15:56:03 +08:00
|
|
|
f"-output-directory=\"{tex_dir}\"",
|
|
|
|
f"\"{root}.tex\"",
|
2018-09-26 21:09:04 +08:00
|
|
|
">",
|
2018-12-30 01:27:03 +08:00
|
|
|
os.devnull
|
2022-05-21 15:56:03 +08:00
|
|
|
))):
|
2021-10-07 17:37:10 +08:00
|
|
|
log.error("LaTeX Error! Not a worry, it happens to the best of us.")
|
2022-05-21 15:56:03 +08:00
|
|
|
with open(root + ".log", "r", encoding="utf-8") as log_file:
|
|
|
|
error_match_obj = re.search(r"(?<=\n! ).*", log_file.read())
|
|
|
|
if error_match_obj:
|
|
|
|
log.debug("The error could be: `%s`", error_match_obj.group())
|
2022-04-20 21:53:05 -07:00
|
|
|
raise LatexError()
|
2022-05-21 15:56:03 +08:00
|
|
|
|
|
|
|
# dvi to svg
|
|
|
|
os.system(" ".join((
|
2018-05-09 14:10:04 -07:00
|
|
|
"dvisvgm",
|
2022-05-21 15:56:03 +08:00
|
|
|
f"\"{root}{self.dvi_ext}\"",
|
2018-05-09 14:10:04 -07:00
|
|
|
"-n",
|
|
|
|
"-v",
|
|
|
|
"0",
|
|
|
|
"-o",
|
2022-05-21 15:56:03 +08:00
|
|
|
f"\"{svg_file_path}\"",
|
2018-05-09 14:10:04 -07:00
|
|
|
">",
|
2018-12-30 01:27:03 +08:00
|
|
|
os.devnull
|
2022-05-21 15:56:03 +08:00
|
|
|
)))
|
2022-04-20 21:53:05 -07:00
|
|
|
|
2022-05-21 15:56:03 +08:00
|
|
|
# Cleanup superfluous documents
|
|
|
|
for ext in (".tex", self.dvi_ext, ".log", ".aux"):
|
|
|
|
try:
|
|
|
|
os.remove(root + ext)
|
|
|
|
except FileNotFoundError:
|
|
|
|
pass
|
2022-04-20 21:53:05 -07:00
|
|
|
|
2022-05-21 15:56:03 +08:00
|
|
|
print(" " * len(displayed_msg), end="\r")
|
|
|
|
return svg_file_path
|
2022-04-20 21:53:05 -07:00
|
|
|
|
2022-05-21 15:56:03 +08:00
|
|
|
def add_preamble(self, *preamble_strs: str):
|
|
|
|
self.preamble.extend(preamble_strs)
|
|
|
|
return self
|