|
|
|
#!/usr/bin/env python
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
|
|
import glob
|
|
|
|
import jinja2
|
|
|
|
import logging
|
|
|
|
import os
|
|
|
|
|
|
|
|
from songbook_core.content import Content, process_content, ContentError
|
|
|
|
from songbook_core.files import recursive_find
|
|
|
|
from songbook_core.songs import Song
|
|
|
|
|
|
|
|
LOGGER = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
class SongRenderer(Content, Song):
|
|
|
|
def begin_new_block(self, previous, __context):
|
|
|
|
return not isinstance(previous, SongRenderer)
|
|
|
|
|
|
|
|
def begin_block(self, context):
|
|
|
|
indexes = context.resolve("indexes")
|
|
|
|
if isinstance(indexes, jinja2.runtime.Undefined):
|
|
|
|
indexes = ""
|
|
|
|
return r'\begin{songs}{%s}' % indexes
|
|
|
|
|
|
|
|
def end_block(self, __context):
|
|
|
|
return r'\end{songs}'
|
|
|
|
|
|
|
|
def render(self, context):
|
|
|
|
outdir = os.path.dirname(context['filename'])
|
|
|
|
if os.path.abspath(self.path).startswith(os.path.abspath(outdir)):
|
|
|
|
path = os.path.relpath(self.path, outdir)
|
|
|
|
else:
|
|
|
|
path = os.path.abspath(self.path)
|
|
|
|
return r'\input{{{}}}'.format(path)
|
|
|
|
|
|
|
|
def parse(keyword, argument, contentlist, config):
|
|
|
|
if 'languages' not in config:
|
|
|
|
config['_languages'] = set()
|
|
|
|
songlist = []
|
|
|
|
for songdir in config['_songdir']:
|
|
|
|
if contentlist:
|
|
|
|
break
|
|
|
|
contentlist = [
|
|
|
|
os.path.relpath(filename, songdir)
|
|
|
|
for filename
|
|
|
|
in recursive_find(songdir, "*.sg")
|
|
|
|
]
|
|
|
|
for elem in contentlist:
|
|
|
|
before = len(songlist)
|
|
|
|
for songdir in config['_songdir']:
|
|
|
|
for filename in glob.iglob(os.path.join(songdir, elem)):
|
|
|
|
LOGGER.debug('Parsing file "{}"…'.format(filename))
|
|
|
|
song = SongRenderer(filename, config)
|
|
|
|
songlist.append(song)
|
|
|
|
config["_languages"].update(song.languages)
|
|
|
|
if len(songlist) > before:
|
|
|
|
break
|
|
|
|
if len(songlist) == before:
|
|
|
|
# No songs were added
|
|
|
|
LOGGER.warning(
|
|
|
|
"Expression '{}' did not match any file".format(elem)
|
|
|
|
)
|
|
|
|
return songlist
|
|
|
|
|
|
|
|
|
|
|
|
CONTENT_PLUGINS = {'song': parse}
|
|
|
|
|
|
|
|
|
|
|
|
class OnlySongsError(ContentError):
|
|
|
|
def __init__(self, not_songs):
|
|
|
|
self.not_songs = not_songs
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
return "Only songs are allowed, and the following items are not:" + str(not_songs)
|
|
|
|
|
|
|
|
def process_songs(content, config = None):
|
|
|
|
contentlist = process_content(content, config)
|
|
|
|
not_songs = [item for item in contentlist if not isinstance(item, SongRenderer)]
|
|
|
|
if not_songs:
|
|
|
|
raise OnlySongsError(not_songs)
|
|
|
|
return contentlist
|