parent
11fe2f8792
commit
375d4bdcb2
@ -1,3 +1,7 @@ |
||||
# PreTex |
||||
# PreTeX |
||||
|
||||
Simple tex jinja2 Precompiler |
||||
Use `pretex -h` for help. |
||||
|
||||
## Installation |
||||
|
||||
`pip install git+` |
||||
|
@ -0,0 +1,139 @@ |
||||
#!/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>] --data=<yamlfile> [options] |
||||
|
||||
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, *.synctex.gz] |
||||
""" |
||||
|
||||
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]): |
||||
subprocess.call(shlex.split(command), cwd=path, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) |
||||
|
||||
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(tex_file) |
||||
rendered = template.render(**data) |
||||
if file is None: |
||||
return rendered |
||||
f = open(file, 'w') |
||||
f.write(rendered) |
||||
f.close() |
||||
return f'"{tex_file}" successful rendered into "{file}"' |
||||
|
||||
|
||||
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('.')), |
||||
) |
||||
|
||||
latex_jinja_env.filters['datetime'] = datetime_filter |
||||
|
||||
with open(arguments['--data']) as file: |
||||
data = yaml.load(file, Loader=yaml.FullLoader)["data"] |
||||
|
||||
cmd = functools.partial(get_latex_toolchain, arguments) |
||||
compile_all(data, arguments['<templates>'], arguments['--pdf'], cmd, arguments['--copy'], arguments['--clean'] and arguments['--files']) |
@ -0,0 +1,18 @@ |
||||
import setuptools |
||||
|
||||
with open("README.md", "r") as fh: |
||||
long_description = fh.read() |
||||
|
||||
setuptools.setup( |
||||
name="PreTeX", # Replace with your own username |
||||
version="0.1", |
||||
scripts=["bin/pretex"], |
||||
author="Ugo Finnendahl", |
||||
author_email="ugo.finnendahl@tu-berlin.de", |
||||
description="A jinja2 based TeX precompiler", |
||||
long_description=long_description, |
||||
long_description_content_type="text/markdown", |
||||
url="", |
||||
packages=setuptools.find_packages(), |
||||
install_requires=['PyYAML','Jinja2', 'docopt', 'dateparser'], |
||||
) |
Loading…
Reference in new issue