129 lines
3.9 KiB
Python
129 lines
3.9 KiB
Python
# -*- encoding: utf-8 -*-
|
|
|
|
from .formatter import formatter
|
|
|
|
from collections import Iterable
|
|
|
|
|
|
class element:
|
|
|
|
""" Class representing a latex element.
|
|
|
|
An element is a latex element (e.g. \\figure), with a parent and some
|
|
childrens. An element can have no parent and 0 childrens.
|
|
|
|
By default, all childrens of an element must be instances of element
|
|
themselves. To avoid this behavior, `raw` element can be used. `raw`
|
|
elements do not wrap their children in `wrapper_element` when they
|
|
are no subclasses of `element`. """
|
|
|
|
# Joiner for childrens
|
|
sep = "\n"
|
|
|
|
# Automatically add label after element if present
|
|
autolabel = True
|
|
|
|
# Do not wrap non-element in wrapper_element
|
|
raw = False
|
|
|
|
def __init__(self, parent=None, childrens=[], label=None, raw=False, **kargs):
|
|
""" Create a new element with given parameters.
|
|
|
|
Parameters:
|
|
- parent Parent of the element (another 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`).
|
|
- kargs Options for the element. """
|
|
self.parent = parent
|
|
self.raw = raw
|
|
if childrens is None:
|
|
childrens = []
|
|
if not isinstance(childrens, Iterable):
|
|
childrens = [childrens]
|
|
self.childrens = []
|
|
self.add(childrens)
|
|
self.label = label
|
|
self.options = kargs
|
|
|
|
def add(self, childrens):
|
|
if not isinstance(childrens, Iterable) or isinstance(childrens, str):
|
|
childrens = [childrens]
|
|
for child in childrens:
|
|
if not self.raw:
|
|
if not isinstance(child, element):
|
|
child = wrapper_element(child, self)
|
|
try:
|
|
child.parent.remove(child)
|
|
except:
|
|
pass
|
|
child.parent = self
|
|
self.childrens.append(child)
|
|
|
|
def content(self):
|
|
return self.sep.join(map(str, self.childrens))
|
|
|
|
def fmt(self):
|
|
return formatter(self.templates)
|
|
|
|
def format_options_dict(self, options):
|
|
opts = []
|
|
# Note: Sorted to have a guaranteed output
|
|
for k in sorted(options):
|
|
value = options[k]
|
|
|
|
if value is True:
|
|
opts.append(k)
|
|
else:
|
|
if isinstance(value, dict):
|
|
value = self.format_options_dict(value)
|
|
elif isinstance(value, list) or isinstance(value, tuple):
|
|
value = ",".join(value)
|
|
else:
|
|
value = str(value).strip()
|
|
if value[0] == "{" and value[1] == "}":
|
|
value = value[1:-1]
|
|
opts.append("{key}={{{value}}}".format(key=k, value=value))
|
|
return ", ".join(opts)
|
|
|
|
def format_options(self, options):
|
|
if not options:
|
|
return ""
|
|
return self.fmt().format(
|
|
"options", {"content": self.format_options_dict(options)}
|
|
)
|
|
|
|
def format_label(self, label):
|
|
if not label:
|
|
return ""
|
|
return "\\label{{{}}}".format(label)
|
|
|
|
def __str__(self):
|
|
out = self.content().strip()
|
|
if self.autolabel:
|
|
out += self.format_label(self.label)
|
|
return out
|
|
|
|
|
|
class wrapper_element(element):
|
|
|
|
""" Wrapper for standard python types working as latex elements. """
|
|
|
|
escape_list = ["_", "#", "%"]
|
|
|
|
def __init__(self, data, parent=None, autoescape=True):
|
|
super().__init__(parent=parent)
|
|
self.autoescape = autoescape
|
|
self.data = data
|
|
|
|
def escape(self, s):
|
|
if not self.autoescape:
|
|
return s
|
|
for e in self.escape_list:
|
|
s = s.replace(e, "\\" + e)
|
|
return s
|
|
|
|
def content(self):
|
|
return self.escape(str(self.data))
|