diff --git a/patacrep/songs/chordpro/__init__.py b/patacrep/songs/chordpro/__init__.py index 0df82d42..a7fd3e3b 100644 --- a/patacrep/songs/chordpro/__init__.py +++ b/patacrep/songs/chordpro/__init__.py @@ -14,7 +14,6 @@ from patacrep.songs.chordpro.syntax import parse_song from patacrep.songs.errors import FileNotFound, SongUnknownLanguage from patacrep.templates import Renderer from patacrep.latex import lang2babel, UnknownLanguage -from patacrep.files import path2posix LOGGER = logging.getLogger(__name__) @@ -22,6 +21,10 @@ def sort_directive_argument(directives): """Sort directives by their argument.""" return sorted(directives, key=operator.attrgetter("argument")) +DEFAULT_FILTERS = { + 'sortargs': sort_directive_argument, + } + class ChordproSong(Song): """Chordpro song parser""" # pylint: disable=abstract-method @@ -41,10 +44,14 @@ class ChordproSong(Song): 'song': song, } - @staticmethod - def _jinja2_filters(): + def _filters(self): """Return additional jinja2 filters.""" - return {} + filters = DEFAULT_FILTERS.copy() + filters.update({ + 'search_image': self.search_image, + 'search_partition': self.search_partition, + }) + return filters def render(self, template="song"): # pylint: disable=arguments-differ context = { @@ -59,11 +66,7 @@ class ChordproSong(Song): jinjaenv = Environment(loader=FileSystemLoader( self.iter_datadirs("templates", "songs", "chordpro", self.output_language) )) - jinjaenv.filters['search_image'] = self.search_image - jinjaenv.filters['search_partition'] = self.search_partition - jinjaenv.filters['sortargs'] = sort_directive_argument - jinjaenv.filters['path2posix'] = path2posix - jinjaenv.filters.update(self._jinja2_filters()) + jinjaenv.filters.update(self._filters()) try: return Renderer( @@ -132,10 +135,12 @@ class Chordpro2LatexSong(ChordproSong): LOGGER.warning(message) return None - def _jinja2_filters(self): - return { + def _filters(self): + parent = super()._filters() + parent.update({ 'lang2babel': self.lang2babel, - } + }) + return parent def lang2babel(self, lang): """Return the LaTeX babel code corresponding to `lang`. diff --git a/patacrep/templates.py b/patacrep/templates.py index ffef0b4a..9194cf7f 100644 --- a/patacrep/templates.py +++ b/patacrep/templates.py @@ -45,6 +45,18 @@ _VARIABLE_REGEXP = re.compile( """, re.VERBOSE|re.DOTALL) +def _escape_tex(value): + '''Escape TeX special characters''' + newval = value + for pattern, replacement in _LATEX_SUBS: + newval = pattern.sub(replacement, newval) + return newval + +DEFAULT_FILTERS = { + "escape_tex": _escape_tex, + "iter_datadirs": files.iter_datadirs, + "path2posix": files.path2posix, + } class VariablesExtension(Extension): """Extension to jinja2 to silently ignore variable block. @@ -62,14 +74,6 @@ class VariablesExtension(Extension): return nodes.Const("") # pylint: disable=no-value-for-parameter -def _escape_tex(value): - '''Escape TeX special characters''' - newval = value - for pattern, replacement in _LATEX_SUBS: - newval = pattern.sub(replacement, newval) - return newval - - class Renderer: """Render a template to a LaTeX file.""" # pylint: disable=too-few-public-methods @@ -85,22 +89,23 @@ class Renderer: self.jinjaenv.comment_start_string = '(% comment %)' self.jinjaenv.comment_end_string = '(% endcomment %)' self.jinjaenv.line_comment_prefix = '%!' - self.jinjaenv.filters['escape_tex'] = _escape_tex self.jinjaenv.trim_blocks = True self.jinjaenv.lstrip_blocks = True - self._fill_filters() - self.template = self.jinjaenv.get_template(template) - - def _fill_filters(self): - """Define some jinja2 filters, if not set yet.""" - for key, value in [ - ("path2posix", files.path2posix), - ("iter_datadirs", files.iter_datadirs), - ("lang2babel", self.lang2babel), - ]: + # Fill default filters + for key, value in self.filters().items(): if key not in self.jinjaenv.filters: self.jinjaenv.filters[key] = value + self.template = self.jinjaenv.get_template(template) + + def filters(self): + """Return a dictionary of jinja2 filters.""" + filters = DEFAULT_FILTERS.copy() + filters.update({ + "lang2babel": self.lang2babel, + }) + return filters + def lang2babel(self, lang): """Return the LaTeX babel code corresponding to `lang`.