diff --git a/songbook_core/build.py b/songbook_core/build.py index bd50d0a3..c81affad 100644 --- a/songbook_core/build.py +++ b/songbook_core/build.py @@ -14,7 +14,7 @@ from songbook_core import __DATADIR__ from songbook_core import errors from songbook_core.files import recursive_find from songbook_core.index import process_sxd -from songbook_core.songs import Song, SongsList +from songbook_core.songs import Song, SongbookContent from songbook_core.templates import TexRenderer LOGGER = logging.getLogger(__name__) @@ -95,17 +95,26 @@ class Songbook(object): # Compute song list if self.config['content'] is None: - self.config['content'] = [ + self.config['content'] = [( + "song", os.path.relpath( filename, os.path.join(self.config['datadir'], 'songs'), - ) + )) for filename in recursive_find( os.path.join(self.config['datadir'], 'songs'), '*.sg', ) ] + else: + content = self.config["content"] + self.config["content"] = [] + for elem in content: + if isinstance(elem, unicode): + self.config["content"].append(("song", elem)) + else: + self.config["content"].append((elem[0], elem[1])) # Ensure self.config['authwords'] contains all entries for (key, value) in DEFAULT_AUTHWORDS.items(): @@ -113,9 +122,9 @@ class Songbook(object): self.config['authwords'][key] = value def _parse_songs(self): - """Parse songs included in songbook.""" - self.songslist = SongsList(self.config['datadir']) - self.songslist.append_list(self.config['content']) + """Parse content included in songbook.""" + self.contentlist = SongbookContent(self.config['datadir']) + self.contentlist.append_list(self.config['content']) def write_tex(self, output): """Build the '.tex' file corresponding to self. @@ -133,7 +142,7 @@ class Songbook(object): context = renderer.get_variables() context.update(self.config) context['titleprefixkeys'] = ["after", "sep", "ignore"] - context['songlist'] = self.songslist + context['content'] = self.contentlist context['filename'] = output.name[:-4] self._set_songs_default(context) diff --git a/songbook_core/data/examples/example.sb b/songbook_core/data/examples/example.sb index 327ed801..a003440e 100644 --- a/songbook_core/data/examples/example.sb +++ b/songbook_core/data/examples/example.sb @@ -10,5 +10,12 @@ "authwords" : { "sep" : ["and", "et"] }, - "datadir" : "." -} + "datadir" : ".", + "content" : [["section", "Traditional"], + "chevaliers_de_la_table_ronde.sg", + "greensleeves.sg", + "vent_frais.sg", + ["section", "Example"], + "example-fr.sg", + "example-en.sg"] +} \ No newline at end of file diff --git a/songbook_core/data/templates/songs.tex b/songbook_core/data/templates/songs.tex index b630a919..8ae2bf26 100644 --- a/songbook_core/data/templates/songs.tex +++ b/songbook_core/data/templates/songs.tex @@ -25,7 +25,7 @@ (( super() )) - (* for lang in songlist.languages() *) + (* for lang in content.languages() *) \PassOptionsToPackage{((lang))}{babel} (* endfor *) \usepackage[((lang))]{babel} @@ -38,8 +38,14 @@ \addcontentsline{toc}{section}{\songlistname} \begin{songs}{((indexes|default('')))} - (* for song in songlist.songs *) - \input{((song.path))} + (* for type, elem in content.content *) + (* if type=="song" *) + \input{((elem.path))} + (* elif type=="section" *) + \end{songs} + \songsection{((elem))} + \begin{songs}{((indexes|default('')))} + (* endif *) (* endfor *) \end{songs} (* endblock *) diff --git a/songbook_core/songs.py b/songbook_core/songs.py index ccb9c7fc..19d732af 100644 --- a/songbook_core/songs.py +++ b/songbook_core/songs.py @@ -87,16 +87,16 @@ def unprefixed_title(title, prefixes): return title -class SongsList(object): +class SongbookContent(object): """Manipulation et traitement de liste de chansons""" def __init__(self, library): self._songdir = os.path.join(library, 'songs') - # Liste triée des chansons - self.songs = [] + # Sorted list of the content + self.content = [] - def append(self, filename): + def append_song(self, filename): """Ajout d'une chanson à la liste Effets de bord : analyse syntaxique plus ou moins sommaire du fichier @@ -104,36 +104,36 @@ class SongsList(object): album, etc.). """ LOGGER.debug('Parsing file "{}"…'.format(filename)) - # Exécution de PlasTeX + # Data extraction from the song with plastex data = parsetex(filename) - song = Song(filename, 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) + self.content.append(("song", song)) + + def append(self, type, value): + """ Append a generic element to the content list""" + self.content.append((type, value)) - def append_list(self, filelist): + def append_list(self, contentlist): """Ajoute une liste de chansons à la liste L'argument est une liste de chaînes, représentant des noms de fichiers sous la forme d'expressions régulières destinées à être analysées avec le module glob. """ - for regexp in filelist: - before = len(self.songs) - for filename in glob.iglob(os.path.join(self._songdir, regexp)): - self.append(filename) - if len(self.songs) == before: - # No songs were added - LOGGER.warning( - "Expression '{}' did not match any file".format(regexp) - ) + for type, elem in contentlist: + if type == "song": + # Add all the songs matching the regex + before = len(self.content) + for filename in glob.iglob(os.path.join(self._songdir, elem)): + self.append_song(filename) + if len(self.content) == before: + # No songs were added + LOGGER.warning( + "Expression '{}' did not match any file".format(regexp) + ) + else: + self.append(type, elem) def languages(self): """Renvoie la liste des langues utilisées par les chansons""" - return set().union(*[set(song.languages) for song in self.songs]) + return set().union(*[set(song.languages) for type, song in self.content if type=="song"])