Engine for LaTeX songbooks http://www.patacrep.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

105 lines
3.1 KiB

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""PlasTeX module to process song files."""
from plasTeX.TeX import TeX
from plasTeX.Base.LaTeX import Sentences
import codecs
import locale
import os
import sys
def process_unbr_spaces(node):
r"""Replace '~' and '\ ' in node by nodes that
will be rendered as unbreakable space.
Return node object for convenience.
"""
if (type(node) == Sentences.InterWordSpace or
(type(node) == Sentences.NoLineBreak and node.source == '~ ')):
node.unicode = unichr(160)
for child in node.childNodes:
process_unbr_spaces(child)
return node
def simpleparse(text):
"""Parse a simple LaTeX string.
"""
tex = TeX()
tex.input(text.decode('utf8'))
doc = tex.parse()
return process_unbr_spaces(doc.textContent)
class SongParser(object):
"""Analyseur syntaxique de fichiers .sg"""
def __init__(self):
pass
@staticmethod
def create_tex():
"""Create a TeX object, ready to parse a tex file."""
tex = TeX()
tex.disableLogging()
tex.ownerDocument.context.loadBaseMacros()
sys.path.append(os.path.dirname(__file__))
tex.ownerDocument.context.loadPackage(tex, "plastex_patchedbabel")
tex.ownerDocument.context.loadPackage(tex, "plastex_songs")
sys.path.pop()
return tex
@classmethod
def parse(cls, filename):
"""Parse a TeX file, and return its plasTeX representation."""
tex = cls.create_tex()
tex.input(codecs.open(filename, 'r+', 'utf-8', 'replace'))
return tex.parse()
def parsetex(filename):
r"""Analyse syntaxique d'un fichier .sg
Renvoie un dictionnaire contenant les métadonnées lues dans le fichier. Les
clefs sont :
- languages: l'ensemble des langages utilisés (recherche des
\selectlanguages{}) ;
- titles: la liste des titres ;
- args: le dictionnaire des paramètres passés à \beginsong.
"""
# /* BEGIN plasTeX patch
# The following lines, and another line a few lines later, are used to
# circumvent a plasTeX bug. It has been reported and corrected :
# https://github.com/tiarno/plastex/commit/8f4e5a385f3cb6a04d5863f731ce24a7e856f2a4
# To see if you can delete those lines, set your LC_TIME locale to French,
# during a month containing diacritics (e.g. Février), and run songbook. If
# no plasTeX bug appears, it is safe to remove those lines.
oldlocale = locale.getlocale(locale.LC_TIME)
locale.setlocale(locale.LC_TIME, 'C')
# plasTeX patch END */
# Analyse syntaxique
doc = SongParser.parse(filename)
# /* BEGIN plasTeX patch
if oldlocale[0] and oldlocale[1]:
locale.setlocale(locale.LC_TIME, "%s.%s" % oldlocale)
# plasTeX patch END */
# Extraction des données
data = {
"languages": set(),
}
for node in doc.allChildNodes:
if node.nodeName == "selectlanguage":
data["languages"].add(node.attributes['lang'])
if node.nodeName == "beginsong":
data["titles"] = node.attributes["titles"]
data["args"] = node.attributes["args"]
return data