Browse Source

[WIP] TeX generation works; TeX compilation does not

pull/213/head
Louis 9 years ago
parent
commit
173c0cafc3
  1. 4
      patacrep/data/templates/songbook/default.tex
  2. 6
      patacrep/data/templates/songbook/patacrep.tex
  3. 2
      patacrep/data/templates/songs/chordpro/chordpro/song_header
  4. 2
      patacrep/data/templates/songs/chordpro/latex/song
  5. 31
      patacrep/songs/chordpro/__init__.py
  6. 52
      patacrep/templates.py
  7. 9
      test/test_book/special.tex.control
  8. 4
      test/test_book/special.yaml

4
patacrep/data/templates/songbook/default.tex

@ -66,8 +66,8 @@ description:
\usepackage{chords} \usepackage{chords}
\title{(( template_var.title ))} \title{(( template_var.title|escape_specials() ))}
\author{(( template_var.author ))} \author{(( template_var.author|escape_specials() ))}
\newindex{titleidx}{((filename))_title} \newindex{titleidx}{((filename))_title}
\newauthorindex{authidx}{((filename))_auth} \newauthorindex{authidx}{((filename))_auth}

6
patacrep/data/templates/songbook/patacrep.tex

@ -138,12 +138,12 @@ description:
]{hyperref} ]{hyperref}
\subtitle{(( template_var.subtitle ))} \subtitle{(( template_var.subtitle|escape_specials ))}
(* if template_var.version -*) (* if template_var.version -*)
\version{(( template_var.version ))} \version{(( template_var.version ))}
(* endif *) (* endif *)
\mail{(( template_var.email ))} \mail{(( template_var.email|escape_url ))}
\web{(( template_var.url ))} \web{(( template_var.url|escape_url ))}
\picture{(( template_var.picture ))} \picture{(( template_var.picture ))}
\picturecopyright{(( template_var.picturecopyright ))} \picturecopyright{(( template_var.picturecopyright ))}
\footer{(( template_var.footer ))} \footer{(( template_var.footer ))}

2
patacrep/data/templates/songs/chordpro/chordpro/song_header

@ -34,7 +34,7 @@
(* endfor *) (* endfor *)
(*- if 'url' in metadata -*) (*- if 'url' in metadata -*)
{url: (( metadata.url ))} {url: (( metadata.url|escape_url ))}
(* endif -*) (* endif -*)
(*- for chord in metadata['define'] *) (*- for chord in metadata['define'] *)

2
patacrep/data/templates/songs/chordpro/latex/song

@ -28,7 +28,7 @@
(* endif *) (* endif *)
(* endfor *) (* endfor *)
(* if 'url' in metadata *) (* if 'url' in metadata *)
url={(( metadata.url|escape_specials('%#') ))}, url={(( metadata.url|escape_url ))},
(* endif *) (* endif *)
(* if 'cover' in metadata *) (* if 'cover' in metadata *)
(* block cover *) (* block cover *)

31
patacrep/songs/chordpro/__init__.py

@ -3,6 +3,7 @@
import logging import logging
import operator import operator
import os import os
import urllib
from jinja2 import Environment, FileSystemLoader, ChoiceLoader from jinja2 import Environment, FileSystemLoader, ChoiceLoader
from jinja2 import contextfunction from jinja2 import contextfunction
@ -31,6 +32,12 @@ class ChordproSong(Song):
output_language = None output_language = None
_translation_map = {} _translation_map = {}
_translation_map_url = None
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if self._translation_map_url is None:
self._translation_map_url = self._translation_map
def _parse(self): def _parse(self):
"""Parse content, and return the dictionary of song data.""" """Parse content, and return the dictionary of song data."""
@ -52,6 +59,7 @@ class ChordproSong(Song):
'search_image': self.search_image, 'search_image': self.search_image,
'search_partition': self.search_partition, 'search_partition': self.search_partition,
'escape_specials': self._escape_specials, 'escape_specials': self._escape_specials,
'escape_url': self._escape_url,
}) })
return filters return filters
@ -86,13 +94,20 @@ class ChordproSong(Song):
context.vars['content'] = content context.vars['content'] = content
return context.environment.get_template(content.template()).render(context) return context.environment.get_template(content.template()).render(context)
def _escape_specials(self, content, chars): def _escape_specials(self, content, chars=None, *, translation_map=None):
if translation_map is None:
translation_map = self._translation_map
if chars is None:
chars = translation_map.keys()
return str(content).translate(str.maketrans({ return str(content).translate(str.maketrans({
key: value key: value
for key, value in self._translation_map.items() for key, value in translation_map.items()
if key in chars if key in chars
})) }))
def _escape_url(self, content):
return self._escape_specials(content, translation_map=self._translation_map_url)
class Chordpro2HtmlSong(ChordproSong): class Chordpro2HtmlSong(ChordproSong):
"""Render chordpro song to html code""" """Render chordpro song to html code"""
@ -125,6 +140,13 @@ class Chordpro2LatexSong(ChordproSong):
'%': r'\%', '%': r'\%',
'_': r'\_', '_': r'\_',
} }
_translation_map_url = {
" ": urllib.parse.quote(" "),
"{": urllib.parse.quote("{"),
"}": urllib.parse.quote("}"),
'%': r'\%',
'#': r'\#',
}
def search_file(self, filename, extensions=None, *, datadirs=None): def search_file(self, filename, extensions=None, *, datadirs=None):
_datadir, filename, _extension = self.search_datadir_file( _datadir, filename, _extension = self.search_datadir_file(
@ -191,6 +213,11 @@ class Chordpro2ChordproSong(ChordproSong):
'\\': '\\\\', '\\': '\\\\',
'#': r'\#', '#': r'\#',
} }
_translation_map_url = {
'{': r'\{',
'}': r'\}',
'\\': '\\\\',
}
def search_file(self, filename, extensions=None, *, datadirs=None): def search_file(self, filename, extensions=None, *, datadirs=None):
# pylint: disable=unused-variable # pylint: disable=unused-variable

