Browse Source

Merge pull request #1 from paternal/next

Correction du bug de PlasTeX et réorganisation
pull/20/head
Luthaf 11 years ago
parent
commit
d98c9d92f2
  1. 21
      song.py
  2. 335
      songbook.py
  3. 0
      songbook/__init__.py
  4. 13
      songbook/authors.py
  5. 191
      songbook/build.py
  6. 14
      songbook/files.py
  7. 8
      songbook/index.py
  8. 0
      songbook/plastex-patchedbabel.py
  9. 0
      songbook/plastex-songs.py
  10. 20
      songbook/plastex.py
  11. 119
      songbook/songs.py
  12. 157
      songbook/tex.py

21
song.py

@ -1,21 +0,0 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
import re
reTitle = re.compile('(?<=beginsong\\{)(.(?<!\\}]))+')
reArtist = re.compile('(?<=by=)(.(?<![,\\]\\}]))+')
reAlbum = re.compile('(?<=album=)(.(?<![,\\]\\}]))+')
#reLilypond = re.compile('(?<=album=)(.(?<![,\\]\\}]))+')
class Song:
def __init__(self, title, artist, album, path, isLilypond):
self.title = title
self.artist = artist
self.album = album
self.path = path
self.isLilypond = isLilypond
def __repr__(self):
return repr((self.title, self.artist, self.album, self.path, self.isLilypond))

335
songbook.py

