From 7161a08b8b9d4a1586d05179cf01c095bf8230ed Mon Sep 17 00:00:00 2001 From: Oliverpool Date: Sat, 19 Sep 2015 14:06:15 +0200 Subject: [PATCH 01/20] Reorganize chordpro templates --- patacrep/songs/chordpro/data/chordpro/song | 36 ++----------------- .../songs/chordpro/data/chordpro/song_body | 3 ++ .../songs/chordpro/data/chordpro/song_header | 31 ++++++++++++++++ 3 files changed, 36 insertions(+), 34 deletions(-) create mode 100644 patacrep/songs/chordpro/data/chordpro/song_body create mode 100644 patacrep/songs/chordpro/data/chordpro/song_header diff --git a/patacrep/songs/chordpro/data/chordpro/song b/patacrep/songs/chordpro/data/chordpro/song index d721df33..3baa8c22 100644 --- a/patacrep/songs/chordpro/data/chordpro/song +++ b/patacrep/songs/chordpro/data/chordpro/song @@ -1,35 +1,3 @@ -(* if language is defined -*) - {language: (( language ))} -(* endif *) -(* if metadata.columns is defined -*) - {columns: (( metadata.columns ))} -(* endif *) -(* if metadata.capo is defined -*) - {capo: (( metadata.capo ))} -(* endif *) +(* include 'song_header' *) -(*- for title in titles -*) - {title: (( title ))} -(* endfor -*) - -(*- for author in authors -*) - {artist: (( author[1] ))(( author[0] ))} -(* endfor *) - -(*- for key in ['album', 'copyright', 'cov', 'tag'] *) - (* if key in metadata -*) - {(( key )): (( metadata[key] ))} - (* endif *) -(* endfor *) - -(*- for key in metadata.keys -*) - {key: (( key.keyword )): (( key.argument ))} -(* endfor *) - -(*- for chord in metadata['define'] *) - ((- render(chord) )) -(* endfor *) - -(* for item in content -*) - (( render(item) )) -(* endfor *) +(* include 'song_body' *) diff --git a/patacrep/songs/chordpro/data/chordpro/song_body b/patacrep/songs/chordpro/data/chordpro/song_body new file mode 100644 index 00000000..1b7159bf --- /dev/null +++ b/patacrep/songs/chordpro/data/chordpro/song_body @@ -0,0 +1,3 @@ +(* for item in content -*) + (( render(item) )) +(* endfor *) diff --git a/patacrep/songs/chordpro/data/chordpro/song_header b/patacrep/songs/chordpro/data/chordpro/song_header new file mode 100644 index 00000000..b4a59862 --- /dev/null +++ b/patacrep/songs/chordpro/data/chordpro/song_header @@ -0,0 +1,31 @@ +(* if language is defined -*) + {language: (( language ))} +(* endif *) +(* if metadata.columns is defined -*) + {columns: (( metadata.columns ))} +(* endif *) +(* if metadata.capo is defined -*) + {capo: (( metadata.capo ))} +(* endif *) + +(*- for title in titles -*) + {title: (( title ))} +(* endfor -*) + +(*- for author in authors -*) + {artist: (( author[1] ))(( author[0] ))} +(* endfor *) + +(*- for key in ['album', 'copyright', 'cov', 'tag'] *) + (* if key in metadata -*) + {(( key )): (( metadata[key] ))} + (* endif *) +(* endfor *) + +(*- for key in metadata.keys -*) + {key: (( key.keyword )): (( key.argument ))} +(* endfor *) + +(*- for chord in metadata['define'] *) + ((- render(chord) )) +(* endfor *) From fd7216d5cb51f7b686b248f90983425fb4ff1958 Mon Sep 17 00:00:00 2001 From: Oliverpool Date: Sat, 19 Sep 2015 14:09:12 +0200 Subject: [PATCH 02/20] Template is an argument of the render method --- patacrep/songs/chordpro/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/patacrep/songs/chordpro/__init__.py b/patacrep/songs/chordpro/__init__.py index 3b5ae809..827d23de 100644 --- a/patacrep/songs/chordpro/__init__.py +++ b/patacrep/songs/chordpro/__init__.py @@ -28,7 +28,7 @@ class ChordproSong(Song): 'song': song, } - def render(self, output, output_format): + def render(self, output, output_format, template="song"): context = { 'language': self.languages[0], "path": files.relpath(self.fullpath, os.path.dirname(output)), @@ -50,7 +50,7 @@ class ChordproSong(Song): return self._render_ast( context, self.cached['song'].content, - template="song", + template=template, ) @contextfunction From d4eb28ba9402f87a885153edd63d5d7a868298c0 Mon Sep 17 00:00:00 2001 From: Oliverpool Date: Sat, 19 Sep 2015 14:24:58 +0200 Subject: [PATCH 03/20] lint fix --- patacrep/songs/chordpro/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patacrep/songs/chordpro/__init__.py b/patacrep/songs/chordpro/__init__.py index 827d23de..cd9bfd4e 100644 --- a/patacrep/songs/chordpro/__init__.py +++ b/patacrep/songs/chordpro/__init__.py @@ -28,7 +28,7 @@ class ChordproSong(Song): 'song': song, } - def render(self, output, output_format, template="song"): + def render(self, output, output_format, template="song"): # pylint: disable=arguments-differ context = { 'language': self.languages[0], "path": files.relpath(self.fullpath, os.path.dirname(output)), From 6dd9bba5283d531beec1e56e5eb7e3babb04e761 Mon Sep 17 00:00:00 2001 From: Oliverpool Date: Sat, 19 Sep 2015 14:25:28 +0200 Subject: [PATCH 04/20] Split latex template with body --- patacrep/songs/chordpro/data/latex/song | 4 +--- patacrep/songs/chordpro/data/latex/song_body | 3 +++ 2 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 patacrep/songs/chordpro/data/latex/song_body diff --git a/patacrep/songs/chordpro/data/latex/song b/patacrep/songs/chordpro/data/latex/song index f7905919..021dd04f 100644 --- a/patacrep/songs/chordpro/data/latex/song +++ b/patacrep/songs/chordpro/data/latex/song @@ -43,8 +43,6 @@ (( render(chord) )) (* endfor *) -(* for item in content -*) - (( render(item) )) -(* endfor *) +(* include 'song_body' *) \endsong diff --git a/patacrep/songs/chordpro/data/latex/song_body b/patacrep/songs/chordpro/data/latex/song_body new file mode 100644 index 00000000..1b7159bf --- /dev/null +++ b/patacrep/songs/chordpro/data/latex/song_body @@ -0,0 +1,3 @@ +(* for item in content -*) + (( render(item) )) +(* endfor *) From 9a834f826a20a51d639b84d408367bb9b983ccc5 Mon Sep 17 00:00:00 2001 From: Oliverpool Date: Sat, 19 Sep 2015 14:58:11 +0200 Subject: [PATCH 05/20] Start the html template --- .../songs/chordpro/data/html/content_chord | 1 + .../chordpro/data/html/content_chordlist | 6 ++++ .../songs/chordpro/data/html/content_comment | 1 + .../songs/chordpro/data/html/content_define | 25 +++++++++++++++ .../songs/chordpro/data/html/content_error | 3 ++ .../chordpro/data/html/content_guitar_comment | 1 + .../songs/chordpro/data/html/content_image | 1 + .../songs/chordpro/data/html/content_line | 3 ++ .../songs/chordpro/data/html/content_newline | 1 + .../chordpro/data/html/content_partition | 1 + .../songs/chordpro/data/html/content_space | 1 + .../chordpro/data/html/content_tablature | 5 +++ .../songs/chordpro/data/html/content_verse | 5 +++ .../songs/chordpro/data/html/content_word | 1 + patacrep/songs/chordpro/data/html/song | 3 ++ patacrep/songs/chordpro/data/html/song_body | 3 ++ patacrep/songs/chordpro/data/html/song_header | 31 +++++++++++++++++++ 17 files changed, 92 insertions(+) create mode 100644 patacrep/songs/chordpro/data/html/content_chord create mode 100644 patacrep/songs/chordpro/data/html/content_chordlist create mode 100644 patacrep/songs/chordpro/data/html/content_comment create mode 100644 patacrep/songs/chordpro/data/html/content_define create mode 100644 patacrep/songs/chordpro/data/html/content_error create mode 100644 patacrep/songs/chordpro/data/html/content_guitar_comment create mode 100644 patacrep/songs/chordpro/data/html/content_image create mode 100644 patacrep/songs/chordpro/data/html/content_line create mode 100644 patacrep/songs/chordpro/data/html/content_newline create mode 100644 patacrep/songs/chordpro/data/html/content_partition create mode 100644 patacrep/songs/chordpro/data/html/content_space create mode 100644 patacrep/songs/chordpro/data/html/content_tablature create mode 100644 patacrep/songs/chordpro/data/html/content_verse create mode 100644 patacrep/songs/chordpro/data/html/content_word create mode 100644 patacrep/songs/chordpro/data/html/song create mode 100644 patacrep/songs/chordpro/data/html/song_body create mode 100644 patacrep/songs/chordpro/data/html/song_header diff --git a/patacrep/songs/chordpro/data/html/content_chord b/patacrep/songs/chordpro/data/html/content_chord new file mode 100644 index 00000000..7d5ec6ca --- /dev/null +++ b/patacrep/songs/chordpro/data/html/content_chord @@ -0,0 +1 @@ +((- content.chord -)) diff --git a/patacrep/songs/chordpro/data/html/content_chordlist b/patacrep/songs/chordpro/data/html/content_chordlist new file mode 100644 index 00000000..ad3fc4d0 --- /dev/null +++ b/patacrep/songs/chordpro/data/html/content_chordlist @@ -0,0 +1,6 @@ + + (*- for chord in content.chords -*) + (* if not loop.first *) (* endif -*) + (( render(chord) -)) + (* endfor -*) + diff --git a/patacrep/songs/chordpro/data/html/content_comment b/patacrep/songs/chordpro/data/html/content_comment new file mode 100644 index 00000000..07381cdf --- /dev/null +++ b/patacrep/songs/chordpro/data/html/content_comment @@ -0,0 +1 @@ +{comment: (( content.argument ))} diff --git a/patacrep/songs/chordpro/data/html/content_define b/patacrep/songs/chordpro/data/html/content_define new file mode 100644 index 00000000..47a93abf --- /dev/null +++ b/patacrep/songs/chordpro/data/html/content_define @@ -0,0 +1,25 @@ +{define: (( render(content.key) )) +(*- if content.basefret *) + base-fret ((content.basefret)) +(*- endif *) + frets +(*- for string in content.frets -*) + (( " " -)) + (*- if string is none -*) + x + (*- else -*) + (( string -)) + (*- endif -*) +(*- endfor -*) +(* if content.fingers *) + fingers + (*- for finger in content.fingers -*) + (( " " -)) + (* if finger is none -*) + - + (*- else -*) + (( finger -)) + (* endif -*) + (* endfor -*) +(* endif -*) +} diff --git a/patacrep/songs/chordpro/data/html/content_error b/patacrep/songs/chordpro/data/html/content_error new file mode 100644 index 00000000..bbdb95fd --- /dev/null +++ b/patacrep/songs/chordpro/data/html/content_error @@ -0,0 +1,3 @@ + +ERROR : Template not found for "(( content.__class__.__name__ ))". See the logs for details. + diff --git a/patacrep/songs/chordpro/data/html/content_guitar_comment b/patacrep/songs/chordpro/data/html/content_guitar_comment new file mode 100644 index 00000000..1ca0c269 --- /dev/null +++ b/patacrep/songs/chordpro/data/html/content_guitar_comment @@ -0,0 +1 @@ +{guitar_comment: (( content.argument ))} diff --git a/patacrep/songs/chordpro/data/html/content_image b/patacrep/songs/chordpro/data/html/content_image new file mode 100644 index 00000000..58e7f904 --- /dev/null +++ b/patacrep/songs/chordpro/data/html/content_image @@ -0,0 +1 @@ +{image: (( content.argument ))} diff --git a/patacrep/songs/chordpro/data/html/content_line b/patacrep/songs/chordpro/data/html/content_line new file mode 100644 index 00000000..03ca80b7 --- /dev/null +++ b/patacrep/songs/chordpro/data/html/content_line @@ -0,0 +1,3 @@ +(* for item in content.line -*) + (( render(item) )) +(*- endfor *) diff --git a/patacrep/songs/chordpro/data/html/content_newline b/patacrep/songs/chordpro/data/html/content_newline new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/patacrep/songs/chordpro/data/html/content_newline @@ -0,0 +1 @@ + diff --git a/patacrep/songs/chordpro/data/html/content_partition b/patacrep/songs/chordpro/data/html/content_partition new file mode 100644 index 00000000..362c4f64 --- /dev/null +++ b/patacrep/songs/chordpro/data/html/content_partition @@ -0,0 +1 @@ +{partition: ((content.argument))} diff --git a/patacrep/songs/chordpro/data/html/content_space b/patacrep/songs/chordpro/data/html/content_space new file mode 100644 index 00000000..8d1c8b69 --- /dev/null +++ b/patacrep/songs/chordpro/data/html/content_space @@ -0,0 +1 @@ + diff --git a/patacrep/songs/chordpro/data/html/content_tablature b/patacrep/songs/chordpro/data/html/content_tablature new file mode 100644 index 00000000..35cfd425 --- /dev/null +++ b/patacrep/songs/chordpro/data/html/content_tablature @@ -0,0 +1,5 @@ +
+  (* for content in content.content *)
+    ((- content ))
+  (* endfor *)
+
diff --git a/patacrep/songs/chordpro/data/html/content_verse b/patacrep/songs/chordpro/data/html/content_verse new file mode 100644 index 00000000..4b6073a4 --- /dev/null +++ b/patacrep/songs/chordpro/data/html/content_verse @@ -0,0 +1,5 @@ +

