Update documentclass.

This commit is contained in:
Mikael Capelle 2018-02-26 19:23:34 +01:00
parent 154d8e1858
commit 758e99d5a7
5 changed files with 147 additions and 22 deletions

View File

@ -6,6 +6,7 @@ from .documentclass import *
from .figure import figure
from .formatter import formatter
from .input_element import input_element
from .includegraphics import includegraphics
from .makebox import makebox
from .resizebox import resizebox
from .subfloat import subfloat

View File

@ -3,20 +3,41 @@
from collections import Iterable
from .element import element
import enum
import os
import subprocess
class change_directory:
"""Context manager for changing the current working directory"""
def __init__(self, newPath):
self.newPath = os.path.expanduser(newPath)
def __enter__(self):
self.savedPath = os.getcwd()
os.chdir(self.newPath)
def __exit__(self, etype, value, traceback):
os.chdir(self.savedPath)
class CompileResult(enum.Enum):
ALREADY_EXISTS = 1
SUCCESS = 2
ERROR = 3
class documentclass(element):
packages = {}
preamble = []
options = []
classname = 'standalone'
templates = {
'package': '\\usepackage{pkgoptions}{{{pkgname}}}',
'options': '[{content}]',
'def': '\\def\\{name}#{nargs}{{{value}}}',
'def': '\\def\\{name}{nargs}{{{value}}}',
'content': """\\documentclass{options}{{{classname}}}
{packages}
{preamble}
@ -26,11 +47,18 @@ class documentclass(element):
"""
}
def __init__(self, classname, childrens=[], options=[], packages=[]):
output_aux_folder = '.pyltk'
auto_tex_folder = '{}/tex2pdf'.format(output_aux_folder)
def __init__(self, classname, childrens=[], options=[],
packages=[], preamble=[]):
super().__init__(parent=None, childrens=childrens)
self.options = options
self.classname = classname
self.packages = {}
self.add_packages(packages)
self.preamble = []
self.add2preamble(preamble)
def add_packages(self, packages):
if type(packages) is str:
@ -49,19 +77,19 @@ class documentclass(element):
def add_def(self, name, nargs, value):
self.preamble.append(self.fmt().format('def', {
'name': name,
'nargs': nargs,
'nargs': '#{}'.format(nargs) if nargs > 0 else '',
'value': value
}))
def format_preamble(self, defs):
return '\n'.join(self.preamble)
return '\n'.join(str(p) for p in self.preamble)
def format_packages(self, pkgs):
out = []
for pkg, opts in self.packages.items():
for pkg in sorted(pkgs):
options = ''
if opts is not True:
options = self.format_options(opts)
if pkgs[pkg] is not True:
options = self.format_options(pkgs[pkg])
out.append(self.fmt().format('package', {
'pkgname': pkg,
'pkgoptions': options
@ -77,12 +105,78 @@ class documentclass(element):
'content': super().content()
})
def compile(self, outfile, infile=None, outlog=None):
if infile is None:
infile = '/tmp/pyltk-{}.tex'.format(id(self))
def compile(self, outfile, infile='auto', outlog=None):
""" Compile the given document into a PDF file.
with open(infile, 'w') as infd:
infd.write(self.content())
If infile is not None, and infile already exists, the document
will only be compiled if the content of infile is different
from this document or if infile is newer than the output
document.
call = ['pdflatex', '-halt-on-error', '-jobname', outfile, infile]
subprocess.call(call, stdout=outlog)
Parameters:
- outfile Name of the output file (pdf extension may
be omitted).
- infile Name of the file to which latex code must be
written. If None, a temporary file will be created
and then erased. If 'auto', file will be saved in
an automatic folder for future use.
- outlog
"""
outdir = os.path.dirname(outfile)
outfile = os.path.basename(outfile)
res = CompileResult.ERROR
with change_directory(outdir):
os.makedirs(self.output_aux_folder, exist_ok=True)
if outfile.endswith('.pdf'):
outfile = outfile[:-4]
to_delete = False
if infile == 'auto':
os.makedirs(self.auto_tex_folder, exist_ok=True)
infile = '{}/{}.tex'.format(self.auto_tex_folder, outfile)
if infile is None:
to_delete = True
infile = '.pyltk-{}.tex'.format(outfile)
to_create = True
new_content = self.content()
# If the input file already exists...
if os.path.exists(infile):
with open(infile, 'r') as infd:
old_content = infd.read()
# Content has not changed
if old_content == new_content \
and os.path.exists('{}.pdf'.format(outfile)) \
and os.path.getctime(infile) <= \
os.path.getctime('{}.pdf'.format(outfile)):
to_create = False
if to_create:
with open(infile, 'w') as infd:
infd.write(self.content())
call = ['pdflatex', '-halt-on-error',
'-output-directory', self.output_aux_folder,
'-jobname', outfile, infile]
if subprocess.call(call, stdout=outlog) == 0:
os.rename('{}/{}.pdf'.format(
self.output_aux_folder, outfile),
'{}.pdf'.format(outfile))
res = CompileResult.SUCCESS
else:
res = CompileResult.ERROR
else:
res = CompileResult.ALREADY_EXISTS
if to_delete:
os.remove(infile)
return res

View File

@ -26,7 +26,8 @@ class element:
# Do not wrap non-element in wrapper_element
raw = False
def __init__(self, parent=None, childrens=[], label=None, raw=False):
def __init__(self, parent=None, childrens=[], label=None,
raw=False, **kargs):
""" Create a new element with given parameters.
Parameters:
@ -34,7 +35,8 @@ class element:
- childrens Childrens of the element - Single element or list of
objects (element or not).
- label Label of the element.
- raw Raw childrens (see description of `element`). """
- raw Raw childrens (see description of `element`).
- kargs Options for the element. """
self.parent = parent
self.raw = raw
if childrens is None:
@ -44,6 +46,7 @@ class element:
self.childrens = []
self.add(childrens)
self.label = label
self.options = kargs
def add(self, childrens):
if not isinstance(childrens, Iterable):
@ -69,8 +72,9 @@ class element:
if not options:
return ''
opts = []
for k, v in options.items():
opts.append('{key} = {{{value}}}'.format(key=k, value=v))
# Note: Sorted to have a guaranteed output
for k in sorted(options):
opts.append('{key} = {{{value}}}'.format(key=k, value=options[k]))
return self.fmt().format('options', {
'content': ', '.join(opts)
})

23
pyltk/includegraphics.py Normal file
View File

@ -0,0 +1,23 @@
# -*- encoding: utf-8 -*-
from .element import element
class includegraphics(element):
""" Class representing a latex includegrahics. """
templates = {
'element': '\\includegraphics[{options}]{{{filename}}}'
}
autolabel = False
def __init__(self, filename, parent=None, **kargs):
super().__init__(parent, **kargs)
self.filename = filename
def content(self):
return self.fmt().format('element', {
'filename': self.filename,
'options': self.format_options(self.options)
})

View File

@ -7,11 +7,13 @@ class subfloat(element):
""" Class representing a latex subfloat. """
templates = {
'content': """\\subfloat[{caption}]{{
'content': """\\subfloat[{caption}{label}]{{
{inner}
}}"""
}
autolabel = False
def __init__(self, caption, parent=None, childrens=None, label=None):
super().__init__(parent, childrens, label=label)
self.caption = caption
@ -19,5 +21,6 @@ class subfloat(element):
def content(self):
return self.fmt().format('content', {
'caption': self.caption,
'label': self.format_label(self.label),
'inner': super().content()
})