Simple tex jinja2 Precompiler
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
PreTex/bin/pretex

151 lines
5.3 KiB

5 years ago
#!/usr/bin/env python3
"""Simple tex jinja2 Precompiler.
With slightly different syntax:
{{ ... }} => \VAR{ ... } for Expressions to print to the template output
{% ... %} => \BLOCK{ ... } for Statements
{# ... #} => \#{ ... } for Comments not included in the template output
# ... ## => %$ ... %# for Line Statements
Usage:
pretex [<templates>] [options]
5 years ago
Arguments:
<templates> Compiles every given file ending with ".j2.tex" into
respective ".tex" file. [default: "**/*.j2.tex"]
Options:
-h --help Show this screen.
-p --pdf Also compiles rendered ".tex" file to pdf.
-o --out=<file> Save output to file.
-d --data=<yamlfile> YAML files with data for the template.
-t --tex=<compiler> LaTeX compiler to use [default: pdflatex]
-a --arg=<args> LaTeX compiler arguments
[default: -synctex=1 -interaction=nonstopmode -file-line-error]
-b --bib=<bib> bibTeX compiler to use. [default: bibtex]
-c --copy=<dir> Gather copies of all resulting pdf files in a folder.
--chain=<chain> Define the render command.
[default: {TEX} {ARG} {document}.tex, {BIB} {document}, {TEX} {ARG} {document}.tex, {TEX} {ARG} {document}.tex]
--clean Clean aux files.
-f --files=<end> Files to clean.
[default: *.aux, *.bbl, *.blg, *.idx, *.ind, *.lof, *.lot, *.out, *.toc, *.acn, *.acr, *.alg, *.glg, *.glo, *.gls, *.ist, *.fls, *.log, *.fdb_latexmk]
5 years ago
"""
import yaml
import glob
import jinja2
import os
from docopt import docopt
import dateparser
import datetime
import subprocess
import functools
import shlex
from shutil import copyfile
class RelEnvironment(jinja2.Environment):
"""Override join_path() to enable relative template paths."""
def join_path(self, template, parent):
return os.path.normpath(os.path.join(os.path.dirname(parent), template))
def datetime_filter(dt, format=None):
"""Jinja template filter to format a datetime object."""
if dt is None:
# By default, render an empty string.
return ''
if not isinstance(dt, datetime.datetime):
dt = dateparser.parse(dt, settings={'DATE_ORDER': 'DMY'})
if format is None:
# No format is given in the template call.
# Use a default format.
formatted_date = dt.strftime('%Y-%m-%d - %A')
formatted_time =\
dt.strftime('%I:%M%p').lstrip('0').lower()
formatted = '%s at %s' %\
(formatted_date, formatted_time)
else:
formatted = dt.strftime(format)
return formatted
def get_latex_toolchain(arguments, document):
return arguments["--chain"].format(
TEX=arguments["--tex"],
ARG=arguments["--arg"],
BIB=arguments["--bib"],
document=document).split(",")
def compile_all(data, templates, pdf, cmd, copy, clean):
if templates is None:
templates = "**/*.j2.tex"
for tex_file in glob.glob(templates, recursive=True):
if tex_file[-7:] == ".j2.tex":
compiled_file = f"{tex_file[:-7]}.tex"
print(compile_file(tex_file, data, compiled_file))
if not pdf:
continue
path, filename = os.path.split(compiled_file)
for command in cmd(filename[:-4]):
cwd = path
if cwd == '':
cwd = None
subprocess.call(shlex.split(command), cwd=cwd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
5 years ago
if copy:
if not os.path.exists(copy):
os.makedirs(copy)
copyfile(f"{tex_file[:-7]}.pdf", os.path.join(copy, f"{filename[:-4]}.pdf"))
if clean:
for ending in clean.split(","):
for file in glob.glob(os.path.join(path, ending.strip()), recursive=True):
os.remove(file)
def compile_file(tex_file, data, file=None):
template = latex_jinja_env.get_template(os.path.abspath(tex_file))
path, filename = os.path.split(tex_file)
rendered = template.render(**data, load_yaml=functools.partial(load_yaml, path=path))
5 years ago
if file is None:
return rendered
f = open(file, 'w')
f.write(rendered)
f.close()
return f'"{tex_file}" successful rendered into "{file}"'
def load_yaml(filename, path=""):
with open(os.path.join(path,filename)) as file:
data = yaml.load(file, Loader=yaml.FullLoader)
return data
5 years ago
if __name__ == '__main__':
arguments = docopt(__doc__)
latex_jinja_env = RelEnvironment(
block_start_string = '\\BLOCK{',
block_end_string = '}',
variable_start_string = '\\VAR{',
variable_end_string = '}',
comment_start_string = '\\#{',
comment_end_string = '}',
line_statement_prefix = '%§',
line_comment_prefix = '%#',
trim_blocks = True,
autoescape = False,
loader = jinja2.FileSystemLoader(os.path.abspath('/')),
5 years ago
)
latex_jinja_env.filters['datetime'] = datetime_filter
if arguments['--data']:
data = load_yaml(arguments["--data"])
else:
data = {}
5 years ago
cmd = functools.partial(get_latex_toolchain, arguments)
compile_all(data, arguments['<templates>'], arguments['--pdf'], cmd, arguments['--copy'], arguments['--clean'] and arguments['--files'])