+ (*- for line in content.lines -*) + (( render(line) )) + (* endfor -*) +

diff --git a/patacrep/songs/chordpro/data/html/content_word b/patacrep/songs/chordpro/data/html/content_word new file mode 100644 index 00000000..d9dd7a30 --- /dev/null +++ b/patacrep/songs/chordpro/data/html/content_word @@ -0,0 +1 @@ +(( content.value )) diff --git a/patacrep/songs/chordpro/data/html/song b/patacrep/songs/chordpro/data/html/song new file mode 100644 index 00000000..3baa8c22 --- /dev/null +++ b/patacrep/songs/chordpro/data/html/song @@ -0,0 +1,3 @@ +(* include 'song_header' *) + +(* include 'song_body' *) diff --git a/patacrep/songs/chordpro/data/html/song_body b/patacrep/songs/chordpro/data/html/song_body new file mode 100644 index 00000000..1b7159bf --- /dev/null +++ b/patacrep/songs/chordpro/data/html/song_body @@ -0,0 +1,3 @@ +(* for item in content -*) + (( render(item) )) +(* endfor *) diff --git a/patacrep/songs/chordpro/data/html/song_header b/patacrep/songs/chordpro/data/html/song_header new file mode 100644 index 00000000..b4a59862 --- /dev/null +++ b/patacrep/songs/chordpro/data/html/song_header @@ -0,0 +1,31 @@ +(* if language is defined -*) + {language: (( language ))} +(* endif *) +(* if metadata.columns is defined -*) + {columns: (( metadata.columns ))} +(* endif *) +(* if metadata.capo is defined -*) + {capo: (( metadata.capo ))} +(* endif *) + +(*- for title in titles -*) + {title: (( title ))} +(* endfor -*) + +(*- for author in authors -*) + {artist: (( author[1] ))(( author[0] ))} +(* endfor *) + +(*- for key in ['album', 'copyright', 'cov', 'tag'] *) + (* if key in metadata -*) + {(( key )): (( metadata[key] ))} + (* endif *) +(* endfor *) + +(*- for key in metadata.keys -*) + {key: (( key.keyword )): (( key.argument ))} +(* endfor *) + +(*- for chord in metadata['define'] *) + ((- render(chord) )) +(* endfor *) From 176db619295416275e8ddb97d83ada86c8bd854b Mon Sep 17 00:00:00 2001 From: Oliverpool Date: Sat, 19 Sep 2015 15:17:31 +0200 Subject: [PATCH 06/20] Add a pretty_chord property to Chord for HTML rendering --- patacrep/songs/chordpro/ast.py | 5 +++++ patacrep/songs/chordpro/data/html/content_chord | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/patacrep/songs/chordpro/ast.py b/patacrep/songs/chordpro/ast.py index b2cc6c08..0227d457 100644 --- a/patacrep/songs/chordpro/ast.py +++ b/patacrep/songs/chordpro/ast.py @@ -153,6 +153,11 @@ class Chord(AST): # pylint: disable=too-many-arguments self.chord = chord + @property + def pretty_chord(self): + """Return the chord with nicer (utf8) alteration""" + return self.chord.replace('b', '♭').replace('#', '♯') + class Verse(AST): """A verse (or bridge, or chorus)""" _template = "verse" diff --git a/patacrep/songs/chordpro/data/html/content_chord b/patacrep/songs/chordpro/data/html/content_chord index 7d5ec6ca..baa97f7e 100644 --- a/patacrep/songs/chordpro/data/html/content_chord +++ b/patacrep/songs/chordpro/data/html/content_chord @@ -1 +1 @@ -((- content.chord -)) +((- content.pretty_chord -)) From 5ab211315ea73127c49c8304d51893931aa495cb Mon Sep 17 00:00:00 2001 From: Louis Date: Sat, 19 Sep 2015 19:55:54 +0200 Subject: [PATCH 07/20] Improved sub-template rendering Using the existing jinja rendere, instead of re-instantiting a new one. --- patacrep/songs/chordpro/__init__.py | 34 ++++++++++------------------- 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/patacrep/songs/chordpro/__init__.py b/patacrep/songs/chordpro/__init__.py index cd9bfd4e..42011244 100644 --- a/patacrep/songs/chordpro/__init__.py +++ b/patacrep/songs/chordpro/__init__.py @@ -14,7 +14,6 @@ class ChordproSong(Song): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - self.jinjaenv = None def parse(self, config): """Parse content, and return the dictionary of song data.""" @@ -37,37 +36,28 @@ class ChordproSong(Song): "metadata": self.data, "render": self._render_ast, "config": self.config, + "content": self.cached['song'].content, } - self.jinjaenv = Environment(loader=FileSystemLoader(os.path.join( + jinjaenv = Environment(loader=FileSystemLoader(os.path.join( os.path.abspath(pkg_resources.resource_filename(__name__, 'data')), output_format, ))) + jinjaenv.filters['search_image'] = self.search_image + jinjaenv.filters['search_partition'] = self.search_partition - 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, - template=template, - ) - - @contextfunction - def _render_ast(self, context, content, template=None): - """Render ``content``.""" - if isinstance(context, dict): - context['content'] = content - else: - context.vars['content'] = content - if template is None: - template = content.template() return Renderer( template=template, encoding='utf8', - jinjaenv=self.jinjaenv, + jinjaenv=jinjaenv, ).template.render(context) + @staticmethod + @contextfunction + def _render_ast(context, content): + """Render ``content``.""" + context.vars['content'] = content + return context.environment.get_template(content.template()).render(context) + SONG_PARSERS = { 'sgc': ChordproSong, } From 51d6ecd8a757011021f5631ea44add8bba68d2b9 Mon Sep 17 00:00:00 2001 From: Oliverpool Date: Sun, 20 Sep 2015 16:10:55 +0200 Subject: [PATCH 08/20] Allow to render only selected elements of a song --- patacrep/songs/chordpro/__init__.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/patacrep/songs/chordpro/__init__.py b/patacrep/songs/chordpro/__init__.py index 42011244..f6c12ad3 100644 --- a/patacrep/songs/chordpro/__init__.py +++ b/patacrep/songs/chordpro/__init__.py @@ -27,7 +27,9 @@ class ChordproSong(Song): 'song': song, } - def render(self, output, output_format, template="song"): # pylint: disable=arguments-differ + def render(self, output, output_format, content=None, template="song"): # pylint: disable=arguments-differ + if content is None: + content = self.cached['song'].content context = { 'language': self.languages[0], "path": files.relpath(self.fullpath, os.path.dirname(output)), @@ -36,7 +38,7 @@ class ChordproSong(Song): "metadata": self.data, "render": self._render_ast, "config": self.config, - "content": self.cached['song'].content, + "content": content, } jinjaenv = Environment(loader=FileSystemLoader(os.path.join( os.path.abspath(pkg_resources.resource_filename(__name__, 'data')), From efdb79cac94ccee4ec976d2c91cce508d52fd94d Mon Sep 17 00:00:00 2001 From: Oliverpool Date: Mon, 21 Sep 2015 07:41:04 +0200 Subject: [PATCH 09/20] search_file returns absolute filepath --- patacrep/songs/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patacrep/songs/__init__.py b/patacrep/songs/__init__.py index b59883be..69403502 100644 --- a/patacrep/songs/__init__.py +++ b/patacrep/songs/__init__.py @@ -223,7 +223,7 @@ class Song: for extension in extensions: fullpath = os.path.join(directory, filename + extension) if os.path.isfile(fullpath): - return fullpath + return os.path.abspath(fullpath) return None def search_image(self, filename): From b9e542cf54b07920ae655e629c20ef5186e3d5f1 Mon Sep 17 00:00:00 2001 From: Oliverpool Date: Tue, 22 Sep 2015 14:54:54 +0200 Subject: [PATCH 10/20] Complete HTML template --- .../songs/chordpro/data/html/content_comment | 2 +- .../songs/chordpro/data/html/content_define | 56 ++++++++++--------- .../chordpro/data/html/content_define_list | 3 + .../chordpro/data/html/content_guitar_comment | 2 +- .../songs/chordpro/data/html/content_image | 2 +- .../chordpro/data/html/content_metadata_cover | 3 + .../chordpro/data/html/content_partition | 2 +- .../songs/chordpro/data/html/content_verse | 1 + patacrep/songs/chordpro/data/html/song | 2 + patacrep/songs/chordpro/data/html/song_header | 33 ++++++----- 10 files changed, 60 insertions(+), 46 deletions(-) create mode 100644 patacrep/songs/chordpro/data/html/content_define_list create mode 100644 patacrep/songs/chordpro/data/html/content_metadata_cover diff --git a/patacrep/songs/chordpro/data/html/content_comment b/patacrep/songs/chordpro/data/html/content_comment index 07381cdf..d9dfd2f1 100644 --- a/patacrep/songs/chordpro/data/html/content_comment +++ b/patacrep/songs/chordpro/data/html/content_comment @@ -1 +1 @@ -{comment: (( content.argument ))} +
(( content.argument ))
diff --git a/patacrep/songs/chordpro/data/html/content_define b/patacrep/songs/chordpro/data/html/content_define index 47a93abf..4998f0bd 100644 --- a/patacrep/songs/chordpro/data/html/content_define +++ b/patacrep/songs/chordpro/data/html/content_define @@ -1,25 +1,31 @@ -{define: (( render(content.key) )) -(*- if content.basefret *) - base-fret ((content.basefret)) -(*- endif *) - frets -(*- for string in content.frets -*) - (( " " -)) - (*- if string is none -*) - x - (*- else -*) - (( string -)) - (*- endif -*) -(*- endfor -*) -(* if content.fingers *) - fingers - (*- for finger in content.fingers -*) - (( " " -)) - (* if finger is none -*) - - - (*- else -*) - (( finger -)) - (* endif -*) - (* endfor -*) -(* endif -*) -} + \ No newline at end of file diff --git a/patacrep/songs/chordpro/data/html/content_define_list b/patacrep/songs/chordpro/data/html/content_define_list new file mode 100644 index 00000000..923f37c2 --- /dev/null +++ b/patacrep/songs/chordpro/data/html/content_define_list @@ -0,0 +1,3 @@ +(*- for chord in metadata['define'] *) + ((- render(chord) )) +(* endfor *) diff --git a/patacrep/songs/chordpro/data/html/content_guitar_comment b/patacrep/songs/chordpro/data/html/content_guitar_comment index 1ca0c269..770cc6b0 100644 --- a/patacrep/songs/chordpro/data/html/content_guitar_comment +++ b/patacrep/songs/chordpro/data/html/content_guitar_comment @@ -1 +1 @@ -{guitar_comment: (( content.argument ))} +
(( content.argument ))
diff --git a/patacrep/songs/chordpro/data/html/content_image b/patacrep/songs/chordpro/data/html/content_image index 58e7f904..4e1889b7 100644 --- a/patacrep/songs/chordpro/data/html/content_image +++ b/patacrep/songs/chordpro/data/html/content_image @@ -1 +1 @@ -{image: (( content.argument ))} + diff --git a/patacrep/songs/chordpro/data/html/content_metadata_cover b/patacrep/songs/chordpro/data/html/content_metadata_cover new file mode 100644 index 00000000..96fc7718 --- /dev/null +++ b/patacrep/songs/chordpro/data/html/content_metadata_cover @@ -0,0 +1,3 @@ +(* if 'cov' in metadata -*) +
+(* endif *) \ No newline at end of file diff --git a/patacrep/songs/chordpro/data/html/content_partition b/patacrep/songs/chordpro/data/html/content_partition index 362c4f64..bf2d3164 100644 --- a/patacrep/songs/chordpro/data/html/content_partition +++ b/patacrep/songs/chordpro/data/html/content_partition @@ -1 +1 @@ -{partition: ((content.argument))} +((content.argument)) diff --git a/patacrep/songs/chordpro/data/html/content_verse b/patacrep/songs/chordpro/data/html/content_verse index 4b6073a4..eab4d361 100644 --- a/patacrep/songs/chordpro/data/html/content_verse +++ b/patacrep/songs/chordpro/data/html/content_verse @@ -1,5 +1,6 @@

