Update documentclass.
This commit is contained in:
parent
154d8e1858
commit
758e99d5a7
@ -6,6 +6,7 @@ from .documentclass import *
|
|||||||
from .figure import figure
|
from .figure import figure
|
||||||
from .formatter import formatter
|
from .formatter import formatter
|
||||||
from .input_element import input_element
|
from .input_element import input_element
|
||||||
|
from .includegraphics import includegraphics
|
||||||
from .makebox import makebox
|
from .makebox import makebox
|
||||||
from .resizebox import resizebox
|
from .resizebox import resizebox
|
||||||
from .subfloat import subfloat
|
from .subfloat import subfloat
|
||||||
|
@ -3,20 +3,41 @@
|
|||||||
from collections import Iterable
|
from collections import Iterable
|
||||||
from .element import element
|
from .element import element
|
||||||
|
|
||||||
|
import enum
|
||||||
|
import os
|
||||||
import subprocess
|
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):
|
class documentclass(element):
|
||||||
|
|
||||||
packages = {}
|
|
||||||
preamble = []
|
|
||||||
options = []
|
|
||||||
classname = 'standalone'
|
classname = 'standalone'
|
||||||
|
|
||||||
templates = {
|
templates = {
|
||||||
'package': '\\usepackage{pkgoptions}{{{pkgname}}}',
|
'package': '\\usepackage{pkgoptions}{{{pkgname}}}',
|
||||||
'options': '[{content}]',
|
'options': '[{content}]',
|
||||||
'def': '\\def\\{name}#{nargs}{{{value}}}',
|
'def': '\\def\\{name}{nargs}{{{value}}}',
|
||||||
'content': """\\documentclass{options}{{{classname}}}
|
'content': """\\documentclass{options}{{{classname}}}
|
||||||
{packages}
|
{packages}
|
||||||
{preamble}
|
{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)
|
super().__init__(parent=None, childrens=childrens)
|
||||||
self.options = options
|
self.options = options
|
||||||
self.classname = classname
|
self.classname = classname
|
||||||
|
self.packages = {}
|
||||||
self.add_packages(packages)
|
self.add_packages(packages)
|
||||||
|
self.preamble = []
|
||||||
|
self.add2preamble(preamble)
|
||||||
|
|
||||||
def add_packages(self, packages):
|
def add_packages(self, packages):
|
||||||
if type(packages) is str:
|
if type(packages) is str:
|
||||||
@ -49,19 +77,19 @@ class documentclass(element):
|
|||||||
def add_def(self, name, nargs, value):
|
def add_def(self, name, nargs, value):
|
||||||
self.preamble.append(self.fmt().format('def', {
|
self.preamble.append(self.fmt().format('def', {
|
||||||
'name': name,
|
'name': name,
|
||||||
'nargs': nargs,
|
'nargs': '#{}'.format(nargs) if nargs > 0 else '',
|
||||||
'value': value
|
'value': value
|
||||||
}))
|
}))
|
||||||
|
|
||||||
def format_preamble(self, defs):
|
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):
|
def format_packages(self, pkgs):
|
||||||
out = []
|
out = []
|
||||||
for pkg, opts in self.packages.items():
|
for pkg in sorted(pkgs):
|
||||||
options = ''
|
options = ''
|
||||||
if opts is not True:
|
if pkgs[pkg] is not True:
|
||||||
options = self.format_options(opts)
|
options = self.format_options(pkgs[pkg])
|
||||||
out.append(self.fmt().format('package', {
|
out.append(self.fmt().format('package', {
|
||||||
'pkgname': pkg,
|
'pkgname': pkg,
|
||||||
'pkgoptions': options
|
'pkgoptions': options
|
||||||
@ -77,12 +105,78 @@ class documentclass(element):
|
|||||||
'content': super().content()
|
'content': super().content()
|
||||||
})
|
})
|
||||||
|
|
||||||
def compile(self, outfile, infile=None, outlog=None):
|
def compile(self, outfile, infile='auto', outlog=None):
|
||||||
if infile is None:
|
""" Compile the given document into a PDF file.
|
||||||
infile = '/tmp/pyltk-{}.tex'.format(id(self))
|
|
||||||
|
|
||||||
with open(infile, 'w') as infd:
|
If infile is not None, and infile already exists, the document
|
||||||
infd.write(self.content())
|
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]
|
Parameters:
|
||||||
subprocess.call(call, stdout=outlog)
|
- 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
|
||||||
|
@ -26,7 +26,8 @@ class element:
|
|||||||
# Do not wrap non-element in wrapper_element
|
# Do not wrap non-element in wrapper_element
|
||||||
raw = False
|
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.
|
""" Create a new element with given parameters.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
@ -34,7 +35,8 @@ class element:
|
|||||||
- childrens Childrens of the element - Single element or list of
|
- childrens Childrens of the element - Single element or list of
|
||||||
objects (element or not).
|
objects (element or not).
|
||||||
- label Label of the element.
|
- 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.parent = parent
|
||||||
self.raw = raw
|
self.raw = raw
|
||||||
if childrens is None:
|
if childrens is None:
|
||||||
@ -44,6 +46,7 @@ class element:
|
|||||||
self.childrens = []
|
self.childrens = []
|
||||||
self.add(childrens)
|
self.add(childrens)
|
||||||
self.label = label
|
self.label = label
|
||||||
|
self.options = kargs
|
||||||
|
|
||||||
def add(self, childrens):
|
def add(self, childrens):
|
||||||
if not isinstance(childrens, Iterable):
|
if not isinstance(childrens, Iterable):
|
||||||
@ -69,8 +72,9 @@ class element:
|
|||||||
if not options:
|
if not options:
|
||||||
return ''
|
return ''
|
||||||
opts = []
|
opts = []
|
||||||
for k, v in options.items():
|
# Note: Sorted to have a guaranteed output
|
||||||
opts.append('{key} = {{{value}}}'.format(key=k, value=v))
|
for k in sorted(options):
|
||||||
|
opts.append('{key} = {{{value}}}'.format(key=k, value=options[k]))
|
||||||
return self.fmt().format('options', {
|
return self.fmt().format('options', {
|
||||||
'content': ', '.join(opts)
|
'content': ', '.join(opts)
|
||||||
})
|
})
|
||||||
|
23
pyltk/includegraphics.py
Normal file
23
pyltk/includegraphics.py
Normal 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)
|
||||||
|
})
|
@ -7,11 +7,13 @@ class subfloat(element):
|
|||||||
""" Class representing a latex subfloat. """
|
""" Class representing a latex subfloat. """
|
||||||
|
|
||||||
templates = {
|
templates = {
|
||||||
'content': """\\subfloat[{caption}]{{
|
'content': """\\subfloat[{caption}{label}]{{
|
||||||
{inner}
|
{inner}
|
||||||
}}"""
|
}}"""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
autolabel = False
|
||||||
|
|
||||||
def __init__(self, caption, parent=None, childrens=None, label=None):
|
def __init__(self, caption, parent=None, childrens=None, label=None):
|
||||||
super().__init__(parent, childrens, label=label)
|
super().__init__(parent, childrens, label=label)
|
||||||
self.caption = caption
|
self.caption = caption
|
||||||
@ -19,5 +21,6 @@ class subfloat(element):
|
|||||||
def content(self):
|
def content(self):
|
||||||
return self.fmt().format('content', {
|
return self.fmt().format('content', {
|
||||||
'caption': self.caption,
|
'caption': self.caption,
|
||||||
|
'label': self.format_label(self.label),
|
||||||
'inner': super().content()
|
'inner': super().content()
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user