@ -2,316 +2,14 @@
# -*- coding: utf-8 -*-
#
import getopt, sys
import os.path
import locale
import platform
import shutil
import json
import glob
import re
from subprocess import call
from tools import recursiveFind, processauthors
from index import *
from unidecode import unidecode
from utils.plastex import parsetex
class Song:
#: Ordre de tri
sort = []
#: Préfixes à ignorer pour le tri par titres
prefixes = []
#: Dictionnaire des options pour le traitement des auteurs
authwords = {"after": [], "ignore": [], "sep": []}
def __init__(self, path, languages, titles, args):
self.titles = titles
self.normalized_titles = [locale.strxfrm(unprefixed(unidecode(unicode(title, "utf-8")), self.prefixes)) for title in titles]
self.args = args
self.path = path
self.languages = languages
if "by" in self.args.keys():
self.normalized_authors = [
locale.strxfrm(author)
for author
in processauthors(self.args["by"], **self.authwords)
]
else:
self.normalized_authors = []
def __repr__(self):
return repr((self.titles, self.args, self.path))
def __cmp__(self, other):
if not isinstance(other, Song):
return NotImplemented
for key in self.sort:
if key == "@title":
self_key = self.normalized_titles
other_key = other.normalized_titles
elif key == "@path":
self_key = locale.strxfrm(self.path)
other_key = locale.strxfrm(other.path)
elif key == "by":
self_key = self.normalized_authors
other_key = other.normalized_authors
else:
self_key = locale.strxfrm(self.args.get(key, ""))
other_key = locale.strxfrm(other.args.get(key, ""))
if self_key < other_key:
return -1
elif self_key > other_key:
return 1
return 0
def matchRegexp(reg, iterable):
return [ m.group(1) for m in (reg.match(l) for l in iterable) if m ]
def unprefixed(title, prefixes):
"""Remove the first prefix of the list in the beginning of title (if any).
"""
for prefix in prefixes:
match = re.compile(r"^(%s)\b\s*(.*)$" % prefix).match(title)
if match:
return match.group(2)
return title
class SongsList:
"""Manipulation et traitement de liste de chansons"""
def __init__(self, library, language):
self._library = library
self._language = language
# Liste triée des chansons
self.songs = []
def append(self, filename):
"""Ajout d'une chanson à la liste
Effets de bord : analyse syntaxique plus ou moins sommaire du fichier
pour en extraire et traiter certaines information (titre, langue,
album, etc.).
"""
path = os.path.join(self._library, 'songs', filename)
# Exécution de PlasTeX
data = parsetex(path)
song = Song(path, data['languages'], data['titles'], data['args'])
low, high = 0, len(self.songs)
while low != high:
middle = (low + high) / 2
if song < self.songs[middle]:
high = middle
else:
low = middle + 1
self.songs.insert(low, song)
def append_list(self, filelist):
"""Ajoute une liste de chansons à la liste
L'argument est une liste de chaînes, représentant des noms de fichiers.
"""
for filename in filelist:
self.append(filename)
def latex(self):
"""Renvoie le code LaTeX nécessaire pour intégrer la liste de chansons.
"""
result = [ '\\input{{{0}}}'.format(song.path.replace("\\","/").strip()) for song in self.songs]
result.append('\\selectlanguage{%s}' % self._language)
return '\n'.join(result)
def languages(self):
"""Renvoie la liste des langues utilisées par les chansons"""
return set().union(*[set(song.languages) for song in self.songs])
def parseTemplate(template):
embeddedJsonPattern = re.compile(r"^%%:")
f = open(template)
code = [ line[3:-1] for line in f if embeddedJsonPattern.match(line) ]
f.close()
data = json.loads(''.join(code))
parameters = dict()
for param in data:
parameters[param["name"]] = param
return parameters
def toValue(parameter, data):
if "type" not in parameter:
return data
elif parameter["type"] == "stringlist":
if "join" in parameter:
joinText = parameter["join"]
else:
joinText = ''
return joinText.join(data)
elif parameter["type"] == "color":
return data[1:]
elif parameter["type"] == "font":
return data+'pt'
elif parameter["type"] == "enum":
return data
elif parameter["type"] == "file":
return data
elif parameter["type"] == "flag":
if "join" in parameter:
joinText = parameter["join"]
else:
joinText = ''
return joinText.join(data)
def formatDeclaration(name, parameter):
value = ""
if "default" in parameter:
value = parameter["default"]
return '\\def\\set@{name}#1{{\\def\\get{name}{{#1}}}}\n'.format(name=name) + formatDefinition(name, toValue(parameter, value))
from songbook.build import buildsongbook
def formatDefinition(name, value):
return '\\set@{name}{{{value}}}\n'.format(name=name, value=value)
def makeTexFile(sb, library, output):
name = output[:-4]
# default value
template = "patacrep.tmpl"
songs = []
prefixes_tex = ""
prefixes = []
authwords_tex = ""
authwords = {"after": ["by"], "ignore": ["unknown"], "sep": ["and"]}
# parse the songbook data
if "template" in sb:
template = sb["template"]
del sb["template"]
if "songs" in sb:
songs = sb["songs"]
del sb["songs"]
if "titleprefixwords" in sb:
prefixes = sb["titleprefixwords"]
for prefix in sb["titleprefixwords"]:
prefixes_tex += "\\titleprefixword{%s}\n" % prefix
sb["titleprefixwords"] = prefixes_tex
if "authwords" in sb:
# Populating default value
for key in ["after", "sep", "ignore"]:
if key not in sb["authwords"]:
sb["authwords"][key] = authwords[key]
# Processing authwords values
authwords = sb["authwords"]
for key in ["after", "sep", "ignore"]:
for word in authwords[key]:
if key == "after":
authwords_tex += "\\auth%sword{%s}\n" % ("by", word)
else:
authwords_tex += "\\auth%sword{%s}\n" % (key, word)
sb["authwords"] = authwords_tex
if "after" in authwords:
authwords["after"] = [re.compile(r"^.*%s\b(.*)" % after) for after in authwords["after"]]
if "sep" in authwords:
authwords["sep"] = [" %s" % sep for sep in authwords["sep"]] + [","]
authwords["sep"] = [re.compile(r"^(.*)%s (.*)$" % sep) for sep in authwords["sep"] ]
if "lang" not in sb:
sb["lang"] = "french"
if "sort" in sb:
sort = sb["sort"]
del sb["sort"]
else:
sort = [u"by", u"album", u"@title"]
Song.sort = sort
Song.prefixes = prefixes
Song.authwords = authwords
parameters = parseTemplate("templates/"+template)
# compute songslist
if songs == "all":
songs = map(lambda x: x[len(library) + 6:], recursiveFind(os.path.join(library, 'songs'), '*.sg'))
songslist = SongsList(library, sb["lang"])
songslist.append_list(songs)
sb["languages"] = ",".join(songslist.languages())
# output relevant fields
out = open(output, 'w')
out.write('%% This file has been automatically generated, do not edit!\n')
out.write('\\makeatletter\n')
# output automatic parameters
out.write(formatDeclaration("name", {"default":name}))
out.write(formatDeclaration("songslist", {"type":"stringlist"}))
# output template parameter command
for name, parameter in parameters.iteritems():
out.write(formatDeclaration(name, parameter))
# output template parameter values
for name, value in sb.iteritems():
if name in parameters:
out.write(formatDefinition(name, toValue(parameters[name],value)))
if len(songs) > 0:
out.write(formatDefinition('songslist', songslist.latex()))
out.write('\\makeatother\n')
# output template
commentPattern = re.compile(r"^\s*%")
f = open("templates/"+template)
content = [ line for line in f if not commentPattern.match(line) ]
for index, line in enumerate(content):
if re.compile("getLibraryImgDirectory").search(line):
line = line.replace("\\getLibraryImgDirectory", library + "img/")
content[index] = line
if re.compile("getLibraryLilypondDirectory").search(line):
line = line.replace("\\getLibraryLilypondDirectory", library + "lilypond/")
content[index] = line
f.close()
out.write(''.join(content))
out.close()
def makeDepend(sb, library, output):
name = output[:-2]
indexPattern = re.compile(r"^[^%]*\\(?:newauthor|new)index\{.*\}\{(.*?)\}")
lilypondPattern = re.compile(r"^[^%]*\\(?:lilypond)\{(.*?)\}")
# check for deps (in sb data)
deps = [];
if sb["songs"] == "all":
deps += recursiveFind(os.path.join(library, 'songs'), '*.sg')
else:
deps += map(lambda x: library + "songs/" + x, sb["songs"])
# check for lilypond deps (in songs data) if necessary
lilypond = []
if "bookoptions" in sb and "lilypond" in sb["bookoptions"]:
for filename in deps:
tmpl = open(filename)
lilypond += matchRegexp(lilypondPattern, tmpl)
tmpl.close()
# check for index (in template file)
if "template" in sb:
filename = sb["template"]
else:
filename = "patacrep.tmpl"
tmpl = open("templates/"+filename)
idx = map(lambda x: x.replace("\getname", name), matchRegexp(indexPattern, tmpl))
tmpl.close()
import getopt
import json
import locale
import os.path
import sys
# write .d file
out = open(output, 'w')
out.write('{0} {1} : {2}\n'.format(output, name+".tex", ' '.join(deps)))
out.write('{0} : {1}\n'.format(name+".pdf", ' '.join(map(lambda x: x+".sbx",idx)+map(lambda x: library+"lilypond/"+x+".pdf", lilypond))))
out.write('\t$(LATEX) {0}\n'.format(name+".tex"))
out.write('{0} : {1}\n'.format(' '.join(map(lambda x: x+".sxd",idx)), name+".aux"))
out.close()
def usage():
print "No usage information yet."
@ -345,31 +43,12 @@ def main():
assert False, "unhandled option"
basename = os.path.basename(sbFile)[:-3]
texFile = basename + ".tex"
pdfFile = basename + ".pdf"
f = open(sbFile)
sb = json.load(f)
f.close()
# Make TeX file
makeTexFile(sb, library, texFile)
# First pdflatex pass
call(["pdflatex", texFile])
# Make index
sxdFiles = glob.glob("%s_*.sxd" % basename)
print sxdFiles
for sxdFile in sxdFiles:
print "processing " + sxdFile
idx = processSXD(sxdFile)
indexFile = open(sxdFile[:-3]+"sbx", "w")
indexFile.write(idx.entriesToStr().encode('utf8'))
indexFile.close()
# Second pdflatex pass
call(["pdflatex", texFile])
buildsongbook(sb, basename, library)
if __name__ == '__main__':
main()