(*- for line in content.lines -*) + (* if not loop.first *)
(* endif -*) (( render(line) )) (* endfor -*)

diff --git a/patacrep/songs/chordpro/data/html/song b/patacrep/songs/chordpro/data/html/song index 3baa8c22..e774cdff 100644 --- a/patacrep/songs/chordpro/data/html/song +++ b/patacrep/songs/chordpro/data/html/song @@ -1,3 +1,5 @@ (* include 'song_header' *) +
(* include 'song_body' *) +
diff --git a/patacrep/songs/chordpro/data/html/song_header b/patacrep/songs/chordpro/data/html/song_header index b4a59862..cc23ad17 100644 --- a/patacrep/songs/chordpro/data/html/song_header +++ b/patacrep/songs/chordpro/data/html/song_header @@ -1,31 +1,30 @@ -(* if language is defined -*) - {language: (( language ))} -(* endif *) -(* if metadata.columns is defined -*) - {columns: (( metadata.columns ))} -(* endif *) -(* if metadata.capo is defined -*) - {capo: (( metadata.capo ))} -(* endif *) - (*- for title in titles -*) - {title: (( title ))} + (* if loop.first *) +

(( title ))

+ (* else *) +

(( title ))

+ (* endif *) (* endfor -*) (*- for author in authors -*) - {artist: (( author[1] ))(( author[0] ))} +

