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.

120 lines
3.9 KiB

#!/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])