0
songbook/__init__.py

13
tools.py → songbook/authors.py

@ -1,16 +1,5 @@
#!/usr/bin/python
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
import fnmatch
import os
def recursiveFind(root_directory, pattern):
matches = []
for root, dirnames, filenames in os.walk(root_directory):
for filename in fnmatch.filter(filenames, pattern):
matches.append(os.path.join(root, filename))
return matches
def split_author_names(string):
"""Split author between first and last name.

191
songbook/build.py

@ -0,0 +1,191 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from subprocess import call
import glob
import json
import os.path
import re
from songbook.files import recursiveFind
from songbook.index import processSXD
from songbook.songs import Song, SongsList
def parseTemplate(template):
embeddedJsonPattern = re.compile(r"^%%:")
f = open(template)
code = [ line[3:-1] for line in f if embeddedJsonPattern.match(line) ]
f.close()
data = json.loads(''.join(code))
parameters = dict()
for param in data:
parameters[param["name"]] = param
return parameters
def toValue(parameter, data):
if "type" not in parameter:
return data
elif parameter["type"] == "stringlist":
if "join" in parameter:
joinText = parameter["join"]
else:
joinText = ''
return joinText.join(data)
elif parameter["type"] == "color":
return data[1:]
elif parameter["type"] == "font":
return data+'pt'
elif parameter["type"] == "enum":
return data
elif parameter["type"] == "file":
return data
elif parameter["type"] == "flag":
if "join" in parameter:
joinText = parameter["join"]
else:
joinText = ''
return joinText.join(data)
def formatDeclaration(name, parameter):
value = ""
if "default" in parameter:
value = parameter["default"]
return '\\def\\set@{name}#1{{\\def\\get{name}{{#1}}}}\n'.format(name=name) + formatDefinition(name, toValue(parameter, value))
def formatDefinition(name, value):
return '\\set@{name}{{{value}}}\n'.format(name=name, value=value)
def makeTexFile(sb, library, output):
name = output[:-4]
# default value
template = "patacrep.tmpl"
songs = []
prefixes_tex = ""
prefixes = []
authwords_tex = ""
authwords = {"after": ["by"], "ignore": ["unknown"], "sep": ["and"]}
# parse the songbook data
if "template" in sb:
template = sb["template"]
del sb["template"]
if "songs" in sb:
songs = sb["songs"]
del sb["songs"]
if "titleprefixwords" in sb:
prefixes = sb["titleprefixwords"]
for prefix in sb["titleprefixwords"]:
prefixes_tex += "\\titleprefixword{%s}\n" % prefix
sb["titleprefixwords"] = prefixes_tex
if "authwords" in sb:
# Populating default value
for key in ["after", "sep", "ignore"]:
if key not in sb["authwords"]:
sb["authwords"][key] = authwords[key]
# Processing authwords values
authwords = sb["authwords"]
for key in ["after", "sep", "ignore"]:
for word in authwords[key]:
if key == "after":
authwords_tex += "\\auth%sword{%s}\n" % ("by", word)
else:
authwords_tex += "\\auth%sword{%s}\n" % (key, word)
sb["authwords"] = authwords_tex
if "after" in authwords:
authwords["after"] = [re.compile(r"^.*%s\b(.*)" % after) for after in authwords["after"]]
if "sep" in authwords:
authwords["sep"] = [" %s" % sep for sep in authwords["sep"]] + [","]
authwords["sep"] = [re.compile(r"^(.*)%s (.*)$" % sep) for sep in authwords["sep"] ]
if "lang" not in sb:
sb["lang"] = "french"
if "sort" in sb:
sort = sb["sort"]
del sb["sort"]
else:
sort = [u"by", u"album", u"@title"]
Song.sort = sort
Song.prefixes = prefixes
Song.authwords = authwords
parameters = parseTemplate("templates/"+template)
# compute songslist
if songs == "all":
songs = map(lambda x: x[len(library) + 6:], recursiveFind(os.path.join(library, 'songs'), '*.sg'))
songslist = SongsList(library, sb["lang"])
songslist.append_list(songs)
sb["languages"] = ",".join(songslist.languages())
# output relevant fields
out = open(output, 'w')
out.write('%% This file has been automatically generated, do not edit!\n')
out.write('\\makeatletter\n')
# output automatic parameters
out.write(formatDeclaration("name", {"default":name}))
out.write(formatDeclaration("songslist", {"type":"stringlist"}))
# output template parameter command
for name, parameter in parameters.iteritems():
out.write(formatDeclaration(name, parameter))
# output template parameter values
for name, value in sb.iteritems():
if name in parameters:
out.write(formatDefinition(name, toValue(parameters[name],value)))
if len(songs) > 0:
out.write(formatDefinition('songslist', songslist.latex()))
out.write('\\makeatother\n')
# output template
commentPattern = re.compile(r"^\s*%")
f = open("templates/"+template)
content = [ line for line in f if not commentPattern.match(line) ]
for index, line in enumerate(content):
if re.compile("getLibraryImgDirectory").search(line):
line = line.replace("\\getLibraryImgDirectory", library + "img/")
content[index] = line
if re.compile("getLibraryLilypondDirectory").search(line):
line = line.replace("\\getLibraryLilypondDirectory", library + "lilypond/")
content[index] = line
f.close()
out.write(''.join(content))
out.close()
def buildsongbook(sb, basename, library):
"""Build a songbook
Arguments:
- sb: Python representation of the .sb songbook configuration file.
- library: directory containing the "songs" directory, itself containing
songs.
- basename: basename of the songbook to be built.
"""
texFile = basename + ".tex"
pdfFile = basename + ".pdf"
# Make TeX file
makeTexFile(sb, library, texFile)
# First pdflatex pass
call(["pdflatex", texFile])
# Make index
sxdFiles = glob.glob("%s_*.sxd" % basename)
print sxdFiles
for sxdFile in sxdFiles:
print "processing " + sxdFile
idx = processSXD(sxdFile)
indexFile = open(sxdFile[:-3]+"sbx", "w")
indexFile.write(idx.entriesToStr().encode('utf8'))
indexFile.close()
# Second pdflatex pass
call(["pdflatex", texFile])

14
songbook/files.py

@ -0,0 +1,14 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
import fnmatch
import os
def recursiveFind(root_directory, pattern):
matches = []
for root, dirnames, filenames in os.walk(root_directory):
for filename in fnmatch.filter(filenames, pattern):
matches.append(os.path.join(root, filename))
return matches

8
index.py → songbook/index.py

@ -10,13 +10,13 @@
#
from unidecode import unidecode
import sys
import re
import locale
import re
import sys
import warnings
from tools import processauthors
from utils.plastex import simpleparse
from songbook.authors import processauthors
from songbook.plastex import simpleparse
# Pattern set to ignore latex command in title prefix
keywordPattern = re.compile(r"^%(\w+)\s?(.*)$")

0
utils/patchedbabel.py → songbook/plastex-patchedbabel.py

0
utils/songs.py → songbook/plastex-songs.py

20
utils/plastex.py → songbook/plastex.py

@ -4,9 +4,11 @@
from plasTeX.TeX import TeX
import codecs
import copy
import locale
import os
import sys
def simpleparse(text):
"""Parse a simple LaTeX string.
"""
@ -24,8 +26,8 @@ class SongParser:
tex.disableLogging()
tex.ownerDocument.context.loadBaseMacros()
sys.path.append(os.path.dirname(__file__))
tex.ownerDocument.context.loadPackage(tex, "patchedbabel")
tex.ownerDocument.context.loadPackage(tex, "songs")
tex.ownerDocument.context.loadPackage(tex, "plastex-patchedbabel")
tex.ownerDocument.context.loadPackage(tex, "plastex-songs")
sys.path.pop()
return tex
@ -45,9 +47,23 @@ def parsetex(filename):
- 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, with a patch.
# 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.setlocale(locale.LC_TIME, 'C')
# plasTeX patch END */
# Analyse syntaxique
doc = SongParser.parse(filename)
# /* BEGIN plasTeX patch
locale.setlocale(locale.LC_TIME, "%s.%s" % oldlocale)
# plasTeX patch END */
# Extraction des données
data = {
"languages": set(),

119
songbook/songs.py

@ -0,0 +1,119 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from unidecode import unidecode
import locale
import os.path
import re
from songbook.authors import processauthors
from songbook.plastex import parsetex
class Song:
#: Ordre de tri
sort = []
#: Préfixes à ignorer pour le tri par titres
prefixes = []
#: Dictionnaire des options pour le traitement des auteurs
authwords = {"after": [], "ignore": [], "sep": []}
def __init__(self, path, languages, titles, args):
self.titles = titles
self.normalized_titles = [locale.strxfrm(unprefixed_title(unidecode(unicode(title, "utf-8")), self.prefixes)) for title in titles]
self.args = args
self.path = path
self.languages = languages
if "by" in self.args.keys():
self.normalized_authors = [
locale.strxfrm(author)
for author
in processauthors(self.args["by"], **self.authwords)
]
else:
self.normalized_authors = []
def __repr__(self):
return repr((self.titles, self.args, self.path))
def __cmp__(self, other):
if not isinstance(other, Song):
return NotImplemented
for key in self.sort:
if key == "@title":
self_key = self.normalized_titles
other_key = other.normalized_titles
elif key == "@path":
self_key = locale.strxfrm(self.path)
other_key = locale.strxfrm(other.path)
elif key == "by":
self_key = self.normalized_authors
other_key = other.normalized_authors
else:
self_key = locale.strxfrm(self.args.get(key, ""))
other_key = locale.strxfrm(other.args.get(key, ""))
if self_key < other_key:
return -1
elif self_key > other_key:
return 1
return 0
def unprefixed_title(title, prefixes):
"""Remove the first prefix of the list in the beginning of title (if any).
"""
for prefix in prefixes:
match = re.compile(r"^(%s)\b\s*(.*)$" % prefix).match(title)
if match:
return match.group(2)
return title
class SongsList:
"""Manipulation et traitement de liste de chansons"""
def __init__(self, library, language):
self._library = library
self._language = language
# Liste triée des chansons
self.songs = []
def append(self, filename):
"""Ajout d'une chanson à la liste
Effets de bord : analyse syntaxique plus ou moins sommaire du fichier
pour en extraire et traiter certaines information (titre, langue,
album, etc.).
"""
path = os.path.join(self._library, 'songs', filename)
# Exécution de PlasTeX
data = parsetex(path)
song = Song(path, data['languages'], data['titles'], data['args'])
low, high = 0, len(self.songs)
while low != high:
middle = (low + high) / 2
if song < self.songs[middle]:
high = middle
else:
low = middle + 1
self.songs.insert(low, song)
def append_list(self, filelist):
"""Ajoute une liste de chansons à la liste
L'argument est une liste de chaînes, représentant des noms de fichiers.
"""
for filename in filelist:
self.append(filename)
def latex(self):
"""Renvoie le code LaTeX nécessaire pour intégrer la liste de chansons.
"""
result = [ '\\input{{{0}}}'.format(song.path.replace("\\","/").strip()) for song in self.songs]
result.append('\\selectlanguage{%s}' % self._language)
return '\n'.join(result)
def languages(self):
"""Renvoie la liste des langues utilisées par les chansons"""
return set().union(*[set(song.languages) for song in self.songs])

157
songbook/tex.py

@ -0,0 +1,157 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import json
import os.path
import re
from songbook.files import recursiveFind
from songbook.songs import Song, SongsList
def parseTemplate(template):
embeddedJsonPattern = re.compile(r"^%%:")
f = open(template)
code = [ line[3:-1] for line in f if embeddedJsonPattern.match(line) ]
f.close()
data = json.loads(''.join(code))
parameters = dict()
for param in data:
parameters[param["name"]] = param
return parameters
def toValue(parameter, data):
if "type" not in parameter:
return data
elif parameter["type"] == "stringlist":
if "join" in parameter:
joinText = parameter["join"]
else:
joinText = ''
return joinText.join(data)
elif parameter["type"] == "color":
return data[1:]
elif parameter["type"] == "font":
return data+'pt'
elif parameter["type"] == "enum":
return data
elif parameter["type"] == "file":
return data
elif parameter["type"] == "flag":
if "join" in parameter:
joinText = parameter["join"]
else:
joinText = ''
return joinText.join(data)
def formatDeclaration(name, parameter):
value = ""
if "default" in parameter:
value = parameter["default"]
return '\\def\\set@{name}#1{{\\def\\get{name}{{#1}}}}\n'.format(name=name) + formatDefinition(name, toValue(parameter, value))
def formatDefinition(name, value):
return '\\set@{name}{{{value}}}\n'.format(name=name, value=value)
def makeTexFile(sb, library, output):
name = output[:-4]
# default value
template = "patacrep.tmpl"
songs = []
prefixes_tex = ""
prefixes = []
authwords_tex = ""
authwords = {"after": ["by"], "ignore": ["unknown"], "sep": ["and"]}
# parse the songbook data
if "template" in sb:
template = sb["template"]
del sb["template"]
if "songs" in sb:
songs = sb["songs"]
del sb["songs"]
if "titleprefixwords" in sb:
prefixes = sb["titleprefixwords"]
for prefix in sb["titleprefixwords"]:
prefixes_tex += "\\titleprefixword{%s}\n" % prefix
sb["titleprefixwords"] = prefixes_tex
if "authwords" in sb:
# Populating default value
for key in ["after", "sep", "ignore"]:
if key not in sb["authwords"]:
sb["authwords"][key] = authwords[key]
# Processing authwords values
authwords = sb["authwords"]
for key in ["after", "sep", "ignore"]:
for word in authwords[key]:
if key == "after":
authwords_tex += "\\auth%sword{%s}\n" % ("by", word)
else:
authwords_tex += "\\auth%sword{%s}\n" % (key, word)
sb["authwords"] = authwords_tex
if "after" in authwords:
authwords["after"] = [re.compile(r"^.*%s\b(.*)" % after) for after in authwords["after"]]
if "sep" in authwords:
authwords["sep"] = [" %s" % sep for sep in authwords["sep"]] + [","]
authwords["sep"] = [re.compile(r"^(.*)%s (.*)$" % sep) for sep in authwords["sep"] ]
if "lang" not in sb:
sb["lang"] = "french"
if "sort" in sb:
sort = sb["sort"]
del sb["sort"]
else:
sort = [u"by", u"album", u"@title"]
Song.sort = sort
Song.prefixes = prefixes
Song.authwords = authwords
parameters = parseTemplate("templates/"+template)
# compute songslist
if songs == "all":
songs = map(lambda x: x[len(library) + 6:], recursiveFind(os.path.join(library, 'songs'), '*.sg'))
songslist = SongsList(library, sb["lang"])
songslist.append_list(songs)
sb["languages"] = ",".join(songslist.languages())
# output relevant fields
out = open(output, 'w')
out.write('%% This file has been automatically generated, do not edit!\n')
out.write('\\makeatletter\n')
# output automatic parameters
out.write(formatDeclaration("name", {"default":name}))
out.write(formatDeclaration("songslist", {"type":"stringlist"}))
# output template parameter command
for name, parameter in parameters.iteritems():
out.write(formatDeclaration(name, parameter))
# output template parameter values
for name, value in sb.iteritems():
if name in parameters:
out.write(formatDefinition(name, toValue(parameters[name],value)))
if len(songs) > 0:
out.write(formatDefinition('songslist', songslist.latex()))
out.write('\\makeatother\n')
# output template
commentPattern = re.compile(r"^\s*%")
f = open("templates/"+template)
content = [ line for line in f if not commentPattern.match(line) ]
for index, line in enumerate(content):
if re.compile("getLibraryImgDirectory").search(line):
line = line.replace("\\getLibraryImgDirectory", library + "img/")
content[index] = line
if re.compile("getLibraryLilypondDirectory").search(line):
line = line.replace("\\getLibraryLilypondDirectory", library + "lilypond/")
content[index] = line
f.close()
out.write(''.join(content))
out.close()
Loading…
Cancel
Save