|
|
|
#!/usr/bin/env python
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
|
|
from subprocess import call
|
|
|
|
import codecs
|
|
|
|
import glob
|
|
|
|
import json
|
|
|
|
import os.path
|
|
|
|
import re
|
|
|
|
import sys
|
|
|
|
|
|
|
|
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, output):
|
|
|
|
datadir = sb['datadir']
|
|
|
|
name = output[:-4]
|
|
|
|
template_dir = os.path.join(datadir, 'templates')
|
|
|
|
# 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(os.path.join(template_dir, template))
|
|
|
|
|
|
|
|
# compute songslist
|
|
|
|
if songs == "all":
|
|
|
|
songs = [
|
|
|
|
os.path.relpath(filename, os.path.join(datadir, 'songs'))
|
|
|
|
for filename
|
|
|
|
in recursiveFind(os.path.join(datadir, 'songs'), '*.sg')
|
|
|
|
]
|
|
|
|
songslist = SongsList(datadir, sb["lang"])
|
|
|
|
songslist.append_list(songs)
|
|
|
|
|
|
|
|
sb["languages"] = ",".join(songslist.languages())
|
|
|
|
|
|
|
|
# output relevant fields
|
|
|
|
out = codecs.open(output, 'w', 'utf-8')
|
|
|
|
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*%")
|
|
|
|
with codecs.open(os.path.join(template_dir, template), 'r', 'utf-8') as f:
|
|
|
|
content = [ line for line in f if not commentPattern.match(line) ]
|
|
|
|
|
|
|
|
for index, line in enumerate(content):
|
|
|
|
if re.compile("getDataImgDirectory").search(line):
|
|
|
|
if os.path.abspath(os.path.join(datadir, "img")).startswith(os.path.abspath(os.path.dirname(output))):
|
|
|
|
imgdir = os.path.relpath(os.path.join(datadir, "img"), os.path.dirname(output))
|
|
|
|
else:
|
|
|
|
imgdir = os.path.abspath(os.path.join(datadir, "img"))
|
|
|
|
line = line.replace("\\getDataImgDirectory", ' {%s/} ' % imgdir)
|
|
|
|
content[index] = line
|
|
|
|
|
|
|
|
out.write(u''.join(content))
|
|
|
|
out.close()
|
|
|
|
|
|
|
|
def buildsongbook(sb, basename):
|
|
|
|
"""Build a songbook
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
- sb: Python representation of the .sb songbook configuration file.
|
|
|
|
- basename: basename of the songbook to be built.
|
|
|
|
"""
|
|
|
|
|
|
|
|
texFile = basename + ".tex"
|
|
|
|
|
|
|
|
# Make TeX file
|
|
|
|
makeTexFile(sb, texFile)
|
|
|
|
|
|
|
|
if not os.environ.has_key('TEXINPUTS'):
|
|
|
|
os.environ['TEXINPUTS'] = ''
|
|
|
|
os.environ['TEXINPUTS'] += os.pathsep + os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'latex')
|
|
|
|
os.environ['TEXINPUTS'] += os.pathsep + os.path.join(sb['datadir'], 'latex')
|
|
|
|
|
|
|
|
# First pdflatex pass
|
|
|
|
if call(["pdflatex", "--shell-escape", texFile]):
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
# Make index
|
|
|
|
sxdFiles = glob.glob("%s_*.sxd" % basename)
|
|
|
|
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
|
|
|
|
if call(["pdflatex", "--shell-escape", texFile]):
|
|
|
|
sys.exit(1)
|