52
patacrep/templates.py

@ -2,6 +2,7 @@
import logging import logging
import re import re
import urllib
import yaml import yaml
@ -16,15 +17,6 @@ import patacrep.encoding
LOGGER = logging.getLogger(__name__) LOGGER = logging.getLogger(__name__)
_LATEX_SUBS = (
(re.compile(r'\\'), r'\\textbackslash'),
(re.compile(r'([{}_#%&$])'), r'\\\1'),
(re.compile(r'~'), r'\~{}'),
(re.compile(r'\^'), r'\^{}'),
(re.compile(r'"'), r"''"),
(re.compile(r'\.\.\.+'), r'\\ldots'),
)
_VARIABLE_REGEXP = re.compile( _VARIABLE_REGEXP = re.compile(
r""" r"""
\(\*-?\ *variables\ *\*\) # Match (* variables *) or (*- variables *) \(\*-?\ *variables\ *\*\) # Match (* variables *) or (*- variables *)
@ -46,15 +38,45 @@ _VARIABLE_REGEXP = re.compile(
""", """,
re.VERBOSE|re.DOTALL) re.VERBOSE|re.DOTALL)
def _escape_tex(value): TRANSLATION_MAP = {
'{': r'\{',
'}': r'\}',
'\\': r'\textbackslash{}',
'^': r'\textasciicircum{}',
'~': r'\textasciitilde{}',
'#': r'\#',
'&': r'\&',
'$': r'\$',
'%': r'\%',
'_': r'\_',
}
TRANSLATION_MAP_URL = {
' ': '\\' + urllib.parse.quote(" "),
'{': '\\' + urllib.parse.quote("{"),
'}': '\\' + urllib.parse.quote("}"),
'%': '\\%',
'\\': '\\\\',
}
def _escape_specials(text, *, chars=None, translation_map=None):
'''Escape TeX special characters''' '''Escape TeX special characters'''
newval = value if translation_map is None:
for pattern, replacement in _LATEX_SUBS: translation_map = TRANSLATION_MAP
newval = pattern.sub(replacement, newval) if chars is None:
return newval chars = translation_map.keys()
return str(text).translate(str.maketrans({
key: value
for key, value in translation_map.items()
if key in chars
}))
def _escape_url(text):
"""Escape TeX special characters, in url."""
return _escape_specials(text, translation_map=TRANSLATION_MAP_URL)
DEFAULT_FILTERS = { DEFAULT_FILTERS = {
"escape_tex": _escape_tex, "escape_specials": _escape_specials,
"escape_url": _escape_url,
"iter_datadirs": files.iter_datadirs, "iter_datadirs": files.iter_datadirs,
"path2posix": files.path2posix, "path2posix": files.path2posix,
} }

9
test/test_book/special.tex.control

@ -67,8 +67,8 @@ guitar,
\usepackage{chords} \usepackage{chords}
\title{\& \% \$ \# \_ \} \{ \textasciitilde{} \textasciicircum{} \textbackslash{} } \title{\& \% \$ \# \_ \} \{ \textasciitilde{} \textasciicircum{} \textbackslash{}}
\author{\& \% \$ \# \_ \} \{ \textasciitilde{} \textasciicircum{} \textbackslash{} } \author{\& \% \$ \# \_ \} \{ \textasciitilde{} \textasciicircum{} \textbackslash{}}
\newindex{titleidx}{special_title} \newindex{titleidx}{special_title}
\newauthorindex{authidx}{special_auth} \newauthorindex{authidx}{special_auth}
@ -101,9 +101,8 @@ guitar,
\subtitle{\& \% \$ \# \_ \} \{ \textasciitilde{} \textasciicircum{} \textbackslash{}} \subtitle{\& \% \$ \# \_ \} \{ \textasciitilde{} \textasciicircum{} \textbackslash{}}
\mail{http://\%25\%20\%26\%24\%5C\%23_\%7E\%5E\%7B\%7D} TODO Do not use encoded chars (%24, and so on). It is eventually a bad idea. Or as least as possible. \mail{foo@\\\%&$#_~^\%20\%7B\%7D}
\web{http://\%25\%20\%26\%24\%5C\%23_\%7E\%5E\%7B\%7D} TODO Idem \web{http://\\\%&$#_~^\%20\%7B\%7D}
\picture{img/treble_a} \picture{img/treble_a}
\picturecopyright{Dbolton \url{http://commons.wikimedia.org/wiki/User:Dbolton}} \picturecopyright{Dbolton \url{http://commons.wikimedia.org/wiki/User:Dbolton}}
\footer{Generated using Songbook (\url{http://www.patacrep.com})} \footer{Generated using Songbook (\url{http://www.patacrep.com})}

4
test/test_book/special.yaml

@ -8,7 +8,7 @@ template:
author: "& % $ # _ } { ~ ^ \\" author: "& % $ # _ } { ~ ^ \\"
patacrep.tex: patacrep.tex:
subtitle: "& % $ # _ } { ~ ^ \\" subtitle: "& % $ # _ } { ~ ^ \\"
url: "http://% &$\\#_~^{}" url: "http://\\%&$#_~^ {}"
email: "% &$\\#_~^{}" email: "foo@\\%&$#_~^ {}"
picture: "img/treble_a" picture: "img/treble_a"

Loading…
Cancel
Save