(( author[1] ))(( author[0] ))

(* endfor *) -(*- for key in ['album', 'copyright', 'cov', 'tag'] *) + +(*- for key in ['album', 'copyright', 'tag', 'columns', 'capo'] *) (* if key in metadata -*) - {(( key )): (( metadata[key] ))} + (( key|capitalize )): (( metadata[key] ))
(* endif *) (* endfor *) +(* if language is defined -*) + Language: (( language ))
+(* endif *) + +(* include 'content_metadata_cover' *) + (*- for key in metadata.keys -*) {key: (( key.keyword )): (( key.argument ))} (* endfor *) -(*- for chord in metadata['define'] *) - ((- render(chord) )) -(* endfor *) +(* include 'content_define_list' *) From 56c7c39b05f2cd0203315a525c4f3e28935cc188 Mon Sep 17 00:00:00 2001 From: Oliverpool Date: Tue, 22 Sep 2015 15:07:22 +0200 Subject: [PATCH 11/20] Allow custom path to song templates --- patacrep/songs/chordpro/__init__.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/patacrep/songs/chordpro/__init__.py b/patacrep/songs/chordpro/__init__.py index f6c12ad3..30264445 100644 --- a/patacrep/songs/chordpro/__init__.py +++ b/patacrep/songs/chordpro/__init__.py @@ -14,6 +14,15 @@ class ChordproSong(Song): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) + self.template_paths = [os.path.abspath(pkg_resources.resource_filename(__name__, 'data'))] + + def add_template_path(self, absolute_path): + """Add a template path (at the beginning, so that it's choosen first).""" + self.template_paths.insert(0, absolute_path) + + def get_template_paths(self, output_format): + """Get the template path for a given output_format.""" + return [os.path.join(path, output_format) for path in self.template_paths] def parse(self, config): """Parse content, and return the dictionary of song data.""" @@ -40,10 +49,9 @@ class ChordproSong(Song): "config": self.config, "content": content, } - jinjaenv = Environment(loader=FileSystemLoader(os.path.join( - os.path.abspath(pkg_resources.resource_filename(__name__, 'data')), - output_format, - ))) + jinjaenv = Environment(loader=FileSystemLoader( + self.get_template_paths(output_format) + )) jinjaenv.filters['search_image'] = self.search_image jinjaenv.filters['search_partition'] = self.search_partition From af893a15de9d62d3da542aed8bcbb196957720eb Mon Sep 17 00:00:00 2001 From: Oliverpool Date: Tue, 22 Sep 2015 16:06:35 +0200 Subject: [PATCH 12/20] Search for the images and partitions in HTML template --- patacrep/songs/chordpro/data/html/content_image | 2 +- patacrep/songs/chordpro/data/html/content_partition | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/patacrep/songs/chordpro/data/html/content_image b/patacrep/songs/chordpro/data/html/content_image index 4e1889b7..0da4bcfe 100644 --- a/patacrep/songs/chordpro/data/html/content_image +++ b/patacrep/songs/chordpro/data/html/content_image @@ -1 +1 @@ - + diff --git a/patacrep/songs/chordpro/data/html/content_partition b/patacrep/songs/chordpro/data/html/content_partition index bf2d3164..1075cced 100644 --- a/patacrep/songs/chordpro/data/html/content_partition +++ b/patacrep/songs/chordpro/data/html/content_partition @@ -1 +1 @@ -((content.argument)) +((content.argument)) From 3a9f5aadce19874e6370b60dbadd57b38cd20b93 Mon Sep 17 00:00:00 2001 From: Louis Date: Wed, 23 Sep 2015 17:37:19 +0200 Subject: [PATCH 13/20] Renamed `Song.parse()` to `Song._parse()` (as this method is private) --- patacrep/songs/__init__.py | 4 ++-- patacrep/songs/chordpro/__init__.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/patacrep/songs/__init__.py b/patacrep/songs/__init__.py index 69403502..0b7cabeb 100644 --- a/patacrep/songs/__init__.py +++ b/patacrep/songs/__init__.py @@ -128,7 +128,7 @@ class Song: self.titles = [] self.data = {} self.cached = None - self.parse(config) + self._parse(config) # Post processing of data self.datadir = datadir @@ -177,7 +177,7 @@ class Song: return getattr(self, method)(output) raise NotImplementedError() - def parse(self, config): # pylint: disable=no-self-use + def _parse(self, config): # pylint: disable=no-self-use """Parse song. It set the following attributes: diff --git a/patacrep/songs/chordpro/__init__.py b/patacrep/songs/chordpro/__init__.py index 30264445..c0328d4b 100644 --- a/patacrep/songs/chordpro/__init__.py +++ b/patacrep/songs/chordpro/__init__.py @@ -24,7 +24,7 @@ class ChordproSong(Song): """Get the template path for a given output_format.""" return [os.path.join(path, output_format) for path in self.template_paths] - def parse(self, config): + def _parse(self, config): """Parse content, and return the dictionary of song data.""" with encoding.open_read(self.fullpath, encoding=self.encoding) as song: song = parse_song(song.read(), self.fullpath) From fe26591b7268bd87aa0b0fa6e07005c703e45813 Mon Sep 17 00:00:00 2001 From: Louis Date: Wed, 23 Sep 2015 17:56:45 +0200 Subject: [PATCH 14/20] Deleted useless parameter. May be added later (I think it does break some tests) --- patacrep/songs/chordpro/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patacrep/songs/chordpro/__init__.py b/patacrep/songs/chordpro/__init__.py index c0328d4b..bcaa68bd 100644 --- a/patacrep/songs/chordpro/__init__.py +++ b/patacrep/songs/chordpro/__init__.py @@ -41,7 +41,6 @@ class ChordproSong(Song): content = self.cached['song'].content context = { 'language': self.languages[0], - "path": files.relpath(self.fullpath, os.path.dirname(output)), "titles": self.titles, "authors": self.authors, "metadata": self.data, @@ -49,6 +48,7 @@ class ChordproSong(Song): "config": self.config, "content": content, } + jinjaenv = Environment(loader=FileSystemLoader( self.get_template_paths(output_format) )) From b73027c865b29ff199bca0b086b9eacca1404062 Mon Sep 17 00:00:00 2001 From: Louis Date: Wed, 23 Sep 2015 19:38:37 +0200 Subject: [PATCH 15/20] Clarified signature of `patacrep.songs.ChordproSong.render()` --- patacrep/songs/__init__.py | 6 +++--- patacrep/songs/chordpro/__init__.py | 6 ++---- patacrep/songs/latex/__init__.py | 2 ++ test/test_chordpro/test_parser.py | 1 - 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/patacrep/songs/__init__.py b/patacrep/songs/__init__.py index 0b7cabeb..0eb0b7e2 100644 --- a/patacrep/songs/__init__.py +++ b/patacrep/songs/__init__.py @@ -165,16 +165,16 @@ class Song: def __repr__(self): return repr((self.titles, self.data, self.fullpath)) - def render(self, output, output_format): + def render(self, output_format, output=None, *args, **kwargs): """Return the code rendering this song. Arguments: - - output: Name of the output file. - output_format: Format of the output file (latex, chordpro...) + - output: Name of the output file, or `None` if irrelevant. """ method = "render_{}".format(output_format) if hasattr(self, method): - return getattr(self, method)(output) + return getattr(self, method)(output, *args, **kwargs) raise NotImplementedError() def _parse(self, config): # pylint: disable=no-self-use diff --git a/patacrep/songs/chordpro/__init__.py b/patacrep/songs/chordpro/__init__.py index bcaa68bd..3ba87169 100644 --- a/patacrep/songs/chordpro/__init__.py +++ b/patacrep/songs/chordpro/__init__.py @@ -36,9 +36,7 @@ class ChordproSong(Song): 'song': song, } - def render(self, output, output_format, content=None, template="song"): # pylint: disable=arguments-differ - if content is None: - content = self.cached['song'].content + def render(self, output_format, output=None, template="song"): context = { 'language': self.languages[0], "titles": self.titles, @@ -46,7 +44,7 @@ class ChordproSong(Song): "metadata": self.data, "render": self._render_ast, "config": self.config, - "content": content, + "content": self.cached['song'].content, } jinjaenv = Environment(loader=FileSystemLoader( diff --git a/patacrep/songs/latex/__init__.py b/patacrep/songs/latex/__init__.py index a0d9c945..805f77f2 100644 --- a/patacrep/songs/latex/__init__.py +++ b/patacrep/songs/latex/__init__.py @@ -30,6 +30,8 @@ class LatexSong(Song): def render_latex(self, output): """Return the code rendering the song.""" + if output is None: + raise ValueError(output) path = files.path2posix(files.relpath( self.fullpath, os.path.dirname(output) diff --git a/test/test_chordpro/test_parser.py b/test/test_chordpro/test_parser.py index 2bdd15aa..796fdb2a 100644 --- a/test/test_chordpro/test_parser.py +++ b/test/test_chordpro/test_parser.py @@ -48,7 +48,6 @@ class TestParsingRendering(unittest.TestCase): with self.subTest(base=os.path.basename(base), format=dest): self.assertMultiLineEqual( ChordproSong(None, chordproname, config).render( - output=chordproname, output_format=LANGUAGES[dest], ).strip(), expectfile.read().strip(), From 1a6507f175e57d3542f996742f71e7b7f29abd6b Mon Sep 17 00:00:00 2001 From: Louis Date: Wed, 23 Sep 2015 19:50:45 +0200 Subject: [PATCH 16/20] Template directories is now an argument to the `render()` method --- patacrep/songs/chordpro/__init__.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/patacrep/songs/chordpro/__init__.py b/patacrep/songs/chordpro/__init__.py index 3ba87169..a04d6dd5 100644 --- a/patacrep/songs/chordpro/__init__.py +++ b/patacrep/songs/chordpro/__init__.py @@ -14,15 +14,12 @@ class ChordproSong(Song): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - self.template_paths = [os.path.abspath(pkg_resources.resource_filename(__name__, 'data'))] - def add_template_path(self, absolute_path): - """Add a template path (at the beginning, so that it's choosen first).""" - self.template_paths.insert(0, absolute_path) - - def get_template_paths(self, output_format): - """Get the template path for a given output_format.""" - return [os.path.join(path, output_format) for path in self.template_paths] + @staticmethod + def iter_template_paths(templatedirs, output_format): + for directory in templatedirs: + yield os.path.join(directory, output_format) + yield os.path.join(os.path.abspath(pkg_resources.resource_filename(__name__, 'data')), output_format) def _parse(self, config): """Parse content, and return the dictionary of song data.""" @@ -36,7 +33,10 @@ class ChordproSong(Song): 'song': song, } - def render(self, output_format, output=None, template="song"): + def render(self, output_format, output=None, template="song", templatedirs=None): + if templatedirs is None: + templatedirs = [] + context = { 'language': self.languages[0], "titles": self.titles, @@ -48,7 +48,7 @@ class ChordproSong(Song): } jinjaenv = Environment(loader=FileSystemLoader( - self.get_template_paths(output_format) + self.iter_template_paths(templatedirs, output_format) )) jinjaenv.filters['search_image'] = self.search_image jinjaenv.filters['search_partition'] = self.search_partition From becea663ea1cab7305732e16d7dc4d6e74eecbcb Mon Sep 17 00:00:00 2001 From: Louis Date: Wed, 23 Sep 2015 20:18:47 +0200 Subject: [PATCH 17/20] Silent changes to `seach_*()` methods; using `search_*()` filters in templates --- patacrep/songs/__init__.py | 25 ++++++++++++------- .../chordpro/data/chordpro/content_image | 2 +- .../chordpro/data/chordpro/content_partition | 2 +- .../songs/chordpro/data/chordpro/song_header | 5 +++- 4 files changed, 22 insertions(+), 12 deletions(-) diff --git a/patacrep/songs/__init__.py b/patacrep/songs/__init__.py index 0eb0b7e2..792347d3 100644 --- a/patacrep/songs/__init__.py +++ b/patacrep/songs/__init__.py @@ -206,16 +206,20 @@ class Song: """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 list extensions: Possible extensions (with '.'). Default is no extension. :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. + + This function can also be used as a preprocessor for a renderer: for + instance, it can compile a file, place it in a temporary folder, and + return the path to the compiled file. """ if extensions is None: extensions = [''] if directories is None: - directories = [] + directories = self.config['datadir'] songdir = os.path.dirname(self.fullpath) @@ -228,8 +232,16 @@ class Song: 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) + filepath = self.search_file( + filename, + ['', '.jpg', '.png'], + self.get_datadirs('img'), + ) + return filepath if filepath else filename + + def search_partition(self, filename): + """Search for a lilypond file""" + filepath = self.search_file(filename, ['', '.ly']) return filepath if filepath else filename @property @@ -241,11 +253,6 @@ class Song: 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). """ diff --git a/patacrep/songs/chordpro/data/chordpro/content_image b/patacrep/songs/chordpro/data/chordpro/content_image index 58e7f904..4f9bf06c 100644 --- a/patacrep/songs/chordpro/data/chordpro/content_image +++ b/patacrep/songs/chordpro/data/chordpro/content_image @@ -1 +1 @@ -{image: (( content.argument ))} +{image: (( content.argument|search_image ))} diff --git a/patacrep/songs/chordpro/data/chordpro/content_partition b/patacrep/songs/chordpro/data/chordpro/content_partition index 362c4f64..43b8761e 100644 --- a/patacrep/songs/chordpro/data/chordpro/content_partition +++ b/patacrep/songs/chordpro/data/chordpro/content_partition @@ -1 +1 @@ -{partition: ((content.argument))} +{partition: ((content.argument|search_partition))} diff --git a/patacrep/songs/chordpro/data/chordpro/song_header b/patacrep/songs/chordpro/data/chordpro/song_header index b4a59862..d3e65f0b 100644 --- a/patacrep/songs/chordpro/data/chordpro/song_header +++ b/patacrep/songs/chordpro/data/chordpro/song_header @@ -16,11 +16,14 @@ {artist: (( author[1] ))(( author[0] ))} (* endfor *) -(*- for key in ['album', 'copyright', 'cov', 'tag'] *) +(*- for key in ['album', 'copyright', 'tag'] *) (* if key in metadata -*) {(( key )): (( metadata[key] ))} (* endif *) (* endfor *) +(* if 'cov' in metadata -*) + {(( 'cov' )): (( metadata['cov'].argument|search_image ))} +(* endif *) (*- for key in metadata.keys -*) {key: (( key.keyword )): (( key.argument ))} From 3779567fea21d4c1f45154fdfa01963550ce17f0 Mon Sep 17 00:00:00 2001 From: Louis Date: Wed, 23 Sep 2015 21:27:26 +0200 Subject: [PATCH 18/20] Deleted method `cover_filepath` --- patacrep/songs/__init__.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/patacrep/songs/__init__.py b/patacrep/songs/__init__.py index 792347d3..d1f24a99 100644 --- a/patacrep/songs/__init__.py +++ b/patacrep/songs/__init__.py @@ -244,15 +244,6 @@ class Song: filepath = self.search_file(filename, ['', '.ly']) 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 unprefixed_title(title, prefixes): """Remove the first prefix of the list in the beginning of title (if any). """ From 8e480a3342b709dd1e12193acdca61b7e7e579ca Mon Sep 17 00:00:00 2001 From: Louis Date: Wed, 23 Sep 2015 21:47:51 +0200 Subject: [PATCH 19/20] Pylint --- patacrep/songs/chordpro/__init__.py | 14 ++++++++++++-- patacrep/songs/latex/__init__.py | 2 +- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/patacrep/songs/chordpro/__init__.py b/patacrep/songs/chordpro/__init__.py index a04d6dd5..6d4c0e39 100644 --- a/patacrep/songs/chordpro/__init__.py +++ b/patacrep/songs/chordpro/__init__.py @@ -17,9 +17,19 @@ class ChordproSong(Song): @staticmethod def iter_template_paths(templatedirs, output_format): + """Iterate over paths in which templates are to be searched. + + :param iterator templatedirs: Iterators of additional directories (the + default hard-coded template directory is returned last). + :param str output_format: Song output format, which is appended to + each directory. + """ for directory in templatedirs: yield os.path.join(directory, output_format) - yield os.path.join(os.path.abspath(pkg_resources.resource_filename(__name__, 'data')), output_format) + yield os.path.join( + os.path.abspath(pkg_resources.resource_filename(__name__, 'data')), + output_format, + ) def _parse(self, config): """Parse content, and return the dictionary of song data.""" @@ -33,7 +43,7 @@ class ChordproSong(Song): 'song': song, } - def render(self, output_format, output=None, template="song", templatedirs=None): + def render(self, output_format, output=None, template="song", templatedirs=None): # pylint: disable=arguments-differ if templatedirs is None: templatedirs = [] diff --git a/patacrep/songs/latex/__init__.py b/patacrep/songs/latex/__init__.py index 805f77f2..6ac54c81 100644 --- a/patacrep/songs/latex/__init__.py +++ b/patacrep/songs/latex/__init__.py @@ -14,7 +14,7 @@ from patacrep.songs import Song class LatexSong(Song): """LaTeX song parser.""" - def parse(self, __config): + def _parse(self, __config): """Parse content, and return the dictinory of song data.""" with encoding.open_read(self.fullpath, encoding=self.encoding) as song: self.data = parse_song(song.read(), self.fullpath) From c11a59db7bf7f36a54688334509100d872bdbb04 Mon Sep 17 00:00:00 2001 From: Oliverpool Date: Thu, 24 Sep 2015 10:49:42 +0200 Subject: [PATCH 20/20] Allow the search_image and search_partition to return None --- patacrep/songs/__init__.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/patacrep/songs/__init__.py b/patacrep/songs/__init__.py index d1f24a99..297a993e 100644 --- a/patacrep/songs/__init__.py +++ b/patacrep/songs/__init__.py @@ -230,19 +230,19 @@ class Song: return os.path.abspath(fullpath) return None - def search_image(self, filename): + def search_image(self, filename, none_if_not_found=False): """Search for an image file""" filepath = self.search_file( filename, ['', '.jpg', '.png'], self.get_datadirs('img'), ) - return filepath if filepath else filename + return filepath if none_if_not_found or filepath else filename - def search_partition(self, filename): + def search_partition(self, filename, none_if_not_found=False): """Search for a lilypond file""" filepath = self.search_file(filename, ['', '.ly']) - return filepath if filepath else filename + return filepath if none_if_not_found or filepath else filename def unprefixed_title(title, prefixes): """Remove the first prefix of the list in the beginning of title (if any).