diff --git a/patacrep/songs/__init__.py b/patacrep/songs/__init__.py index fbf02e36..b59883be 100644 --- a/patacrep/songs/__init__.py +++ b/patacrep/songs/__init__.py @@ -194,6 +194,58 @@ class Song: """ raise NotImplementedError() + def get_datadirs(self, subdir=None): + """Return an iterator of existing datadirs (with eventually a subdir) + """ + for directory in self.config['datadir']: + fullpath = os.path.join(directory, subdir) + if os.path.isdir(fullpath): + yield fullpath + + def search_file(self, filename, extensions=None, directories=None): + """Search for a file name. + + :param str filename: The name, as provided in the chordpro file (with or without extension). + :param list extensions: Possible extensions (with '.') + :param iterator directories: Other directories where to search for the file + The directory where the Song file is stored is added to the list. + + Returns None if nothing found. + """ + if extensions is None: + extensions = [''] + if directories is None: + directories = [] + + songdir = os.path.dirname(self.fullpath) + + for directory in [songdir] + list(directories): + for extension in extensions: + fullpath = os.path.join(directory, filename + extension) + if os.path.isfile(fullpath): + return fullpath + return None + + def search_image(self, filename): + """Search for an image file""" + datadir_img = self.get_datadirs('img') + filepath = self.search_file(filename, ['', '.jpg', '.png'], datadir_img) + return filepath if filepath else filename + + @property + def cover_filepath(self): + """Get the path to the cover file (or None if not found)""" + filename = str(self.data.get('cov', '')) + if not filename: + return None + datadir_img = self.get_datadirs('img') + return self.search_file(filename, ['', '.jpg', '.png'], datadir_img) + + def search_partition(self, filename): + """Search for a lilypond file""" + filepath = self.search_file(filename, ['', '.ly']) + return filepath if filepath else filename + def unprefixed_title(title, prefixes): """Remove the first prefix of the list in the beginning of title (if any). """ @@ -202,39 +254,3 @@ def unprefixed_title(title, prefixes): if match: return match.group(2) return title - -def search_image(image, chordprofile, config): - """Return the file name of an image, so that LaTeX will find it. - - :param str image: The name, as provided in the chordpro file. - :param str chordprofile: The name of the file including this image. - :param dict config: Songbook configuration dictionary. - - The image can be: - - - in the same directory as the including song file; - - in the same directory as the main LaTeX file; - - in some of the `DATADIR/img` directories. - - If image is not found, the `image` argument is returned. - """ - # Image is in the same folder as its song - texdir = os.path.dirname(chordprofile) - if os.path.exists(os.path.join(texdir, image)): - return os.path.join(texdir, image) - - # Image is in the same directory as the main tex file - rootdir = os.path.dirname(os.path.join( - os.getcwd(), - config['filename'], - )) - if os.path.exists(os.path.join(rootdir, image)): - return image - - # Image is in a datadir - for directory in config['datadir']: - if os.path.exists(os.path.join(directory, 'img', image)): - return os.path.join(directory, 'img', image) - - # Could not find image - return image diff --git a/patacrep/songs/chordpro/__init__.py b/patacrep/songs/chordpro/__init__.py index ae37b79b..3b5ae809 100644 --- a/patacrep/songs/chordpro/__init__.py +++ b/patacrep/songs/chordpro/__init__.py @@ -5,7 +5,7 @@ import pkg_resources import os from patacrep import encoding, files -from patacrep.songs import Song, search_image +from patacrep.songs import Song from patacrep.songs.chordpro.syntax import parse_song from patacrep.templates import Renderer @@ -42,7 +42,11 @@ class ChordproSong(Song): os.path.abspath(pkg_resources.resource_filename(__name__, 'data')), output_format, ))) - self.jinjaenv.filters['search_image'] = search_image + + self.jinjaenv.filters['search_image'] = self.search_image + + self.jinjaenv.filters['search_partition'] = self.search_partition + return self._render_ast( context, self.cached['song'].content, diff --git a/patacrep/songs/chordpro/ast.py b/patacrep/songs/chordpro/ast.py index 5cffbb86..b2cc6c08 100644 --- a/patacrep/songs/chordpro/ast.py +++ b/patacrep/songs/chordpro/ast.py @@ -39,6 +39,10 @@ class OrderedLifoDict: def __getitem__(self, key): return self._values[key] + def get(self, key, default=None): + """Same as :meth:`dict.get`.""" + return self._values.get(key, default) + def _indent(string): """Return and indented version of argument.""" return "\n".join([" {}".format(line) for line in string.split('\n')]) @@ -337,6 +341,11 @@ class Define(Directive): self.fingers = fingers # Can be None super().__init__("define", None) + @property + def pretty_key(self): + """Return the key with nicer (utf8) alteration""" + return self.key.chord.replace('&', '♭').replace('#', '♯') + def __str__(self): return None diff --git a/patacrep/songs/chordpro/data/latex/content_image b/patacrep/songs/chordpro/data/latex/content_image index bd132ce6..e4c2befb 100644 --- a/patacrep/songs/chordpro/data/latex/content_image +++ b/patacrep/songs/chordpro/data/latex/content_image @@ -1 +1 @@ -\image{(( content.argument|search_image(path, config) ))} +\image{(( content.argument|search_image ))} diff --git a/patacrep/songs/chordpro/data/latex/content_partition b/patacrep/songs/chordpro/data/latex/content_partition index bcb92a0b..4ce134a1 100644 --- a/patacrep/songs/chordpro/data/latex/content_partition +++ b/patacrep/songs/chordpro/data/latex/content_partition @@ -1 +1 @@ -\lilypond{ ((- content.argument|search_image(path, config) -)) } +\lilypond{ ((- content.argument|search_partition -)) } diff --git a/patacrep/songs/chordpro/data/latex/song b/patacrep/songs/chordpro/data/latex/song index e3be0f83..f7905919 100644 --- a/patacrep/songs/chordpro/data/latex/song +++ b/patacrep/songs/chordpro/data/latex/song @@ -28,7 +28,7 @@ (* endif *) (* endfor *) (* if 'cov' in metadata *) - cov={(( metadata["cov"].argument|search_image(path, config) ))}, + cov={(( metadata["cov"].argument|search_image ))}, (* endif *) (* for key in metadata.keys *) (( key.keyword ))={(( key.argument ))},