Browse Source

Recherche des variables dans les templates (#18)

- Charge les variable dans les templates de manière récursive
- Respecte la surcharge (les variables d'un template surchargent les
  variables des templates inclus).
- Accepte plusieurs blocs de variables dans un même template.
pull/22/head
Louis 11 years ago
parent
commit
74ecaf6114
  1. 100
      songbook_core/templates.py

100
songbook_core/templates.py

@ -6,6 +6,7 @@ from jinja2 import Environment, FileSystemLoader, ChoiceLoader, PackageLoader, \
TemplateNotFound, nodes TemplateNotFound, nodes
from jinja2.ext import Extension from jinja2.ext import Extension
from jinja2.meta import find_referenced_templates as find_templates from jinja2.meta import find_referenced_templates as find_templates
import codecs
import os import os
import re import re
import json import json
@ -21,6 +22,25 @@ _LATEX_SUBS = (
(re.compile(r'\.\.\.+'), r'\\ldots'), (re.compile(r'\.\.\.+'), r'\\ldots'),
) )
VARIABLE_REGEXP = re.compile(r"""
\(\*\ *variables\ *\*\) # Match (* variables *)
( # Match and capture the following:
(?: # Start of non-capturing group, used to match a single character
(?! # only if it's impossible to match the following:
\(\*\ * # - a literal (*
(?: # Inner non-capturing group, used for the following alternation:
variables # - Either match the word variables
| # or
endvariables # - the word endvariables
) # End of inner non-capturing group
\ *\*\) # - a literal *)
) # End of negative lookahead assertion
. # Match any single character
)* # Repeat as often as possible
) # End of capturing group 1
\(\*\ *endvariables\ *\*\) # until (* endvariables *) is matched.""",
re.VERBOSE|re.DOTALL)
class VariablesExtension(Extension): class VariablesExtension(Extension):
"""Extension to jinja2 to silently ignore variable block. """Extension to jinja2 to silently ignore variable block.
@ -96,7 +116,7 @@ class TexRenderer(object):
'''Get and return a dictionary with the default values '''Get and return a dictionary with the default values
for all the variables for all the variables
''' '''
data = self.parse_templates() data = self.get_template_variables(self.template)
variables = dict() variables = dict()
for name, param in data.items(): for name, param in data.items():
variables[name] = self._get_default(param) variables[name] = self._get_default(param)
@ -124,39 +144,57 @@ class TexRenderer(object):
return variable return variable
def parse_templates(self): def get_template_variables(self, template, skip=None):
'''Recursively parse all the used templates to extract all the """Parse the template to extract the variables as a dictionary.
variables as a dictionary.
''' If the template includes or extends other templates, load them as well.
templates = self.get_templates(self.template)
templates |= set([self.template.name]) Arguments:
- template: the name of the template, as a string.
- skip: a list of templates (as strings) to skip: if they are included
in 'template' (or one of its subtemplates), it is not parsed.
"""
if not skip:
skip = []
variables = {} variables = {}
regex = re.compile(r'\(\* variables \*\)\n(?P<variables>.*)' (current, templates) = self.parse_template(template)
'\(\* endvariables \*\)', re.DOTALL) for subtemplate in templates:
for template_name in templates: if subtemplate in skip:
filename = self.texenv.get_template(template_name).filename continue
with open(filename, 'r') as template_file: variables.update(
content = template_file.read() self.get_template_variables(
match = re.search(regex, content) subtemplate,
if match: skip + templates
content = match.group('variables') )
variables.update(json.loads(content)) )
variables.update(current)
return variables return variables
def get_templates(self, template): def parse_template(self, template):
'''Recursively get a set of all the templates used """Return (variables, templates).
by a particular template.
''' Argument:
with open(template.filename, 'r') as template_file: - template: name of the template to parse.
content = template_file.readlines()
new_templates = list(find_templates(self.texenv.parse(content))) Return values:
all_templates = set(new_templates) - variables: a dictionary of variables contained in 'template', NOT
if len(new_templates) > 0: recursively (included templates are not parsed).
for new_template_name in new_templates: - templates: list of included temlates, NOT recursively.
new_template = self.texenv.get_template(new_template_name) """
# union of the sets
all_templates |= self.get_templates(new_template) subvariables = {}
return all_templates with codecs.open(
self.texenv.get_template(template).filename,
'r',
'utf-8'
) as template_file:
content = template_file.read()
subtemplates = list(find_templates(self.texenv.parse(content)))
match = re.findall(VARIABLE_REGEXP, content)
if match:
for var in match:
subvariables.update(json.loads(var))
return (subvariables, subtemplates)
def render_tex(self, output, context): def render_tex(self, output, context):
'''Render a template into a .tex file '''Render a template into a .tex file

Loading…
Cancel
Save