diff --git a/patacrep/build.py b/patacrep/build.py index c9aa87e3..5682da1d 100644 --- a/patacrep/build.py +++ b/patacrep/build.py @@ -33,6 +33,7 @@ DEFAULT_CONFIG = { 'content': [], 'titleprefixwords': [], 'encoding': None, + 'datadir': [], } @@ -113,7 +114,7 @@ class Songbook(object): ) # Configuration set - config['render_content'] = content.render_content + config['render'] = content.render config['content'] = content.process_content( config.get('content', []), config, diff --git a/patacrep/content/__init__.py b/patacrep/content/__init__.py index d92dc99b..040adbad 100755 --- a/patacrep/content/__init__.py +++ b/patacrep/content/__init__.py @@ -131,7 +131,7 @@ class ContentError(SongbookError): return "Content: {}: {}".format(self.keyword, self.message) @jinja2.contextfunction -def render_content(context, content): +def render(context, content): """Render the content of the songbook as a LaTeX code. Arguments: diff --git a/patacrep/content/song.py b/patacrep/content/song.py index f252e314..b44fc7f1 100755 --- a/patacrep/content/song.py +++ b/patacrep/content/song.py @@ -4,6 +4,7 @@ import glob import jinja2 import logging import os +import textwrap from patacrep.content import process_content, ContentError, Content from patacrep import files, errors @@ -34,7 +35,16 @@ class SongRenderer(Content): def render(self, context): """Return the string that will render the song.""" - return self.song.tex(output=context['filename']) + return textwrap.dedent("""\ + {separator} + %% {path} + + {song} + """).format( + separator="%"*80, + path=self.song.subpath, + song=self.song.render(output=context['filename'], output_format="latex"), + ) #pylint: disable=unused-argument def parse(keyword, argument, contentlist, config): diff --git a/patacrep/data/examples/example-all.sb b/patacrep/data/examples/example-all.sb index ca35b622..dba08cc0 100644 --- a/patacrep/data/examples/example-all.sb +++ b/patacrep/data/examples/example-all.sb @@ -1,11 +1,12 @@ { "bookoptions" : [ - "importantdiagramonly", + "diagram", "repeatchords", "lilypond", "pictures" ], "booktype" : "chorded", +"template" : "patacrep.tex", "lang" : "french", "encoding": "utf8", "authwords" : { diff --git a/patacrep/data/examples/example-subdir.sb b/patacrep/data/examples/example-subdir.sb new file mode 100644 index 00000000..c7d23631 --- /dev/null +++ b/patacrep/data/examples/example-subdir.sb @@ -0,0 +1,17 @@ +{ +"bookoptions" : [ + "diagram", + "repeatchords", + "lilypond", + "pictures" + ], +"booktype" : "chorded", +"template" : "patacrep.tex", +"lang" : "french", +"encoding": "utf8", +"authwords" : { + "sep" : ["and", "et"] + }, + "content": [["sorted", "subdir/*.sg", "subdir/*.sgc"]] + +} diff --git a/patacrep/data/examples/img/datadir.ly b/patacrep/data/examples/img/datadir.ly new file mode 100644 index 00000000..1fd2bccb --- /dev/null +++ b/patacrep/data/examples/img/datadir.ly @@ -0,0 +1,19 @@ +\include "_lilypond/header" +\paper{paper-height = 6.5\cm} + +{ + \key a \minor + \time 6/8 + \partial 8 a'8 + \relative c''{ + c4 d8 e8. (f16) e8 d4 b8 g8. (a16) b8 + c4 a8 a8. (gis16) a8 b4 gis8 e4 a8 + c4 d8 e8. (f16 e8) d4 b8 g8. (a16) b8 + c8. (b16) a8 gis8. (fis16) gis8 a4 a8 a4. + + g'4. g8. (fis16) e8 d4 b8 g8. (a16) b8 + c4 (a8) a8. (gis16) a8 b4 gis8 e4. + g'4. g8. (fis16) e8 d4 b8 g8. (a16) b8 + c8. (b16) a8 gis8. (fis16) gis8 a4. a4. + } +} diff --git a/patacrep/data/examples/img/datadir.png b/patacrep/data/examples/img/datadir.png new file mode 100644 index 00000000..e2efe409 Binary files /dev/null and b/patacrep/data/examples/img/datadir.png differ diff --git a/patacrep/data/examples/root.ly b/patacrep/data/examples/root.ly new file mode 100644 index 00000000..1fd2bccb --- /dev/null +++ b/patacrep/data/examples/root.ly @@ -0,0 +1,19 @@ +\include "_lilypond/header" +\paper{paper-height = 6.5\cm} + +{ + \key a \minor + \time 6/8 + \partial 8 a'8 + \relative c''{ + c4 d8 e8. (f16) e8 d4 b8 g8. (a16) b8 + c4 a8 a8. (gis16) a8 b4 gis8 e4 a8 + c4 d8 e8. (f16 e8) d4 b8 g8. (a16) b8 + c8. (b16) a8 gis8. (fis16) gis8 a4 a8 a4. + + g'4. g8. (fis16) e8 d4 b8 g8. (a16) b8 + c4 (a8) a8. (gis16) a8 b4 gis8 e4. + g'4. g8. (fis16) e8 d4 b8 g8. (a16) b8 + c8. (b16) a8 gis8. (fis16) gis8 a4. a4. + } +} diff --git a/patacrep/data/examples/root.png b/patacrep/data/examples/root.png new file mode 100644 index 00000000..70ea3b7c Binary files /dev/null and b/patacrep/data/examples/root.png differ diff --git a/patacrep/data/examples/songs/chords.sgc b/patacrep/data/examples/songs/chords.sgc new file mode 100644 index 00000000..8779a140 --- /dev/null +++ b/patacrep/data/examples/songs/chords.sgc @@ -0,0 +1,23 @@ +{language: english} +{columns: 1} +{title: Chords testing} +{subtitle: Test of the chords specification and LaTeX translation} + +{define: E5 base-fret 7 frets 0 1 3 3 x x fingers - 1 2 3 - -} +{define: A frets x 0 2 2 2 0 fingers - - 1 2 3 -} +{define: C#sus4 base-fret 4 frets x x 3 3 4 1} +{define: Bb frets x 1 3 3 3 1} + +[A]Simple +[Bb]Bémol +[C#]Dièse +[Adim]dim +[Dmaj]maj +[Em3]m chiffre +[G4]Nombre +[Emaj3]maj et nombre +[Absus8]bémol, sus et nombre +[A/A]Deux notes +[F/Fb]Deux notes, bémol +[B/C#]Deux notes, dièse +[A/C# Dmaj]Plusieurs accords diff --git a/patacrep/data/examples/songs/errors.sgc b/patacrep/data/examples/songs/errors.sgc new file mode 100644 index 00000000..0b006cab --- /dev/null +++ b/patacrep/data/examples/songs/errors.sgc @@ -0,0 +1,13 @@ +{language : english} +{columns : 2} +{ title : Error} +{subtitle: A chordpro file with many errors} +{artist: Traditionnel} + +{define: H4 base-fret 7 frets 2} +{define:} + +Bla []bla +Bla [H]bla + + diff --git a/patacrep/data/examples/songs/greensleeves.sgc b/patacrep/data/examples/songs/greensleeves.sgc index d9c14627..e7a6d7cb 100644 --- a/patacrep/data/examples/songs/greensleeves.sgc +++ b/patacrep/data/examples/songs/greensleeves.sgc @@ -4,7 +4,7 @@ {subtitle: Test of the chordpro format} {artist: Traditionnel} {artist: Prénom Nom} -{cover : traditionnel } +{cover : traditionnel.jpg } {album :Angleterre} {partition : greensleeves.ly} @@ -41,7 +41,7 @@ And [Am]all this [E]cost I [Am]spent on thee {gc: test of guitar comment} -{image: traditionnel} +{image: traditionnel.jpg} Thy [Am]smock of silke, both [G]faire and white With [Am]gold embrodered [E]gorgeously diff --git a/patacrep/data/examples/songs/subdir/datadir.sg b/patacrep/data/examples/songs/subdir/datadir.sg new file mode 100644 index 00000000..18e92c3d --- /dev/null +++ b/patacrep/data/examples/songs/subdir/datadir.sg @@ -0,0 +1,10 @@ +\beginsong{Image included from datadir\\\LaTeX} + [cov={datadir}] + + \cover + + \lilypond{datadir.ly} + + \image{datadir} + +\endsong diff --git a/patacrep/data/examples/songs/subdir/datadir.sgc b/patacrep/data/examples/songs/subdir/datadir.sgc new file mode 100644 index 00000000..a209c229 --- /dev/null +++ b/patacrep/data/examples/songs/subdir/datadir.sgc @@ -0,0 +1,6 @@ +{title : Image included from datadir} +{subtitle: Chordpro} +{cover: datadir.png} + +{partition: datadir.ly} +{image: datadir.png} diff --git a/patacrep/data/examples/songs/subdir/relative.ly b/patacrep/data/examples/songs/subdir/relative.ly new file mode 100644 index 00000000..1fd2bccb --- /dev/null +++ b/patacrep/data/examples/songs/subdir/relative.ly @@ -0,0 +1,19 @@ +\include "_lilypond/header" +\paper{paper-height = 6.5\cm} + +{ + \key a \minor + \time 6/8 + \partial 8 a'8 + \relative c''{ + c4 d8 e8. (f16) e8 d4 b8 g8. (a16) b8 + c4 a8 a8. (gis16) a8 b4 gis8 e4 a8 + c4 d8 e8. (f16 e8) d4 b8 g8. (a16) b8 + c8. (b16) a8 gis8. (fis16) gis8 a4 a8 a4. + + g'4. g8. (fis16) e8 d4 b8 g8. (a16) b8 + c4 (a8) a8. (gis16) a8 b4 gis8 e4. + g'4. g8. (fis16) e8 d4 b8 g8. (a16) b8 + c8. (b16) a8 gis8. (fis16) gis8 a4. a4. + } +} diff --git a/patacrep/data/examples/songs/subdir/relative.png b/patacrep/data/examples/songs/subdir/relative.png new file mode 100644 index 00000000..ff1b083e Binary files /dev/null and b/patacrep/data/examples/songs/subdir/relative.png differ diff --git a/patacrep/data/examples/songs/subdir/relative.sg b/patacrep/data/examples/songs/subdir/relative.sg new file mode 100644 index 00000000..681b4086 --- /dev/null +++ b/patacrep/data/examples/songs/subdir/relative.sg @@ -0,0 +1,10 @@ +\beginsong{Image included from song directory\\\LaTeX} + [cov={relative}] + + \cover + + \lilypond{relative.ly} + + \image{relative} + +\endsong diff --git a/patacrep/data/examples/songs/subdir/relative.sgc b/patacrep/data/examples/songs/subdir/relative.sgc new file mode 100644 index 00000000..73241352 --- /dev/null +++ b/patacrep/data/examples/songs/subdir/relative.sgc @@ -0,0 +1,6 @@ +{title : Image included from song directory} +{subtitle: Chordpro} +{cover: relative.png} + +{partition: relative.ly} +{image: relative.png} diff --git a/patacrep/data/examples/songs/subdir/root.sg b/patacrep/data/examples/songs/subdir/root.sg new file mode 100644 index 00000000..2e4a11b0 --- /dev/null +++ b/patacrep/data/examples/songs/subdir/root.sg @@ -0,0 +1,10 @@ +\beginsong{Image included from root directory\\\LaTeX} + [cov={root}] + + \cover + + \lilypond{root.ly} + + \image{root} + +\endsong diff --git a/patacrep/data/examples/songs/subdir/root.sgc b/patacrep/data/examples/songs/subdir/root.sgc new file mode 100644 index 00000000..0aa21297 --- /dev/null +++ b/patacrep/data/examples/songs/subdir/root.sgc @@ -0,0 +1,6 @@ +{title : Image included from root directory} +{subtitle: Chordpro} +{cover: root.png} + +{partition: root.ly} +{image: root.png} diff --git a/patacrep/data/latex/patacrep.sty b/patacrep/data/latex/patacrep.sty index 019de15f..f3218005 100644 --- a/patacrep/data/latex/patacrep.sty +++ b/patacrep/data/latex/patacrep.sty @@ -11,9 +11,9 @@ \RequirePackage{fancybox} \RequirePackage{xstring} \RequirePackage{framed} -\RequirePackage{currfile} \RequirePackage{ifthen} \RequirePackage{tikz} +\RequirePackage{import} % tabs: display the guitar tabs \newif{\iftabs} @@ -134,8 +134,7 @@ \setlength{\coverspace}{0.1cm} \newcommand{\songcover}{} \newcommand{\songalbum}{} -\newsongkey{cov}{\let\songcover\@empty}{\def\songcover{\currfiledir#1}} -\newsongkey{vcov}{\let\songcover\@empty}{\def\songcover{#1}} +\newsongkey{cov}{\let\songcover\@empty}{\def\songcover{#1}} \newsongkey{album}{\let\songalbum\@empty}{\def\songalbum{#1}} \newsongkey{url}{\let\songurl\@empty}{\def\songurl{#1}} \newsongkey{original}{\let\songoriginal\@empty}{\def\songoriginal{#1}} @@ -247,11 +246,6 @@ \newcommand{\lilypond}[1]{% \iflilypond% \epstopdfsetup{suffix=-\the\hsize-converted} - \includegraphics{\currfiledir#1}% - \fi% -} -\newcommand{\vlilypond}[1]{% - \iflilypond% \includegraphics{#1}% \fi% } diff --git a/patacrep/data/templates/default.tex b/patacrep/data/templates/default.tex index 5f40d2d9..65c56c8f 100644 --- a/patacrep/data/templates/default.tex +++ b/patacrep/data/templates/default.tex @@ -1,23 +1,22 @@ -%! Copyright (C) 2014 The Patacrep team (www.patacrep.com) -%! -%! This program is free software; you can redistribute it and/or -%! modify it under the terms of the GNU General Public License -%! as published by the Free Software Foundation; either version 2 -%! of the License, or (at your option) any later version. -%! -%! This program is distributed in the hope that it will be useful, -%! but WITHOUT ANY WARRANTY; without even the implied warranty of -%! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -%! GNU General Public License for more details. -%! -%! You should have received a copy of the GNU General Public License -%! along with this program; if not, write to the Free Software -%! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -%! MA 02110-1301, USA. -%! -%! The latest version of this program can be obtained from -%! https://github.com/patacrep/ - +%!- Copyright (C) 2014 The Patacrep team (www.patacrep.com) +%!- +%!- This program is free software; you can redistribute it and/or +%!- modify it under the terms of the GNU General Public License +%!- as published by the Free Software Foundation; either version 2 +%!- of the License, or (at your option) any later version. +%!- +%!- This program is distributed in the hope that it will be useful, +%!- but WITHOUT ANY WARRANTY; without even the implied warranty of +%!- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%!- GNU General Public License for more details. +%!- +%!- You should have received a copy of the GNU General Public License +%!- along with this program; if not, write to the Free Software +%!- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +%!- MA 02110-1301, USA. +%!- +%!- The latest version of this program can be obtained from +%!- https://github.com/patacrep/ (* variables *) { @@ -40,47 +39,49 @@ "default": {"default": "alphascale", "french": "solfedge"} } } -(* endvariables *) +(* endvariables -*) -(* extends "songs.tex" *) -(* set indexes = "titleidx,authidx" *) +(*- extends "songs.tex" -*) +(*- set indexes = "titleidx,authidx" -*) (* block documentclass *) -\documentclass[(* for option in classoptions *) - ((option)), - (* endfor *)]{article} +\documentclass[ + (* for option in classoptions *) + ((option)), + (* endfor *) + ]{article} (* endblock *) (* block songbookpreambule *) - (( super() )) +(( super() )) - \usepackage{chords} +\usepackage{chords} - \title{((title))} - \author{((author))} +\title{((title))} +\author{((author))} - \newindex{titleidx}{((filename))_title} - \newauthorindex{authidx}{((filename))_auth} +\newindex{titleidx}{((filename))_title} +\newauthorindex{authidx}{((filename))_auth} - (* for prefix in titleprefixwords *) - \titleprefixword{((prefix))} - (* endfor*) - (* for word in authwords.ignore *) - \authignoreword{((word))} - (* endfor *) - (* for word in authwords.after *) - \authbyword{((word))} - (* endfor *) - (* for word in authwords.sep *) - \authsepword{((word))} - (* endfor *) +(* for prefix in titleprefixwords -*) + \titleprefixword{((prefix))} +(* endfor*) +(* for word in authwords.ignore -*) + \authignoreword{((word))} +(* endfor *) +(* for word in authwords.after -*) + \authbyword{((word))} +(* endfor *) +(* for word in authwords.sep -*) + \authsepword{((word))} +(* endfor *) - (* if notenamesout=="alphascale" *) - \notenamesout{A}{B}{C}{D}{E}{F}{G} - (* else *) - \notenamesout{La}{Si}{Do}{R\'e}{Mi}{Fa}{Sol} - (* endif *) +(* if notenamesout=="alphascale" -*) + \notenamesout{A}{B}{C}{D}{E}{F}{G} +(* else -*) + \notenamesout{La}{Si}{Do}{R\'e}{Mi}{Fa}{Sol} +(* endif *) (* endblock *) (* block title *) @@ -88,18 +89,18 @@ (* endblock *) (* block index *) - \showindex{\songindexname}{titleidx} - \showindex{\authorindexname}{authidx} +\showindex{\songindexname}{titleidx} +\showindex{\authorindexname}{authidx} (* endblock *) (* block chords *) - % list of chords - \ifchorded - \ifdiagram - \phantomsection - \addcontentsline{toc}{section}{\chordlistname} - \chords - \fi - \fi +% list of chords +\ifchorded + \ifdiagram + \phantomsection + \addcontentsline{toc}{section}{\chordlistname} + \chords + \fi +\fi (* endblock *) diff --git a/patacrep/data/templates/layout.tex b/patacrep/data/templates/layout.tex index f525abd3..ae23d681 100644 --- a/patacrep/data/templates/layout.tex +++ b/patacrep/data/templates/layout.tex @@ -1,23 +1,22 @@ -%! Copyright (C) 2014 The Patacrep team (www.patacrep.com) -%! -%! This program is free software; you can redistribute it and/or -%! modify it under the terms of the GNU General Public License -%! as published by the Free Software Foundation; either version 2 -%! of the License, or (at your option) any later version. -%! -%! This program is distributed in the hope that it will be useful, -%! but WITHOUT ANY WARRANTY; without even the implied warranty of -%! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -%! GNU General Public License for more details. -%! -%! You should have received a copy of the GNU General Public License -%! along with this program; if not, write to the Free Software -%! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -%! MA 02110-1301, USA. -%! -%! The latest version of this program can be obtained from -%! https://github.com/patacrep/ - +%!- Copyright (C) 2014 The Patacrep team (www.patacrep.com) +%!- +%!- This program is free software; you can redistribute it and/or +%!- modify it under the terms of the GNU General Public License +%!- as published by the Free Software Foundation; either version 2 +%!- of the License, or (at your option) any later version. +%!- +%!- This program is distributed in the hope that it will be useful, +%!- but WITHOUT ANY WARRANTY; without even the implied warranty of +%!- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%!- GNU General Public License for more details. +%!- +%!- You should have received a copy of the GNU General Public License +%!- along with this program; if not, write to the Free Software +%!- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +%!- MA 02110-1301, USA. +%!- +%!- The latest version of this program can be obtained from +%!- https://github.com/patacrep/ %% Automatically generated document. %% You may edit this file but all changes will be overwritten. @@ -27,10 +26,11 @@ %% Generated using Songbook \makeatletter -\def\input@path{(* for dir in datadir *) - {(( path2posix(dir) ))/latex/} % - (* endfor *) - } +\def\input@path{ % + (* for dir in datadir *) + {(( path2posix(dir) ))/latex/} % + (* endfor *) +} \makeatother (* block documentclass *) @@ -41,9 +41,9 @@ (* endblock *) (* block songbookpreambule *) - \usepackage[utf8]{inputenc} - \usepackage[T1]{fontenc} - \usepackage{lmodern} +\usepackage[utf8]{inputenc} +\usepackage[T1]{fontenc} +\usepackage{lmodern} (* endblock songbookpreambule *) (* block preambule *) @@ -71,4 +71,4 @@ \end{document} -%! End of file +%!- End of file diff --git a/patacrep/data/templates/patacrep.tex b/patacrep/data/templates/patacrep.tex index 21a84e64..96367078 100644 --- a/patacrep/data/templates/patacrep.tex +++ b/patacrep/data/templates/patacrep.tex @@ -1,23 +1,22 @@ -%! Copyright (C) 2014 The Patacrep team (www.patacrep.com) -%! -%! This program is free software; you can redistribute it and/or -%! modify it under the terms of the GNU General Public License -%! as published by the Free Software Foundation; either version 2 -%! of the License, or (at your option) any later version. -%! -%! This program is distributed in the hope that it will be useful, -%! but WITHOUT ANY WARRANTY; without even the implied warranty of -%! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -%! GNU General Public License for more details. -%! -%! You should have received a copy of the GNU General Public License -%! along with this program; if not, write to the Free Software -%! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -%! MA 02110-1301, USA. -%! -%! The latest version of this program can be obtained from -%! https://github.com/patacrep/ - +%!- Copyright (C) 2014 The Patacrep team (www.patacrep.com) +%!- +%!- This program is free software; you can redistribute it and/or +%!- modify it under the terms of the GNU General Public License +%!- as published by the Free Software Foundation; either version 2 +%!- of the License, or (at your option) any later version. +%!- +%!- This program is distributed in the hope that it will be useful, +%!- but WITHOUT ANY WARRANTY; without even the implied warranty of +%!- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%!- GNU General Public License for more details. +%!- +%!- You should have received a copy of the GNU General Public License +%!- along with this program; if not, write to the Free Software +%!- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +%!- MA 02110-1301, USA. +%!- +%!- The latest version of this program can be obtained from +%!- https://github.com/patacrep/ (* variables *) { @@ -61,21 +60,25 @@ "Des", "El", "Les", "Ma", "Mon", "Un"]} } } -(* endvariables *) +(* endvariables -*) -(* extends "default.tex" *) +(*- extends "default.tex" -*) (* block songbookpackages *) %! booktype, bookoptions and instruments are defined in "songs.tex" -\usepackage[((booktype)), - (* for option in bookoptions *)((option)), - (* endfor *) - (* for instrument in instruments *)((instrument)), - (* endfor *)]{crepbook} +\usepackage[ + ((booktype)), + (* for option in bookoptions *) + ((option)), + (* endfor *) + (* for instrument in instruments *) + ((instrument)), + (* endfor *) + ]{crepbook} (* endblock *) (* block songbookpreambule *) - \usepackage[ +\usepackage[ a4paper % paper size ,includeheadfoot % include header and footer into text size ,hmarginratio=1:1 % ratio between inner and outer margin (default) @@ -84,35 +87,37 @@ ,bmargin=1.3cm % bottom margin ]{geometry} - (( super() )) +(( super() )) - \pagestyle{empty} +\pagestyle{empty} - \definecolor{SongNumberBgColor}{HTML}{((songnumberbgcolor))} - \definecolor{NoteBgColor}{HTML}{((notebgcolor))} - \definecolor{IndexBgColor}{HTML}{((indexbgcolor))} +\definecolor{SongNumberBgColor}{HTML}{((songnumberbgcolor))} +\definecolor{NoteBgColor}{HTML}{((notebgcolor))} +\definecolor{IndexBgColor}{HTML}{((indexbgcolor))} - \renewcommand{\snumbgcolor}{SongNumberBgColor} - \renewcommand{\notebgcolor}{NoteBgColor} - \renewcommand{\idxbgcolor}{IndexBgColor} +\renewcommand{\snumbgcolor}{SongNumberBgColor} +\renewcommand{\notebgcolor}{NoteBgColor} +\renewcommand{\idxbgcolor}{IndexBgColor} - \definecolor{tango-green-3}{HTML}{4e9a06} - \definecolor{tango-blue-3}{HTML}{204a87} - \usepackage[bookmarks, - bookmarksopen, - hyperfigures=true, - colorlinks=true, - linkcolor=tango-green-3, - urlcolor=tango-blue-3]{hyperref} +\definecolor{tango-green-3}{HTML}{4e9a06} +\definecolor{tango-blue-3}{HTML}{204a87} +\usepackage[ + bookmarks, + bookmarksopen, + hyperfigures=true, + colorlinks=true, + linkcolor=tango-green-3, + urlcolor=tango-blue-3 + ]{hyperref} - \subtitle{((subtitle))} - (* if version!="undefined" *) - \version{((version))} - (* endif *) - \mail{((mail))} - \web{((web))} - \picture{((picture))} - \picturecopyright{((picturecopyright))} - \footer{((footer))} +\subtitle{((subtitle))} +(* if version!="undefined" -*) + \version{((version))} +(* endif *) +\mail{((mail))} +\web{((web))} +\picture{((picture))} +\picturecopyright{((picturecopyright))} +\footer{((footer))} (* endblock *) diff --git a/patacrep/data/templates/songs.tex b/patacrep/data/templates/songs.tex index 802c216d..bdfcf7bb 100644 --- a/patacrep/data/templates/songs.tex +++ b/patacrep/data/templates/songs.tex @@ -1,22 +1,22 @@ -%! Copyright (C) 2014 The Patacrep team (www.patacrep.com) -%! -%! This program is free software; you can redistribute it and/or -%! modify it under the terms of the GNU General Public License -%! as published by the Free Software Foundation; either version 2 -%! of the License, or (at your option) any later version. -%! -%! This program is distributed in the hope that it will be useful, -%! but WITHOUT ANY WARRANTY; without even the implied warranty of -%! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -%! GNU General Public License for more details. -%! -%! You should have received a copy of the GNU General Public License -%! along with this program; if not, write to the Free Software -%! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -%! MA 02110-1301, USA. -%! -%! The latest version of this program can be obtained from -%! https://github.com/patacrep/ +%!- Copyright (C) 2014 The Patacrep team (www.patacrep.com) +%!- +%!- This program is free software; you can redistribute it and/or +%!- modify it under the terms of the GNU General Public License +%!- as published by the Free Software Foundation; either version 2 +%!- of the License, or (at your option) any later version. +%!- +%!- This program is distributed in the hope that it will be useful, +%!- but WITHOUT ANY WARRANTY; without even the implied warranty of +%!- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%!- GNU General Public License for more details. +%!- +%!- You should have received a copy of the GNU General Public License +%!- along with this program; if not, write to the Free Software +%!- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +%!- MA 02110-1301, USA. +%!- +%!- The latest version of this program can be obtained from +%!- https://github.com/patacrep/ (* variables *) { @@ -63,48 +63,51 @@ "default": {"default": {}} } } -(* endvariables *) +(* endvariables -*) -(* extends "layout.tex" *) +(*- extends "layout.tex" -*) (* block songbookpackages *) -\usepackage[((booktype)), - (* for option in bookoptions *)((option)), - (* endfor *) - (* for instrument in instruments *)((instrument)), - (* endfor *)]{patacrep} +\usepackage[ + ((booktype)), + (* for option in bookoptions *)((option)), + (* endfor *) + (* for instrument in instruments *)((instrument)), + (* endfor *) + ]{patacrep} (* endblock *) (* block songbookpreambule *) - (( super() )) +(( super() )) - (* for lang in _languages *) - \PassOptionsToPackage{((lang))}{babel} - (* endfor *) - \usepackage[((lang))]{babel} - \lang{((lang))} +(* for lang in _languages -*) + \PassOptionsToPackage{((lang))}{babel} +(* endfor *) +\usepackage[((lang))]{babel} +\lang{((lang))} - \usepackage{graphicx} - \graphicspath{(* for dir in datadir *) - {(( path2posix(dir) ))/img/} % - (* endfor *) - } +\usepackage{graphicx} +\graphicspath{ % + (* for dir in datadir *) + {(( path2posix(dir) ))/img/} % + (* endfor *) +} - \makeatletter - \@ifpackageloaded{hyperref}{}{ - \usepackage{url} - \newcommand{\phantomsection}{} - \newcommand{\hyperlink}[2]{#2} - \newcommand{\href}[2]{\expandafter\url\expandafter{#1}} - } - \makeatother +\makeatletter +\@ifpackageloaded{hyperref}{}{ + \usepackage{url} + \newcommand{\phantomsection}{} + \newcommand{\hyperlink}[2]{#2} + \newcommand{\href}[2]{\expandafter\url\expandafter{#1}} +} +\makeatother (* endblock *) (* block songs *) - \phantomsection - \addcontentsline{toc}{section}{\songlistname} +\phantomsection +\addcontentsline{toc}{section}{\songlistname} - ((render_content(content) )) +(( render(content) )) (* endblock *) diff --git a/patacrep/songs/__init__.py b/patacrep/songs/__init__.py index 2afbb8b5..fbf02e36 100644 --- a/patacrep/songs/__init__.py +++ b/patacrep/songs/__init__.py @@ -10,7 +10,6 @@ import re from patacrep.authors import process_listauthors from patacrep import files, encoding -from patacrep.content import Content LOGGER = logging.getLogger(__name__) @@ -63,25 +62,25 @@ class DataSubpath(object): return self # pylint: disable=too-many-instance-attributes -class Song(Content): +class Song: """Song (or song metadata) This class represents a song, bound to a file. - It can parse the file given in arguments. - - It can render the song as some LaTeX code. + - It can render the song as some code (LaTeX, chordpro, depending on subclasses implemetation). - Its content is cached, so that if the file has not been changed, the file is not parsed again. This class is inherited by classes implementing song management for several file formats. Those subclasses must implement: - `parse()` to parse the file; - - `render()` to render the song as LaTeX code. + - `render()` to render the song as code. """ # Version format of cached song. Increment this number if we update # information stored in cache. - CACHE_VERSION = 1 + CACHE_VERSION = 2 # List of attributes to cache cached_attributes = [ @@ -144,7 +143,7 @@ class Song(Content): ] self.authors = process_listauthors( self.authors, - **config["_compiled_authwords"] + **config.get("_compiled_authwords", {}) ) # Cache management @@ -166,12 +165,16 @@ class Song(Content): def __repr__(self): return repr((self.titles, self.data, self.fullpath)) - def tex(self, output): # pylint: disable=no-self-use, unused-argument - """Return the LaTeX code rendering this song. + def render(self, output, output_format): + """Return the code rendering this song. Arguments: - output: Name of the output file. + - output_format: Format of the output file (latex, chordpro...) """ + method = "render_{}".format(output_format) + if hasattr(self, method): + return getattr(self, method)(output) raise NotImplementedError() def parse(self, config): # pylint: disable=no-self-use @@ -199,3 +202,39 @@ 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 cb0be42a..ae37b79b 100644 --- a/patacrep/songs/chordpro/__init__.py +++ b/patacrep/songs/chordpro/__init__.py @@ -5,16 +5,16 @@ import pkg_resources import os from patacrep import encoding, files -from patacrep.songs import Song +from patacrep.songs import Song, search_image from patacrep.songs.chordpro.syntax import parse_song -from patacrep.templates import TexRenderer +from patacrep.templates import Renderer class ChordproSong(Song): """Chordpros song parser.""" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - self.texenv = None + self.jinjaenv = None def parse(self, config): """Parse content, and return the dictionary of song data.""" @@ -22,42 +22,46 @@ class ChordproSong(Song): song = parse_song(song.read(), self.fullpath) self.authors = song.authors self.titles = song.titles - self.languages = song.get_directives('language') - self.data = dict([meta.as_tuple for meta in song.meta]) + self.languages = song.get_data_argument('language', [self.config['lang']]) + self.data = song.meta self.cached = { 'song': song, } - def tex(self, output): + def render(self, output, output_format): context = { - 'language': self.cached['song'].get_directive('language', self.config['lang']), - 'columns': self.cached['song'].get_directive('columns', 1), + 'language': self.languages[0], "path": files.relpath(self.fullpath, os.path.dirname(output)), - "titles": r"\\".join(self.titles), - "authors": ", ".join(["{} {}".format(name[1], name[0]) for name in self.authors]), + "titles": self.titles, + "authors": self.authors, "metadata": self.data, - "beginsong": self.cached['song'].meta_beginsong(), - "render": self.render_tex, + "render": self._render_ast, + "config": self.config, } - self.texenv = Environment(loader=FileSystemLoader(os.path.join( + self.jinjaenv = Environment(loader=FileSystemLoader(os.path.join( os.path.abspath(pkg_resources.resource_filename(__name__, 'data')), - 'latex' + output_format, ))) - return self.render_tex(context, self.cached['song'].content, template="chordpro.tex") + self.jinjaenv.filters['search_image'] = search_image + return self._render_ast( + context, + self.cached['song'].content, + template="song", + ) @contextfunction - def render_tex(self, context, content, template=None): - """Render ``content`` as tex.""" + 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('tex') - return TexRenderer( + template = content.template() + return Renderer( template=template, encoding='utf8', - texenv=self.texenv, + jinjaenv=self.jinjaenv, ).template.render(context) SONG_PARSERS = { diff --git a/patacrep/songs/chordpro/ast.py b/patacrep/songs/chordpro/ast.py index b82b46a9..5cffbb86 100644 --- a/patacrep/songs/chordpro/ast.py +++ b/patacrep/songs/chordpro/ast.py @@ -2,12 +2,43 @@ # pylint: disable=too-few-public-methods -import functools import logging -import os LOGGER = logging.getLogger() +class OrderedLifoDict: + """Ordered (LIFO) dictionary. + + Mimics the :class:`dict` dictionary, with: + - dictionary is ordered: the order the keys are kept (as with + :class:`collections.OrderedDict`), excepted that: + - LIFO: the last item is reterned first when iterating. + """ + + def __init__(self, default=None): + if default is None: + self._keys = [] + self._values = {} + else: + self._keys = list(default.keys()) + self._values = default.copy() + + def values(self): + """Same as :meth:`dict.values`.""" + for key in self: + yield self._values[key] + + def __iter__(self): + yield from self._keys + + def __setitem__(self, key, value): + if key not in self._keys: + self._keys.insert(0, key) + self._values[key] = value + + def __getitem__(self, key): + return self._values[key] + def _indent(string): """Return and indented version of argument.""" return "\n".join([" {}".format(line) for line in string.split('\n')]) @@ -21,15 +52,6 @@ INLINE_PROPERTIES = { "image", } -#: List of properties that are listed in the `\beginsong` LaTeX directive. -BEGINSONG_PROPERTIES = { - "album", - "copyright", - "cov", - "vcov", - "tag", - } - #: Some directive have alternative names. For instance `{title: Foo}` and `{t: #: Foo}` are equivalent. DIRECTIVE_SHORTCUTS = { @@ -40,7 +62,6 @@ DIRECTIVE_SHORTCUTS = { "c": "comment", "gc": "guitar_comment", "cover": "cov", - "vcover": "vcov", } def directive_name(text): @@ -53,14 +74,17 @@ class AST: _template = None inline = False - def template(self, extension): + def template(self): """Return the template to be used to render this object.""" if self._template is None: LOGGER.warning("No template defined for {}.".format(self.__class__)) base = "error" else: base = self._template - return "content_{}.{}".format(base, extension) + return "content_{}".format(base) + +class Error(AST): + """Parsing error. To be ignored.""" class Line(AST): """A line is a sequence of (possibly truncated) words, spaces and chords.""" @@ -76,9 +100,6 @@ class Line(AST): self.line.insert(0, data) return self - def __str__(self): - return "".join([str(item) for item in self.line]) - def strip(self): """Remove spaces at the beginning and end of line.""" while True: @@ -94,6 +115,7 @@ class Line(AST): class LineElement(AST): """Something present on a line.""" + # pylint: disable=abstract-method pass class Word(LineElement): @@ -104,9 +126,6 @@ class Word(LineElement): super().__init__() self.value = value - def __str__(self): - return self.value - class Space(LineElement): """A space between words""" _template = "space" @@ -114,20 +133,21 @@ class Space(LineElement): def __init__(self): super().__init__() - def __str__(self): - return " " +class ChordList(LineElement): + """A list of chords.""" + _template = "chordlist" + + def __init__(self, *chords): + self.chords = chords -class Chord(LineElement): +class Chord(AST): """A chord.""" _template = "chord" - def __init__(self, value): - super().__init__() - self.value = value - - def __str__(self): - return "[{}]".format(self.value) + def __init__(self, chord): + # pylint: disable=too-many-arguments + self.chord = chord class Verse(AST): """A verse (or bridge, or chorus)""" @@ -144,12 +164,6 @@ class Verse(AST): self.lines.insert(0, data) return self - def __str__(self): - return '{{start_of_{type}}}\n{content}\n{{end_of_{type}}}'.format( - type=self.type, - content=_indent("\n".join([str(line) for line in self.lines])), - ) - class Chorus(Verse): """Chorus""" type = 'chorus' @@ -167,30 +181,23 @@ class Song(AST): - titles: The list of titles - language: The language (if set), None otherwise - authors: The list of authors - - meta_beginsong: The list of directives that are to be set in the - `\beginsong{}` LaTeX directive. - meta: Every other metadata. """ #: Some directives are added to the song using special methods. - METADATA_TYPE = { + METADATA_ADD = { "title": "add_title", "subtitle": "add_subtitle", "artist": "add_author", "key": "add_key", - } - - #: Some directives have to be processed before being considered. - PROCESS_DIRECTIVE = { - "cov": "_process_relative", - "partition": "_process_relative", - "image": "_process_relative", + "define": "add_cumulative", + "language": "add_cumulative", } def __init__(self, filename): super().__init__() self.content = [] - self.meta = [] + self.meta = OrderedLifoDict() self._authors = [] self._titles = [] self._subtitles = [] @@ -199,13 +206,9 @@ class Song(AST): def add(self, data): """Add an element to the song""" - if isinstance(data, Directive): - # Some directives are preprocessed - name = directive_name(data.keyword) - if name in self.PROCESS_DIRECTIVE: - data = getattr(self, self.PROCESS_DIRECTIVE[name])(data) - - if data is None: + if isinstance(data, Error): + return self + elif data is None: # New line if not (self.content and isinstance(self.content[0], Newline)): self.content.insert(0, Newline()) @@ -219,127 +222,78 @@ class Song(AST): self.content.insert(0, data) elif isinstance(data, Directive): # Add a metadata directive. Some of them are added using special - # methods listed in ``METADATA_TYPE``. - name = directive_name(data.keyword) - if name in self.METADATA_TYPE: - getattr(self, self.METADATA_TYPE[name])(*data.as_tuple) + # methods listed in ``METADATA_ADD``. + if data.keyword in self.METADATA_ADD: + getattr(self, self.METADATA_ADD[data.keyword])(data) else: - self.meta.append(data) + self.meta[data.keyword] = data else: raise Exception() return self - def str_meta(self): - """Return an iterator over *all* metadata, as strings.""" - for title in self.titles: - yield "{{title: {}}}".format(title) - for author in self.authors: - yield "{{by: {}}}".format(author) - for key in sorted(self.keys): - yield "{{key: {}}}".format(str(key)) - for key in sorted(self.meta): - yield str(key) + def add_title(self, data): + """Add a title""" + self._titles.insert(0, data.argument) + + def add_cumulative(self, data): + """Add a cumulative argument into metadata""" + if data.keyword not in self.meta: + self.meta[data.keyword] = [] + self.meta[data.keyword].insert(0, data) - def __str__(self): - return ( - "\n".join(self.str_meta()).strip() - + - "\n========\n" - + - "\n".join([str(item) for item in self.content]).strip() - ) + def get_data_argument(self, keyword, default): + """Return `self.meta[keyword].argument`. + Return `default` if `self.meta[keyword]` does not exist. - def add_title(self, __ignored, title): - """Add a title""" - self._titles.insert(0, title) + If `self.meta[keyword]` is a list, return the list of `item.argument` + for each item in the list. + """ + if keyword not in self.meta: + return default + if isinstance(self.meta[keyword], list): + return [item.argument for item in self.meta[keyword]] + else: + return self.meta[keyword].argument - def add_subtitle(self, __ignored, title): + def add_subtitle(self, data): """Add a subtitle""" - self._subtitles.insert(0, title) + self._subtitles.insert(0, data.argument) @property def titles(self): """Return the list of titles (and subtitles).""" return self._titles + self._subtitles - def add_author(self, __ignored, title): + def add_author(self, data): """Add an auhor.""" - self._authors.insert(0, title) + self._authors.insert(0, data.argument) @property def authors(self): """Return the list of (raw) authors.""" return self._authors - def get_directive(self, key, default=None): - """Return the first directive with a given key.""" - for directive in self.meta: - if directive.keyword == directive_name(key): - return directive.argument - return default - - def get_directives(self, key): - """Return the list of directives with a given key.""" - values = [] - for directive in self.meta: - if directive.keyword == directive_name(key): - values.append(directive.argument) - return values - - def add_key(self, __ignored, argument): + def add_key(self, data): """Add a new {key: foo: bar} directive.""" - key, *argument = argument.split(":") - self._keys.append(Directive( + key, *argument = data.argument.split(":") + if 'keys' not in self.meta: + self.meta['keys'] = [] + self.meta['keys'].insert(0, Directive( key.strip(), ":".join(argument).strip(), )) - @property - def keys(self): - """Return the list of keys. - - That is, directive that where given of the form ``{key: foo: bar}``. - """ - return self._keys - - def meta_beginsong(self): - r"""Return the meta information to be put in \beginsong.""" - for directive in BEGINSONG_PROPERTIES: - if self.get_directive(directive) is not None: - yield (directive, self.get_directive(directive)) - for (key, value) in self.keys: - yield (key, value) - - - def _process_relative(self, directive): - """Return the directive, in which the argument is given relative to file - - This argument is expected to be a path (as a string). - """ - return Directive( - directive.keyword, - os.path.join( - os.path.dirname(self.filename), - directive.argument, - ), - ) - class Newline(AST): """New line""" _template = "newline" - def __str__(self): - return "" - -@functools.total_ordering class Directive(AST): """A directive""" - def __init__(self, keyword="", argument=None): + def __init__(self, keyword, argument=None): super().__init__() - self._keyword = None - self.keyword = keyword + self.keyword = directive_name(keyword.strip()) self.argument = argument @property @@ -350,49 +304,47 @@ class Directive(AST): """ return self.keyword - @property - def keyword(self): - """Keyword of the directive.""" - return self._keyword - @property def inline(self): """True iff this directive is to be rendered in the flow on the song. """ return self.keyword in INLINE_PROPERTIES - @keyword.setter - def keyword(self, value): - """self.keyword setter - - Replace keyword by its canonical name if it is a shortcut. - """ - self._keyword = directive_name(value.strip()) - def __str__(self): - if self.argument is not None: - return "{{{}: {}}}".format( - self.keyword, - self.argument, - ) - else: - return "{{{}}}".format(self.keyword) + return self.argument - @property - def as_tuple(self): - """Return the directive as a tuple.""" - return (self.keyword, self.argument) +class Define(Directive): + """A chord definition. + + Attributes: - def __eq__(self, other): - return self.as_tuple == other.as_tuple + .. attribute:: key + The key, as a :class:`Chord` object. + .. attribute:: basefret + The base fret, as an integer. Can be `None` if no base fret is defined. + .. attribute:: frets + The list of frets, as a list of integers, or `None`, if this fret is not to be played. + .. attribute:: fingers + The list of fingers to use on frets, as a list of integers, or `None` + if no information is given (this string is not played, or is played + open). Can be `None` if not defined. + """ + + def __init__(self, key, basefret, frets, fingers): + self.key = key + self.basefret = basefret # Can be None + self.frets = frets + self.fingers = fingers # Can be None + super().__init__("define", None) - def __lt__(self, other): - return self.as_tuple < other.as_tuple + def __str__(self): + return None class Tab(AST): """Tablature""" inline = True + _template = "tablature" def __init__(self): super().__init__() @@ -402,9 +354,3 @@ class Tab(AST): """Add an element at the beginning of content.""" self.content.insert(0, data) return self - - def __str__(self): - return '{{start_of_tab}}\n{}\n{{end_of_tab}}'.format( - _indent("\n".join(self.content)), - ) - diff --git a/patacrep/songs/chordpro/data/chordpro/content_chord b/patacrep/songs/chordpro/data/chordpro/content_chord new file mode 100644 index 00000000..7d5ec6ca --- /dev/null +++ b/patacrep/songs/chordpro/data/chordpro/content_chord @@ -0,0 +1 @@ +((- content.chord -)) diff --git a/patacrep/songs/chordpro/data/chordpro/content_chordlist b/patacrep/songs/chordpro/data/chordpro/content_chordlist new file mode 100644 index 00000000..8bcd3410 --- /dev/null +++ b/patacrep/songs/chordpro/data/chordpro/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/chordpro/content_comment b/patacrep/songs/chordpro/data/chordpro/content_comment new file mode 100644 index 00000000..07381cdf --- /dev/null +++ b/patacrep/songs/chordpro/data/chordpro/content_comment @@ -0,0 +1 @@ +{comment: (( content.argument ))} diff --git a/patacrep/songs/chordpro/data/chordpro/content_define b/patacrep/songs/chordpro/data/chordpro/content_define new file mode 100644 index 00000000..47a93abf --- /dev/null +++ b/patacrep/songs/chordpro/data/chordpro/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/chordpro/content_error b/patacrep/songs/chordpro/data/chordpro/content_error new file mode 100644 index 00000000..bbdb95fd --- /dev/null +++ b/patacrep/songs/chordpro/data/chordpro/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/chordpro/content_guitar_comment b/patacrep/songs/chordpro/data/chordpro/content_guitar_comment new file mode 100644 index 00000000..1ca0c269 --- /dev/null +++ b/patacrep/songs/chordpro/data/chordpro/content_guitar_comment @@ -0,0 +1 @@ +{guitar_comment: (( content.argument ))} diff --git a/patacrep/songs/chordpro/data/chordpro/content_image b/patacrep/songs/chordpro/data/chordpro/content_image new file mode 100644 index 00000000..58e7f904 --- /dev/null +++ b/patacrep/songs/chordpro/data/chordpro/content_image @@ -0,0 +1 @@ +{image: (( content.argument ))} diff --git a/patacrep/songs/chordpro/data/chordpro/content_line b/patacrep/songs/chordpro/data/chordpro/content_line new file mode 100644 index 00000000..03ca80b7 --- /dev/null +++ b/patacrep/songs/chordpro/data/chordpro/content_line @@ -0,0 +1,3 @@ +(* for item in content.line -*) + (( render(item) )) +(*- endfor *) diff --git a/patacrep/songs/chordpro/data/latex/content_newline.tex b/patacrep/songs/chordpro/data/chordpro/content_newline similarity index 100% rename from patacrep/songs/chordpro/data/latex/content_newline.tex rename to patacrep/songs/chordpro/data/chordpro/content_newline diff --git a/patacrep/songs/chordpro/data/chordpro/content_partition b/patacrep/songs/chordpro/data/chordpro/content_partition new file mode 100644 index 00000000..362c4f64 --- /dev/null +++ b/patacrep/songs/chordpro/data/chordpro/content_partition @@ -0,0 +1 @@ +{partition: ((content.argument))} diff --git a/patacrep/songs/chordpro/data/latex/content_space.tex b/patacrep/songs/chordpro/data/chordpro/content_space similarity index 100% rename from patacrep/songs/chordpro/data/latex/content_space.tex rename to patacrep/songs/chordpro/data/chordpro/content_space diff --git a/patacrep/songs/chordpro/data/chordpro/content_tablature b/patacrep/songs/chordpro/data/chordpro/content_tablature new file mode 100644 index 00000000..1036924b --- /dev/null +++ b/patacrep/songs/chordpro/data/chordpro/content_tablature @@ -0,0 +1,5 @@ +{start_of_tab} + (* for content in content.content *) + ((- content )) + (* endfor *) +{end_of_tab} diff --git a/patacrep/songs/chordpro/data/chordpro/content_verse b/patacrep/songs/chordpro/data/chordpro/content_verse new file mode 100644 index 00000000..465e7697 --- /dev/null +++ b/patacrep/songs/chordpro/data/chordpro/content_verse @@ -0,0 +1,5 @@ +{start_of_(( content.type ))} + (* for line in content.lines *) + (( render(line) )) + (* endfor *) +{end_of_(( content.type ))} diff --git a/patacrep/songs/chordpro/data/latex/content_word.tex b/patacrep/songs/chordpro/data/chordpro/content_word similarity index 100% rename from patacrep/songs/chordpro/data/latex/content_word.tex rename to patacrep/songs/chordpro/data/chordpro/content_word diff --git a/patacrep/songs/chordpro/data/chordpro/song b/patacrep/songs/chordpro/data/chordpro/song new file mode 100644 index 00000000..92f474ee --- /dev/null +++ b/patacrep/songs/chordpro/data/chordpro/song @@ -0,0 +1,35 @@ +(* 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 *) + +(* for item in content -*) + (( render(item) )) +(* endfor *) diff --git a/patacrep/songs/chordpro/data/latex/chordpro.tex b/patacrep/songs/chordpro/data/latex/chordpro.tex deleted file mode 100644 index 1f21adb1..00000000 --- a/patacrep/songs/chordpro/data/latex/chordpro.tex +++ /dev/null @@ -1,27 +0,0 @@ -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% ((path)) - -(* if language is defined *) -\selectlanguage{((language))} -(* endif *) -\songcolumns{((metadata.columns))} - -\beginsong{((titles))}[ - by={((authors))}, - (* for (key, argument) in beginsong *) - ((key))={((argument))}, - (* endfor *) - ] - - (* if (metadata.cov is defined) or (metadata.vcov is defined) *) - \cover - (* endif *) - - (* for item in content *) - (( render(item) )) - (* endfor *) - -\endsong -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - diff --git a/patacrep/songs/chordpro/data/latex/content_chord b/patacrep/songs/chordpro/data/latex/content_chord new file mode 100644 index 00000000..61b51c8a --- /dev/null +++ b/patacrep/songs/chordpro/data/latex/content_chord @@ -0,0 +1 @@ +((- content.chord|replace("b", "&") -)) diff --git a/patacrep/songs/chordpro/data/latex/content_chord.tex b/patacrep/songs/chordpro/data/latex/content_chord.tex deleted file mode 100644 index bd2bd8b8..00000000 --- a/patacrep/songs/chordpro/data/latex/content_chord.tex +++ /dev/null @@ -1 +0,0 @@ -\[(( content.value ))] diff --git a/patacrep/songs/chordpro/data/latex/content_chordlist b/patacrep/songs/chordpro/data/latex/content_chordlist new file mode 100644 index 00000000..5ff3fa6b --- /dev/null +++ b/patacrep/songs/chordpro/data/latex/content_chordlist @@ -0,0 +1,8 @@ +(* if content.chords *) +\[ + (*- for chord in content.chords -*) + (* if not loop.first *) (* endif -*) + (( render(chord) -)) + (* endfor -*) +] +(*- endif -*) diff --git a/patacrep/songs/chordpro/data/latex/content_comment.tex b/patacrep/songs/chordpro/data/latex/content_comment similarity index 100% rename from patacrep/songs/chordpro/data/latex/content_comment.tex rename to patacrep/songs/chordpro/data/latex/content_comment diff --git a/patacrep/songs/chordpro/data/latex/content_define b/patacrep/songs/chordpro/data/latex/content_define new file mode 100644 index 00000000..ca899ff3 --- /dev/null +++ b/patacrep/songs/chordpro/data/latex/content_define @@ -0,0 +1,24 @@ +\gtab{ + ((- render(content.key) -)) +}{ + (*- if content.basefret -*) + ((content.basefret)): + (*- endif -*) + (*- for string in content.frets -*) + (*- if string is none -*) + X + (*- else -*) + (( string -)) + (* endif -*) + (* endfor -*) + (* if content.fingers -*) + : + (*- for finger in content.fingers -*) + (* if finger is none -*) + 0 + (*- else -*) + (( finger -)) + (* endif -*) + (* endfor -*) + (* endif -*) +} diff --git a/patacrep/songs/chordpro/data/latex/content_error b/patacrep/songs/chordpro/data/latex/content_error new file mode 100644 index 00000000..cee78a38 --- /dev/null +++ b/patacrep/songs/chordpro/data/latex/content_error @@ -0,0 +1,3 @@ + +ERROR : Template not found for \verb+(( content.__class__.__name__ ))+. See the logs for details. + diff --git a/patacrep/songs/chordpro/data/latex/content_error.tex b/patacrep/songs/chordpro/data/latex/content_error.tex deleted file mode 100644 index a41faeb5..00000000 --- a/patacrep/songs/chordpro/data/latex/content_error.tex +++ /dev/null @@ -1,3 +0,0 @@ - -ERROR : Template not found for \verb+(( content.__class__))+. See the logs for details. - diff --git a/patacrep/songs/chordpro/data/latex/content_guitar_comment.tex b/patacrep/songs/chordpro/data/latex/content_guitar_comment similarity index 100% rename from patacrep/songs/chordpro/data/latex/content_guitar_comment.tex rename to patacrep/songs/chordpro/data/latex/content_guitar_comment diff --git a/patacrep/songs/chordpro/data/latex/content_image b/patacrep/songs/chordpro/data/latex/content_image new file mode 100644 index 00000000..bd132ce6 --- /dev/null +++ b/patacrep/songs/chordpro/data/latex/content_image @@ -0,0 +1 @@ +\image{(( content.argument|search_image(path, config) ))} diff --git a/patacrep/songs/chordpro/data/latex/content_image.tex b/patacrep/songs/chordpro/data/latex/content_image.tex deleted file mode 100644 index 336233d5..00000000 --- a/patacrep/songs/chordpro/data/latex/content_image.tex +++ /dev/null @@ -1 +0,0 @@ -\image{(( content.argument ))} diff --git a/patacrep/songs/chordpro/data/latex/content_line b/patacrep/songs/chordpro/data/latex/content_line new file mode 100644 index 00000000..03ca80b7 --- /dev/null +++ b/patacrep/songs/chordpro/data/latex/content_line @@ -0,0 +1,3 @@ +(* for item in content.line -*) + (( render(item) )) +(*- endfor *) diff --git a/patacrep/songs/chordpro/data/latex/content_line.tex b/patacrep/songs/chordpro/data/latex/content_line.tex deleted file mode 100644 index bdad1100..00000000 --- a/patacrep/songs/chordpro/data/latex/content_line.tex +++ /dev/null @@ -1 +0,0 @@ -(* for item in content.line *)(( render(item) ))(* endfor *) diff --git a/patacrep/songs/chordpro/data/latex/content_newline b/patacrep/songs/chordpro/data/latex/content_newline new file mode 100644 index 00000000..139597f9 --- /dev/null +++ b/patacrep/songs/chordpro/data/latex/content_newline @@ -0,0 +1,2 @@ + + diff --git a/patacrep/songs/chordpro/data/latex/content_partition b/patacrep/songs/chordpro/data/latex/content_partition new file mode 100644 index 00000000..bcb92a0b --- /dev/null +++ b/patacrep/songs/chordpro/data/latex/content_partition @@ -0,0 +1 @@ +\lilypond{ ((- content.argument|search_image(path, config) -)) } diff --git a/patacrep/songs/chordpro/data/latex/content_partition.tex b/patacrep/songs/chordpro/data/latex/content_partition.tex deleted file mode 100644 index 98bfed57..00000000 --- a/patacrep/songs/chordpro/data/latex/content_partition.tex +++ /dev/null @@ -1 +0,0 @@ -\lilypond{((content.argument))} diff --git a/patacrep/songs/chordpro/data/latex/content_space b/patacrep/songs/chordpro/data/latex/content_space new file mode 100644 index 00000000..8d1c8b69 --- /dev/null +++ b/patacrep/songs/chordpro/data/latex/content_space @@ -0,0 +1 @@ + diff --git a/patacrep/songs/chordpro/data/latex/content_tablature b/patacrep/songs/chordpro/data/latex/content_tablature new file mode 100644 index 00000000..85f74e6d --- /dev/null +++ b/patacrep/songs/chordpro/data/latex/content_tablature @@ -0,0 +1,5 @@ +\begin{verbatim} +(* for content in content.content *) + ((- content )) +(* endfor *) +\end{verbatim} diff --git a/patacrep/songs/chordpro/data/latex/content_verse b/patacrep/songs/chordpro/data/latex/content_verse new file mode 100644 index 00000000..b6065a7f --- /dev/null +++ b/patacrep/songs/chordpro/data/latex/content_verse @@ -0,0 +1,5 @@ +\begin{(( content.type ))} + (* for line in content.lines *) + (( render(line) )) + (* endfor *) +\end{(( content.type ))} diff --git a/patacrep/songs/chordpro/data/latex/content_verse.tex b/patacrep/songs/chordpro/data/latex/content_verse.tex deleted file mode 100644 index dc50f3f0..00000000 --- a/patacrep/songs/chordpro/data/latex/content_verse.tex +++ /dev/null @@ -1,6 +0,0 @@ -\begin{(( content.type ))} - (* for line in content.lines *) - (( render(line) )) - (* endfor *) -\end{(( content.type ))} - diff --git a/patacrep/songs/chordpro/data/latex/content_word b/patacrep/songs/chordpro/data/latex/content_word new file mode 100644 index 00000000..d9dd7a30 --- /dev/null +++ b/patacrep/songs/chordpro/data/latex/content_word @@ -0,0 +1 @@ +(( content.value )) diff --git a/patacrep/songs/chordpro/data/latex/song b/patacrep/songs/chordpro/data/latex/song new file mode 100644 index 00000000..4cb04412 --- /dev/null +++ b/patacrep/songs/chordpro/data/latex/song @@ -0,0 +1,50 @@ +(* if language is defined -*) + \selectlanguage{((language))} +(* endif *) + +(*- if metadata.columns is defined *) +\songcolumns{(( metadata.columns ))} +(* endif *) + +\beginsong{ + (*- for title in titles -*) + (( title )) + (*- if not loop.last -*) + \\ + (* endif *) + (* endfor -*) +}[ + by={ + (* for author in authors *) + (( author[1] )) (( author[0] )) + (*- if not loop.last -*) + , + (* endif *) + (* endfor *) + }, + (* 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(path, config) ))}, + (* endif *) + (* for key in metadata.keys *) + (( key.keyword ))={(( key.argument ))}, + (* endfor *) +] + +(* if (metadata.cov is defined) *) +\cover +(* endif *) + +(*- for chord in metadata['define'] -*) + (( render(chord) )) +(* endfor *) + +(* for item in content -*) + (( render(item) )) +(* endfor *) + +\endsong diff --git a/patacrep/songs/chordpro/lexer.py b/patacrep/songs/chordpro/lexer.py index 7f1582e6..aba37a1c 100644 --- a/patacrep/songs/chordpro/lexer.py +++ b/patacrep/songs/chordpro/lexer.py @@ -9,11 +9,11 @@ LOGGER = logging.getLogger() tokens = ( 'LBRACE', 'RBRACE', - 'CHORD', 'NEWLINE', 'COLON', 'WORD', 'SPACE', + 'CHORD', 'TEXT', 'KEYWORD', 'SOC', @@ -39,7 +39,7 @@ class ChordProLexer: t_SPACE = r'[ \t]+' - t_chord_CHORD = r'[A-G7#m]+' + t_chord_CHORD = r'[^\]]+' t_directive_SPACE = r'[ \t]+' t_directive_KEYWORD = r'[a-zA-Z_]+' @@ -133,28 +133,32 @@ class ChordProLexer: return token @staticmethod - def t_error(token): - """Manage errors""" - LOGGER.error("Illegal character '{}'".format(token.value[0])) + def error(token, more=""): + """Display error message, and skip illegal token.""" + LOGGER.error( + "Line {line}: Illegal character '{char}'{more}.".format( + line=token.lexer.lineno, + char=token.value[0], + more=more, + ) + ) token.lexer.skip(1) - @staticmethod - def t_chord_error(token): + def t_error(self, token): """Manage errors""" - LOGGER.error("Illegal character '{}' in chord..".format(token.value[0])) - token.lexer.skip(1) + self.error(token) - @staticmethod - def t_tablature_error(token): + def t_chord_error(self, token): """Manage errors""" - LOGGER.error("Illegal character '{}' in tablature..".format(token.value[0])) - token.lexer.skip(1) + self.error(token, more=" in chord") - @staticmethod - def t_directive_error(token): + def t_tablature_error(self, token): """Manage errors""" - LOGGER.error("Illegal character '{}' in directive..".format(token.value[0])) - token.lexer.skip(1) + self.error(token, more=" in tablature") + + def t_directive_error(self, token): + """Manage errors""" + self.error(token, more=" in directive") def t_directiveargument_error(self, token): """Manage errors""" diff --git a/patacrep/songs/chordpro/syntax.py b/patacrep/songs/chordpro/syntax.py index fdcf9b72..a5d1b102 100644 --- a/patacrep/songs/chordpro/syntax.py +++ b/patacrep/songs/chordpro/syntax.py @@ -1,16 +1,15 @@ """ChordPro parser""" -import logging import ply.yacc as yacc +import re from patacrep.songs.syntax import Parser from patacrep.songs.chordpro import ast from patacrep.songs.chordpro.lexer import tokens, ChordProLexer -LOGGER = logging.getLogger() - class ChordproParser(Parser): """ChordPro parser class""" + # pylint: disable=too-many-public-methods start = "song" @@ -23,7 +22,6 @@ class ChordproParser(Parser): """song : block song | empty """ - #if isinstance(symbols[1], str): if len(symbols) == 2: symbols[0] = ast.Song(self.filename) else: @@ -54,28 +52,113 @@ class ChordproParser(Parser): symbols[0] = None @staticmethod - def p_directive(symbols): + def _parse_define(groups): + """Parse a `{define: KEY base-fret BASE frets FRETS fingers FINGERS}` directive + + Return a :class:`ast.Define` object. + """ + # pylint: disable=too-many-branches + if not groups['key'].strip(): + return None + else: + key = ast.Chord(groups['key'].strip()) + + if groups['basefret'] is None: + basefret = None + else: + basefret = int(groups['basefret']) + + if groups['frets'] is None: + frets = None + else: + frets = [] + for fret in groups['frets'].split(): + if fret in "xX": + frets.append(None) + else: + frets.append(int(fret)) + + if groups['fingers'] is None: + fingers = None + else: + fingers = [] + for finger in groups['fingers'].split(): + if finger == '-': + fingers.append(None) + else: + fingers.append(int(finger)) + + return ast.Define( + key=key, + basefret=basefret, + frets=frets, + fingers=fingers, + ) + + def p_directive(self, symbols): """directive : LBRACE KEYWORD directive_next RBRACE | LBRACE SPACE KEYWORD directive_next RBRACE """ if len(symbols) == 5: - symbols[3].keyword = symbols[2] - symbols[0] = symbols[3] + keyword = symbols[2] + argument = symbols[3] + else: + keyword = symbols[3] + argument = symbols[4] + + if keyword == "define": + match = re.compile( + r""" + ^ + (?P[^\ ]*)\ * + (base-fret\ *(?P\d{1,2}))?\ * + frets\ *(?P((\d+|x|X)\ *)+)\ * + (fingers\ *(?P(([0-4-])\ *)*))? + $ + """, + re.VERBOSE + ).match(argument) + + if match is None: + if argument.strip(): + self.error( + line=symbols.lexer.lineno, + message="Invalid chord definition '{}'.".format(argument), + ) + else: + self.error( + line=symbols.lexer.lineno, + message="Invalid empty chord definition.", + ) + symbols[0] = ast.Error() + return + + symbols[0] = self._parse_define(match.groupdict()) + if symbols[0] is None: + self.error( + line=symbols.lexer.lineno, + message="Invalid chord definition '{}'.".format(argument), + ) + symbols[0] = ast.Error() + else: - symbols[4].keyword = symbols[3] - symbols[0] = symbols[4] + symbols[0] = ast.Directive(keyword, argument) @staticmethod def p_directive_next(symbols): """directive_next : SPACE COLON TEXT | COLON TEXT + | COLON | empty """ - symbols[0] = ast.Directive() if len(symbols) == 3: - symbols[0].argument = symbols[2].strip() + symbols[0] = symbols[2].strip() elif len(symbols) == 4: - symbols[0].argument = symbols[3].strip() + symbols[0] = symbols[3].strip() + elif len(symbols) == 2 and symbols[1] == ":": + symbols[0] = "" + else: + symbols[0] = None @staticmethod def p_line(symbols): @@ -109,7 +192,7 @@ class ChordproParser(Parser): @staticmethod def p_chord(symbols): """chord : CHORD""" - symbols[0] = ast.Chord(symbols[1]) + symbols[0] = ast.ChordList(*[ast.Chord(chord) for chord in symbols[1].split()]) @staticmethod def p_chorus(symbols): diff --git a/patacrep/songs/chordpro/test/00.sgc b/patacrep/songs/chordpro/test/00.sgc index e69de29b..3e2185b7 100644 --- a/patacrep/songs/chordpro/test/00.sgc +++ b/patacrep/songs/chordpro/test/00.sgc @@ -0,0 +1 @@ +{language: english} diff --git a/patacrep/songs/chordpro/test/00.source b/patacrep/songs/chordpro/test/00.source new file mode 100644 index 00000000..e69de29b diff --git a/patacrep/songs/chordpro/test/00.tex b/patacrep/songs/chordpro/test/00.tex new file mode 100644 index 00000000..bd99a922 --- /dev/null +++ b/patacrep/songs/chordpro/test/00.tex @@ -0,0 +1,10 @@ +\selectlanguage{english} + +\beginsong{}[ + by={ + }, +] + + + +\endsong diff --git a/patacrep/songs/chordpro/test/00.txt b/patacrep/songs/chordpro/test/00.txt deleted file mode 100644 index dbbd9c50..00000000 --- a/patacrep/songs/chordpro/test/00.txt +++ /dev/null @@ -1 +0,0 @@ -======== diff --git a/patacrep/songs/chordpro/test/01.sgc b/patacrep/songs/chordpro/test/01.sgc index 8ea8d2a2..ae7eabc4 100644 --- a/patacrep/songs/chordpro/test/01.sgc +++ b/patacrep/songs/chordpro/test/01.sgc @@ -1 +1,5 @@ -A verse line +{language: english} + +{start_of_verse} + A verse line +{end_of_verse} diff --git a/patacrep/songs/chordpro/test/01.source b/patacrep/songs/chordpro/test/01.source new file mode 100644 index 00000000..8ea8d2a2 --- /dev/null +++ b/patacrep/songs/chordpro/test/01.source @@ -0,0 +1 @@ +A verse line diff --git a/patacrep/songs/chordpro/test/01.tex b/patacrep/songs/chordpro/test/01.tex new file mode 100644 index 00000000..15825e69 --- /dev/null +++ b/patacrep/songs/chordpro/test/01.tex @@ -0,0 +1,13 @@ +\selectlanguage{english} + +\beginsong{}[ + by={ + }, +] + + +\begin{verse} + A verse line +\end{verse} + +\endsong diff --git a/patacrep/songs/chordpro/test/01.txt b/patacrep/songs/chordpro/test/01.txt deleted file mode 100644 index 84cf4364..00000000 --- a/patacrep/songs/chordpro/test/01.txt +++ /dev/null @@ -1,4 +0,0 @@ -======== -{start_of_verse} - A verse line -{end_of_verse} diff --git a/patacrep/songs/chordpro/test/02.sgc b/patacrep/songs/chordpro/test/02.sgc index 270bc746..2a8629e0 100644 --- a/patacrep/songs/chordpro/test/02.sgc +++ b/patacrep/songs/chordpro/test/02.sgc @@ -1 +1,3 @@ -{title : A directive} +{language: english} +{title: A directive} + diff --git a/patacrep/songs/chordpro/test/02.source b/patacrep/songs/chordpro/test/02.source new file mode 100644 index 00000000..270bc746 --- /dev/null +++ b/patacrep/songs/chordpro/test/02.source @@ -0,0 +1 @@ +{title : A directive} diff --git a/patacrep/songs/chordpro/test/02.tex b/patacrep/songs/chordpro/test/02.tex new file mode 100644 index 00000000..b3ec6f17 --- /dev/null +++ b/patacrep/songs/chordpro/test/02.tex @@ -0,0 +1,10 @@ +\selectlanguage{english} + +\beginsong{A directive}[ + by={ + }, +] + + + +\endsong diff --git a/patacrep/songs/chordpro/test/02.txt b/patacrep/songs/chordpro/test/02.txt deleted file mode 100644 index f3fbd9e9..00000000 --- a/patacrep/songs/chordpro/test/02.txt +++ /dev/null @@ -1,2 +0,0 @@ -{title: A directive} -======== diff --git a/patacrep/songs/chordpro/test/03.sgc b/patacrep/songs/chordpro/test/03.sgc index fd40910d..341c9bd4 100644 --- a/patacrep/songs/chordpro/test/03.sgc +++ b/patacrep/songs/chordpro/test/03.sgc @@ -1,4 +1,2 @@ - - - +{language: english} diff --git a/patacrep/songs/chordpro/test/03.source b/patacrep/songs/chordpro/test/03.source new file mode 100644 index 00000000..fd40910d --- /dev/null +++ b/patacrep/songs/chordpro/test/03.source @@ -0,0 +1,4 @@ + + + + diff --git a/patacrep/songs/chordpro/test/03.tex b/patacrep/songs/chordpro/test/03.tex new file mode 100644 index 00000000..c2d0cc18 --- /dev/null +++ b/patacrep/songs/chordpro/test/03.tex @@ -0,0 +1,12 @@ +\selectlanguage{english} + +\beginsong{}[ + by={ + }, +] + + + + + +\endsong diff --git a/patacrep/songs/chordpro/test/03.txt b/patacrep/songs/chordpro/test/03.txt deleted file mode 100644 index dbbd9c50..00000000 --- a/patacrep/songs/chordpro/test/03.txt +++ /dev/null @@ -1 +0,0 @@ -======== diff --git a/patacrep/songs/chordpro/test/04.sgc b/patacrep/songs/chordpro/test/04.sgc index 6a266eea..e9c2a952 100644 --- a/patacrep/songs/chordpro/test/04.sgc +++ b/patacrep/songs/chordpro/test/04.sgc @@ -1,3 +1,5 @@ -{soc} -A one line chorus -{eoc} +{language: english} + +{start_of_chorus} + A one line chorus +{end_of_chorus} diff --git a/patacrep/songs/chordpro/test/04.source b/patacrep/songs/chordpro/test/04.source new file mode 100644 index 00000000..6a266eea --- /dev/null +++ b/patacrep/songs/chordpro/test/04.source @@ -0,0 +1,3 @@ +{soc} +A one line chorus +{eoc} diff --git a/patacrep/songs/chordpro/test/04.tex b/patacrep/songs/chordpro/test/04.tex new file mode 100644 index 00000000..d25d81fd --- /dev/null +++ b/patacrep/songs/chordpro/test/04.tex @@ -0,0 +1,13 @@ +\selectlanguage{english} + +\beginsong{}[ + by={ + }, +] + + +\begin{chorus} + A one line chorus +\end{chorus} + +\endsong diff --git a/patacrep/songs/chordpro/test/04.txt b/patacrep/songs/chordpro/test/04.txt deleted file mode 100644 index 3336d565..00000000 --- a/patacrep/songs/chordpro/test/04.txt +++ /dev/null @@ -1,4 +0,0 @@ -======== -{start_of_chorus} - A one line chorus -{end_of_chorus} diff --git a/patacrep/songs/chordpro/test/05.sgc b/patacrep/songs/chordpro/test/05.sgc index 9472ebcb..9bc7f016 100644 --- a/patacrep/songs/chordpro/test/05.sgc +++ b/patacrep/songs/chordpro/test/05.sgc @@ -1,3 +1,5 @@ -{sob} -A one line bridge -{eob} +{language: english} + +{start_of_bridge} + A one line bridge +{end_of_bridge} diff --git a/patacrep/songs/chordpro/test/05.source b/patacrep/songs/chordpro/test/05.source new file mode 100644 index 00000000..9472ebcb --- /dev/null +++ b/patacrep/songs/chordpro/test/05.source @@ -0,0 +1,3 @@ +{sob} +A one line bridge +{eob} diff --git a/patacrep/songs/chordpro/test/05.tex b/patacrep/songs/chordpro/test/05.tex new file mode 100644 index 00000000..be4a189b --- /dev/null +++ b/patacrep/songs/chordpro/test/05.tex @@ -0,0 +1,13 @@ +\selectlanguage{english} + +\beginsong{}[ + by={ + }, +] + + +\begin{bridge} + A one line bridge +\end{bridge} + +\endsong diff --git a/patacrep/songs/chordpro/test/05.txt b/patacrep/songs/chordpro/test/05.txt deleted file mode 100644 index b2f99be2..00000000 --- a/patacrep/songs/chordpro/test/05.txt +++ /dev/null @@ -1,4 +0,0 @@ -======== -{start_of_bridge} - A one line bridge -{end_of_bridge} diff --git a/patacrep/songs/chordpro/test/06.sgc b/patacrep/songs/chordpro/test/06.sgc index 90a2b559..341c9bd4 100644 --- a/patacrep/songs/chordpro/test/06.sgc +++ b/patacrep/songs/chordpro/test/06.sgc @@ -1 +1,2 @@ -# A comment +{language: english} + diff --git a/patacrep/songs/chordpro/test/06.source b/patacrep/songs/chordpro/test/06.source new file mode 100644 index 00000000..90a2b559 --- /dev/null +++ b/patacrep/songs/chordpro/test/06.source @@ -0,0 +1 @@ +# A comment diff --git a/patacrep/songs/chordpro/test/06.tex b/patacrep/songs/chordpro/test/06.tex new file mode 100644 index 00000000..c2d0cc18 --- /dev/null +++ b/patacrep/songs/chordpro/test/06.tex @@ -0,0 +1,12 @@ +\selectlanguage{english} + +\beginsong{}[ + by={ + }, +] + + + + + +\endsong diff --git a/patacrep/songs/chordpro/test/06.txt b/patacrep/songs/chordpro/test/06.txt deleted file mode 100644 index dbbd9c50..00000000 --- a/patacrep/songs/chordpro/test/06.txt +++ /dev/null @@ -1 +0,0 @@ -======== diff --git a/patacrep/songs/chordpro/test/07.sgc b/patacrep/songs/chordpro/test/07.sgc index fd183eff..b05a536f 100644 --- a/patacrep/songs/chordpro/test/07.sgc +++ b/patacrep/songs/chordpro/test/07.sgc @@ -1,3 +1,5 @@ -{sot} +{language: english} + +{start_of_tab} A tab -{eot} +{end_of_tab} diff --git a/patacrep/songs/chordpro/test/07.source b/patacrep/songs/chordpro/test/07.source new file mode 100644 index 00000000..fd183eff --- /dev/null +++ b/patacrep/songs/chordpro/test/07.source @@ -0,0 +1,3 @@ +{sot} +A tab +{eot} diff --git a/patacrep/songs/chordpro/test/07.tex b/patacrep/songs/chordpro/test/07.tex new file mode 100644 index 00000000..01c0198e --- /dev/null +++ b/patacrep/songs/chordpro/test/07.tex @@ -0,0 +1,13 @@ +\selectlanguage{english} + +\beginsong{}[ + by={ + }, +] + + +\begin{verbatim} +A tab +\end{verbatim} + +\endsong diff --git a/patacrep/songs/chordpro/test/07.txt b/patacrep/songs/chordpro/test/07.txt deleted file mode 100644 index 7fb8bc64..00000000 --- a/patacrep/songs/chordpro/test/07.txt +++ /dev/null @@ -1,4 +0,0 @@ -======== -{start_of_tab} - A tab -{end_of_tab} diff --git a/patacrep/songs/chordpro/test/08.sgc b/patacrep/songs/chordpro/test/08.sgc index b51646ca..61224d41 100644 --- a/patacrep/songs/chordpro/test/08.sgc +++ b/patacrep/songs/chordpro/test/08.sgc @@ -1,10 +1,7 @@ +{language: english} -# comment -# comment - - -A lot of new lines - -# comment +{start_of_verse} + A lot of new lines +{end_of_verse} diff --git a/patacrep/songs/chordpro/test/08.source b/patacrep/songs/chordpro/test/08.source new file mode 100644 index 00000000..b51646ca --- /dev/null +++ b/patacrep/songs/chordpro/test/08.source @@ -0,0 +1,10 @@ + + + +# comment +# comment + + +A lot of new lines + +# comment diff --git a/patacrep/songs/chordpro/test/08.tex b/patacrep/songs/chordpro/test/08.tex new file mode 100644 index 00000000..70c26f87 --- /dev/null +++ b/patacrep/songs/chordpro/test/08.tex @@ -0,0 +1,17 @@ +\selectlanguage{english} + +\beginsong{}[ + by={ + }, +] + + + + +\begin{verse} + A lot of new lines +\end{verse} + + + +\endsong diff --git a/patacrep/songs/chordpro/test/08.txt b/patacrep/songs/chordpro/test/08.txt deleted file mode 100644 index 92c183b1..00000000 --- a/patacrep/songs/chordpro/test/08.txt +++ /dev/null @@ -1,4 +0,0 @@ -======== -{start_of_verse} - A lot of new lines -{end_of_verse} diff --git a/patacrep/songs/chordpro/test/09.sgc b/patacrep/songs/chordpro/test/09.sgc index b831f230..942a91e1 100644 --- a/patacrep/songs/chordpro/test/09.sgc +++ b/patacrep/songs/chordpro/test/09.sgc @@ -1,15 +1,8 @@ - - - -# comment -# comment - - -A lot of new lines - -# comment - +{language: english} {title: and a directive} -# comment + +{start_of_verse} + A lot of new lines +{end_of_verse} diff --git a/patacrep/songs/chordpro/test/09.source b/patacrep/songs/chordpro/test/09.source new file mode 100644 index 00000000..b831f230 --- /dev/null +++ b/patacrep/songs/chordpro/test/09.source @@ -0,0 +1,15 @@ + + + +# comment +# comment + + +A lot of new lines + +# comment + +{title: and a directive} + +# comment + diff --git a/patacrep/songs/chordpro/test/09.tex b/patacrep/songs/chordpro/test/09.tex new file mode 100644 index 00000000..c57b285f --- /dev/null +++ b/patacrep/songs/chordpro/test/09.tex @@ -0,0 +1,17 @@ +\selectlanguage{english} + +\beginsong{and a directive}[ + by={ + }, +] + + + + +\begin{verse} + A lot of new lines +\end{verse} + + + +\endsong diff --git a/patacrep/songs/chordpro/test/09.txt b/patacrep/songs/chordpro/test/09.txt deleted file mode 100644 index b7669e62..00000000 --- a/patacrep/songs/chordpro/test/09.txt +++ /dev/null @@ -1,5 +0,0 @@ -{title: and a directive} -======== -{start_of_verse} - A lot of new lines -{end_of_verse} diff --git a/patacrep/songs/chordpro/test/10.sgc b/patacrep/songs/chordpro/test/10.sgc index 6519ab80..23bce4fa 100644 --- a/patacrep/songs/chordpro/test/10.sgc +++ b/patacrep/songs/chordpro/test/10.sgc @@ -1 +1,5 @@ -A line[A] with a chord +{language: english} + +{start_of_verse} + A line[A] with a chord +{end_of_verse} diff --git a/patacrep/songs/chordpro/test/10.source b/patacrep/songs/chordpro/test/10.source new file mode 100644 index 00000000..6519ab80 --- /dev/null +++ b/patacrep/songs/chordpro/test/10.source @@ -0,0 +1 @@ +A line[A] with a chord diff --git a/patacrep/songs/chordpro/test/10.tex b/patacrep/songs/chordpro/test/10.tex new file mode 100644 index 00000000..b17d3999 --- /dev/null +++ b/patacrep/songs/chordpro/test/10.tex @@ -0,0 +1,13 @@ +\selectlanguage{english} + +\beginsong{}[ + by={ + }, +] + + +\begin{verse} + A line\[A] with a chord +\end{verse} + +\endsong diff --git a/patacrep/songs/chordpro/test/10.txt b/patacrep/songs/chordpro/test/10.txt deleted file mode 100644 index b96d8637..00000000 --- a/patacrep/songs/chordpro/test/10.txt +++ /dev/null @@ -1,4 +0,0 @@ -======== -{start_of_verse} - A line[A] with a chord -{end_of_verse} diff --git a/patacrep/songs/chordpro/test/11.sgc b/patacrep/songs/chordpro/test/11.sgc index fc3d697d..79d44702 100644 --- a/patacrep/songs/chordpro/test/11.sgc +++ b/patacrep/songs/chordpro/test/11.sgc @@ -1 +1,5 @@ -A line ending with a chord[A] +{language: english} + +{start_of_verse} + A line ending with a chord[A] +{end_of_verse} diff --git a/patacrep/songs/chordpro/test/11.source b/patacrep/songs/chordpro/test/11.source new file mode 100644 index 00000000..fc3d697d --- /dev/null +++ b/patacrep/songs/chordpro/test/11.source @@ -0,0 +1 @@ +A line ending with a chord[A] diff --git a/patacrep/songs/chordpro/test/11.tex b/patacrep/songs/chordpro/test/11.tex new file mode 100644 index 00000000..e5ed4113 --- /dev/null +++ b/patacrep/songs/chordpro/test/11.tex @@ -0,0 +1,13 @@ +\selectlanguage{english} + +\beginsong{}[ + by={ + }, +] + + +\begin{verse} + A line ending with a chord\[A] +\end{verse} + +\endsong diff --git a/patacrep/songs/chordpro/test/11.txt b/patacrep/songs/chordpro/test/11.txt deleted file mode 100644 index 2a9eaf17..00000000 --- a/patacrep/songs/chordpro/test/11.txt +++ /dev/null @@ -1,4 +0,0 @@ -======== -{start_of_verse} - A line ending with a chord[A] -{end_of_verse} diff --git a/patacrep/songs/chordpro/test/12.sgc b/patacrep/songs/chordpro/test/12.sgc index a9583451..6afb5bf8 100644 --- a/patacrep/songs/chordpro/test/12.sgc +++ b/patacrep/songs/chordpro/test/12.sgc @@ -1 +1,5 @@ -[A]A line starting with a chord +{language: english} + +{start_of_verse} + [A]A line starting with a chord +{end_of_verse} diff --git a/patacrep/songs/chordpro/test/12.source b/patacrep/songs/chordpro/test/12.source new file mode 100644 index 00000000..a9583451 --- /dev/null +++ b/patacrep/songs/chordpro/test/12.source @@ -0,0 +1 @@ +[A]A line starting with a chord diff --git a/patacrep/songs/chordpro/test/12.tex b/patacrep/songs/chordpro/test/12.tex new file mode 100644 index 00000000..ec3aca08 --- /dev/null +++ b/patacrep/songs/chordpro/test/12.tex @@ -0,0 +1,13 @@ +\selectlanguage{english} + +\beginsong{}[ + by={ + }, +] + + +\begin{verse} + \[A]A line starting with a chord +\end{verse} + +\endsong diff --git a/patacrep/songs/chordpro/test/12.txt b/patacrep/songs/chordpro/test/12.txt deleted file mode 100644 index 83c11625..00000000 --- a/patacrep/songs/chordpro/test/12.txt +++ /dev/null @@ -1,4 +0,0 @@ -======== -{start_of_verse} - [A]A line starting with a chord -{end_of_verse} diff --git a/patacrep/songs/chordpro/test/13.sgc b/patacrep/songs/chordpro/test/13.sgc index 6cc3dfbc..aa6f6603 100644 --- a/patacrep/songs/chordpro/test/13.sgc +++ b/patacrep/songs/chordpro/test/13.sgc @@ -1,5 +1,7 @@ -{sot} - A table - wit many # weir [ - [ symbols -{eot} +{language: english} + +{start_of_tab} +A table +wit many # weir [ +[ symbols +{end_of_tab} diff --git a/patacrep/songs/chordpro/test/13.txt b/patacrep/songs/chordpro/test/13.source similarity index 53% rename from patacrep/songs/chordpro/test/13.txt rename to patacrep/songs/chordpro/test/13.source index 447f67dd..6cc3dfbc 100644 --- a/patacrep/songs/chordpro/test/13.txt +++ b/patacrep/songs/chordpro/test/13.source @@ -1,6 +1,5 @@ -======== -{start_of_tab} +{sot} A table wit many # weir [ [ symbols -{end_of_tab} +{eot} diff --git a/patacrep/songs/chordpro/test/13.tex b/patacrep/songs/chordpro/test/13.tex new file mode 100644 index 00000000..0bce3b58 --- /dev/null +++ b/patacrep/songs/chordpro/test/13.tex @@ -0,0 +1,15 @@ +\selectlanguage{english} + +\beginsong{}[ + by={ + }, +] + + +\begin{verbatim} +A table +wit many # weir [ +[ symbols +\end{verbatim} + +\endsong diff --git a/patacrep/songs/chordpro/test/21.sgc b/patacrep/songs/chordpro/test/21.sgc index c01b31ad..ae7eabc4 100644 --- a/patacrep/songs/chordpro/test/21.sgc +++ b/patacrep/songs/chordpro/test/21.sgc @@ -1 +1,5 @@ - A verse line +{language: english} + +{start_of_verse} + A verse line +{end_of_verse} diff --git a/patacrep/songs/chordpro/test/21.source b/patacrep/songs/chordpro/test/21.source new file mode 100644 index 00000000..c01b31ad --- /dev/null +++ b/patacrep/songs/chordpro/test/21.source @@ -0,0 +1 @@ + A verse line diff --git a/patacrep/songs/chordpro/test/21.tex b/patacrep/songs/chordpro/test/21.tex new file mode 100644 index 00000000..15825e69 --- /dev/null +++ b/patacrep/songs/chordpro/test/21.tex @@ -0,0 +1,13 @@ +\selectlanguage{english} + +\beginsong{}[ + by={ + }, +] + + +\begin{verse} + A verse line +\end{verse} + +\endsong diff --git a/patacrep/songs/chordpro/test/21.txt b/patacrep/songs/chordpro/test/21.txt deleted file mode 100644 index 84cf4364..00000000 --- a/patacrep/songs/chordpro/test/21.txt +++ /dev/null @@ -1,4 +0,0 @@ -======== -{start_of_verse} - A verse line -{end_of_verse} diff --git a/patacrep/songs/chordpro/test/22.sgc b/patacrep/songs/chordpro/test/22.sgc index 425fd584..2a8629e0 100644 --- a/patacrep/songs/chordpro/test/22.sgc +++ b/patacrep/songs/chordpro/test/22.sgc @@ -1 +1,3 @@ - {title : A directive} +{language: english} +{title: A directive} + diff --git a/patacrep/songs/chordpro/test/22.source b/patacrep/songs/chordpro/test/22.source new file mode 100644 index 00000000..425fd584 --- /dev/null +++ b/patacrep/songs/chordpro/test/22.source @@ -0,0 +1 @@ + {title : A directive} diff --git a/patacrep/songs/chordpro/test/22.tex b/patacrep/songs/chordpro/test/22.tex new file mode 100644 index 00000000..b3ec6f17 --- /dev/null +++ b/patacrep/songs/chordpro/test/22.tex @@ -0,0 +1,10 @@ +\selectlanguage{english} + +\beginsong{A directive}[ + by={ + }, +] + + + +\endsong diff --git a/patacrep/songs/chordpro/test/22.txt b/patacrep/songs/chordpro/test/22.txt deleted file mode 100644 index f3fbd9e9..00000000 --- a/patacrep/songs/chordpro/test/22.txt +++ /dev/null @@ -1,2 +0,0 @@ -{title: A directive} -======== diff --git a/patacrep/songs/chordpro/test/23.sgc b/patacrep/songs/chordpro/test/23.sgc index ce5ed9dd..3e2185b7 100644 --- a/patacrep/songs/chordpro/test/23.sgc +++ b/patacrep/songs/chordpro/test/23.sgc @@ -1,4 +1 @@ - - - - +{language: english} diff --git a/patacrep/songs/chordpro/test/23.source b/patacrep/songs/chordpro/test/23.source new file mode 100644 index 00000000..ce5ed9dd --- /dev/null +++ b/patacrep/songs/chordpro/test/23.source @@ -0,0 +1,4 @@ + + + + diff --git a/patacrep/songs/chordpro/test/23.tex b/patacrep/songs/chordpro/test/23.tex new file mode 100644 index 00000000..c2d0cc18 --- /dev/null +++ b/patacrep/songs/chordpro/test/23.tex @@ -0,0 +1,12 @@ +\selectlanguage{english} + +\beginsong{}[ + by={ + }, +] + + + + + +\endsong diff --git a/patacrep/songs/chordpro/test/23.txt b/patacrep/songs/chordpro/test/23.txt deleted file mode 100644 index dbbd9c50..00000000 --- a/patacrep/songs/chordpro/test/23.txt +++ /dev/null @@ -1 +0,0 @@ -======== diff --git a/patacrep/songs/chordpro/test/24.sgc b/patacrep/songs/chordpro/test/24.sgc index a929a754..e9c2a952 100644 --- a/patacrep/songs/chordpro/test/24.sgc +++ b/patacrep/songs/chordpro/test/24.sgc @@ -1,3 +1,5 @@ - {soc} - A one line chorus - {eoc} +{language: english} + +{start_of_chorus} + A one line chorus +{end_of_chorus} diff --git a/patacrep/songs/chordpro/test/24.source b/patacrep/songs/chordpro/test/24.source new file mode 100644 index 00000000..a929a754 --- /dev/null +++ b/patacrep/songs/chordpro/test/24.source @@ -0,0 +1,3 @@ + {soc} + A one line chorus + {eoc} diff --git a/patacrep/songs/chordpro/test/24.tex b/patacrep/songs/chordpro/test/24.tex new file mode 100644 index 00000000..d25d81fd --- /dev/null +++ b/patacrep/songs/chordpro/test/24.tex @@ -0,0 +1,13 @@ +\selectlanguage{english} + +\beginsong{}[ + by={ + }, +] + + +\begin{chorus} + A one line chorus +\end{chorus} + +\endsong diff --git a/patacrep/songs/chordpro/test/24.txt b/patacrep/songs/chordpro/test/24.txt deleted file mode 100644 index 3336d565..00000000 --- a/patacrep/songs/chordpro/test/24.txt +++ /dev/null @@ -1,4 +0,0 @@ -======== -{start_of_chorus} - A one line chorus -{end_of_chorus} diff --git a/patacrep/songs/chordpro/test/25.sgc b/patacrep/songs/chordpro/test/25.sgc index 45efba59..9bc7f016 100644 --- a/patacrep/songs/chordpro/test/25.sgc +++ b/patacrep/songs/chordpro/test/25.sgc @@ -1,3 +1,5 @@ - {sob} - A one line bridge - {eob} +{language: english} + +{start_of_bridge} + A one line bridge +{end_of_bridge} diff --git a/patacrep/songs/chordpro/test/25.source b/patacrep/songs/chordpro/test/25.source new file mode 100644 index 00000000..45efba59 --- /dev/null +++ b/patacrep/songs/chordpro/test/25.source @@ -0,0 +1,3 @@ + {sob} + A one line bridge + {eob} diff --git a/patacrep/songs/chordpro/test/25.tex b/patacrep/songs/chordpro/test/25.tex new file mode 100644 index 00000000..be4a189b --- /dev/null +++ b/patacrep/songs/chordpro/test/25.tex @@ -0,0 +1,13 @@ +\selectlanguage{english} + +\beginsong{}[ + by={ + }, +] + + +\begin{bridge} + A one line bridge +\end{bridge} + +\endsong diff --git a/patacrep/songs/chordpro/test/25.txt b/patacrep/songs/chordpro/test/25.txt deleted file mode 100644 index b2f99be2..00000000 --- a/patacrep/songs/chordpro/test/25.txt +++ /dev/null @@ -1,4 +0,0 @@ -======== -{start_of_bridge} - A one line bridge -{end_of_bridge} diff --git a/patacrep/songs/chordpro/test/26.sgc b/patacrep/songs/chordpro/test/26.sgc index 372b96b4..341c9bd4 100644 --- a/patacrep/songs/chordpro/test/26.sgc +++ b/patacrep/songs/chordpro/test/26.sgc @@ -1 +1,2 @@ - # A comment +{language: english} + diff --git a/patacrep/songs/chordpro/test/26.source b/patacrep/songs/chordpro/test/26.source new file mode 100644 index 00000000..372b96b4 --- /dev/null +++ b/patacrep/songs/chordpro/test/26.source @@ -0,0 +1 @@ + # A comment diff --git a/patacrep/songs/chordpro/test/26.tex b/patacrep/songs/chordpro/test/26.tex new file mode 100644 index 00000000..c2d0cc18 --- /dev/null +++ b/patacrep/songs/chordpro/test/26.tex @@ -0,0 +1,12 @@ +\selectlanguage{english} + +\beginsong{}[ + by={ + }, +] + + + + + +\endsong diff --git a/patacrep/songs/chordpro/test/26.txt b/patacrep/songs/chordpro/test/26.txt deleted file mode 100644 index dbbd9c50..00000000 --- a/patacrep/songs/chordpro/test/26.txt +++ /dev/null @@ -1 +0,0 @@ -======== diff --git a/patacrep/songs/chordpro/test/27.sgc b/patacrep/songs/chordpro/test/27.sgc index bfa0cf0e..b05a536f 100644 --- a/patacrep/songs/chordpro/test/27.sgc +++ b/patacrep/songs/chordpro/test/27.sgc @@ -1,3 +1,5 @@ - {sot} - A tab - {eot} +{language: english} + +{start_of_tab} +A tab +{end_of_tab} diff --git a/patacrep/songs/chordpro/test/27.source b/patacrep/songs/chordpro/test/27.source new file mode 100644 index 00000000..bfa0cf0e --- /dev/null +++ b/patacrep/songs/chordpro/test/27.source @@ -0,0 +1,3 @@ + {sot} + A tab + {eot} diff --git a/patacrep/songs/chordpro/test/27.tex b/patacrep/songs/chordpro/test/27.tex new file mode 100644 index 00000000..01c0198e --- /dev/null +++ b/patacrep/songs/chordpro/test/27.tex @@ -0,0 +1,13 @@ +\selectlanguage{english} + +\beginsong{}[ + by={ + }, +] + + +\begin{verbatim} +A tab +\end{verbatim} + +\endsong diff --git a/patacrep/songs/chordpro/test/27.txt b/patacrep/songs/chordpro/test/27.txt deleted file mode 100644 index 7fb8bc64..00000000 --- a/patacrep/songs/chordpro/test/27.txt +++ /dev/null @@ -1,4 +0,0 @@ -======== -{start_of_tab} - A tab -{end_of_tab} diff --git a/patacrep/songs/chordpro/test/28.sgc b/patacrep/songs/chordpro/test/28.sgc index 69f980b3..61224d41 100644 --- a/patacrep/songs/chordpro/test/28.sgc +++ b/patacrep/songs/chordpro/test/28.sgc @@ -1,10 +1,7 @@ +{language: english} - - # comment -# comment - - A lot of new lines - -# comment +{start_of_verse} + A lot of new lines +{end_of_verse} diff --git a/patacrep/songs/chordpro/test/28.source b/patacrep/songs/chordpro/test/28.source new file mode 100644 index 00000000..69f980b3 --- /dev/null +++ b/patacrep/songs/chordpro/test/28.source @@ -0,0 +1,10 @@ + + + + # comment +# comment + + + A lot of new lines + +# comment diff --git a/patacrep/songs/chordpro/test/28.tex b/patacrep/songs/chordpro/test/28.tex new file mode 100644 index 00000000..70c26f87 --- /dev/null +++ b/patacrep/songs/chordpro/test/28.tex @@ -0,0 +1,17 @@ +\selectlanguage{english} + +\beginsong{}[ + by={ + }, +] + + + + +\begin{verse} + A lot of new lines +\end{verse} + + + +\endsong diff --git a/patacrep/songs/chordpro/test/28.txt b/patacrep/songs/chordpro/test/28.txt deleted file mode 100644 index 92c183b1..00000000 --- a/patacrep/songs/chordpro/test/28.txt +++ /dev/null @@ -1,4 +0,0 @@ -======== -{start_of_verse} - A lot of new lines -{end_of_verse} diff --git a/patacrep/songs/chordpro/test/29.sgc b/patacrep/songs/chordpro/test/29.sgc index 830e0177..942a91e1 100644 --- a/patacrep/songs/chordpro/test/29.sgc +++ b/patacrep/songs/chordpro/test/29.sgc @@ -1,15 +1,8 @@ +{language: english} +{title: and a directive} -# comment -# comment - - - A lot of new lines - -# comment - - {title: and a directive} - -# comment - +{start_of_verse} + A lot of new lines +{end_of_verse} diff --git a/patacrep/songs/chordpro/test/29.source b/patacrep/songs/chordpro/test/29.source new file mode 100644 index 00000000..830e0177 --- /dev/null +++ b/patacrep/songs/chordpro/test/29.source @@ -0,0 +1,15 @@ + + + +# comment +# comment + + + A lot of new lines + +# comment + + {title: and a directive} + +# comment + diff --git a/patacrep/songs/chordpro/test/29.tex b/patacrep/songs/chordpro/test/29.tex new file mode 100644 index 00000000..c57b285f --- /dev/null +++ b/patacrep/songs/chordpro/test/29.tex @@ -0,0 +1,17 @@ +\selectlanguage{english} + +\beginsong{and a directive}[ + by={ + }, +] + + + + +\begin{verse} + A lot of new lines +\end{verse} + + + +\endsong diff --git a/patacrep/songs/chordpro/test/29.txt b/patacrep/songs/chordpro/test/29.txt deleted file mode 100644 index b7669e62..00000000 --- a/patacrep/songs/chordpro/test/29.txt +++ /dev/null @@ -1,5 +0,0 @@ -{title: and a directive} -======== -{start_of_verse} - A lot of new lines -{end_of_verse} diff --git a/patacrep/songs/chordpro/test/30.sgc b/patacrep/songs/chordpro/test/30.sgc deleted file mode 100644 index ee67061c..00000000 --- a/patacrep/songs/chordpro/test/30.sgc +++ /dev/null @@ -1 +0,0 @@ - [A]A line starting with a chord diff --git a/patacrep/songs/chordpro/test/chords.sgc b/patacrep/songs/chordpro/test/chords.sgc new file mode 100644 index 00000000..942a0223 --- /dev/null +++ b/patacrep/songs/chordpro/test/chords.sgc @@ -0,0 +1,19 @@ +{language: english} + +{start_of_verse} + [A]Simple + [Bb]Bémol + [C#]Dièse + [Adim]dim + [Dmaj]maj + [Em3]m chiffre + [G4]Nombre + [Emaj3]maj et nombre + [Absus8]bémol, sus et nombre + [A/A]Deux notes + [F/Fb]Deux notes, bémol + [B/C#]Deux notes, dièse + [Ab B#/A]Plusieurs notes à la suite + [E5/A*]Avec une étoile + [B#+8]Avec un plus +{end_of_verse} diff --git a/patacrep/songs/chordpro/test/chords.source b/patacrep/songs/chordpro/test/chords.source new file mode 100644 index 00000000..a4803589 --- /dev/null +++ b/patacrep/songs/chordpro/test/chords.source @@ -0,0 +1,15 @@ +[A]Simple +[Bb]Bémol +[C#]Dièse +[Adim]dim +[Dmaj]maj +[Em3]m chiffre +[G4]Nombre +[Emaj3]maj et nombre +[Absus8]bémol, sus et nombre +[A/A]Deux notes +[F/Fb]Deux notes, bémol +[B/C#]Deux notes, dièse +[Ab B#/A]Plusieurs notes à la suite +[E5/A*]Avec une étoile +[B#+8]Avec un plus diff --git a/patacrep/songs/chordpro/test/chords.tex b/patacrep/songs/chordpro/test/chords.tex new file mode 100644 index 00000000..a621a7cd --- /dev/null +++ b/patacrep/songs/chordpro/test/chords.tex @@ -0,0 +1,27 @@ +\selectlanguage{english} + +\beginsong{}[ + by={ + }, +] + + +\begin{verse} + \[A]Simple + \[B&]Bémol + \[C#]Dièse + \[Adim]dim + \[Dmaj]maj + \[Em3]m chiffre + \[G4]Nombre + \[Emaj3]maj et nombre + \[A&sus8]bémol, sus et nombre + \[A/A]Deux notes + \[F/F&]Deux notes, bémol + \[B/C#]Deux notes, dièse + \[A& B#/A]Plusieurs notes à la suite + \[E5/A*]Avec une étoile + \[B#+8]Avec un plus +\end{verse} + +\endsong diff --git a/patacrep/songs/chordpro/test/customchords.sgc b/patacrep/songs/chordpro/test/customchords.sgc new file mode 100644 index 00000000..3357bb96 --- /dev/null +++ b/patacrep/songs/chordpro/test/customchords.sgc @@ -0,0 +1,5 @@ +{language: english} +{define: E4 base-fret 7 frets 0 1 3 3 x x} +{define: E5 base-fret 7 frets 0 1 3 3 x x fingers - 1 2 3 - -} +{define: E5/A* base-fret 7 frets 0 1 3 3 x x fingers - 1 2 3 - -} +{define: A#+2 base-fret 7 frets 0 1 3 3 x x fingers - 1 2 3 - -} diff --git a/patacrep/songs/chordpro/test/customchords.source b/patacrep/songs/chordpro/test/customchords.source new file mode 100644 index 00000000..4c6734cc --- /dev/null +++ b/patacrep/songs/chordpro/test/customchords.source @@ -0,0 +1,4 @@ +{define: E4 base-fret 7 frets 0 1 3 3 x x} +{define: E5 base-fret 7 frets 0 1 3 3 x x fingers - 1 2 3 - -} +{define: E5/A* base-fret 7 frets 0 1 3 3 x x fingers - 1 2 3 - -} +{define: A#+2 base-fret 7 frets 0 1 3 3 x x fingers - 1 2 3 - -} diff --git a/patacrep/songs/chordpro/test/customchords.tex b/patacrep/songs/chordpro/test/customchords.tex new file mode 100644 index 00000000..80f13c9a --- /dev/null +++ b/patacrep/songs/chordpro/test/customchords.tex @@ -0,0 +1,14 @@ +\selectlanguage{english} + +\beginsong{}[ + by={ + }, +] + +\gtab{E4}{7:0133XX} +\gtab{E5}{7:0133XX:012300} +\gtab{E5/A*}{7:0133XX:012300} +\gtab{A#+2}{7:0133XX:012300} + + +\endsong diff --git a/patacrep/songs/chordpro/test/greensleeves.sgc b/patacrep/songs/chordpro/test/greensleeves.sgc index 1dee93ff..bd0ddd71 100644 --- a/patacrep/songs/chordpro/test/greensleeves.sgc +++ b/patacrep/songs/chordpro/test/greensleeves.sgc @@ -1,44 +1,60 @@ -{language : english} -{columns : 2} -{subtitle : Un sous titre} -{ title : Greensleeves} -{title : Un autre sous-titre} -{artist: Traditionnel} -{cover : traditionnel } -{album :Angleterre} +{language: english} +{columns: 2} +{title: Greensleeves} +{title: Un autre sous-titre} +{title: Un sous titre} +{artist: Traditionnel} +{album: Angleterre} +{cov: traditionnel} -{partition : greensleeves.ly} -A[Am]las, my love, ye [G]do me wrong -To [Am]cast me oft dis[E]curteously -And [Am]I have loved [G]you so long -De[Am]lighting [E]in your [Am]companie +{partition: greensleeves.ly} + + +{start_of_verse} + A[Am]las, my love, ye [G]do me wrong + To [Am]cast me oft dis[E]curteously + And [Am]I have loved [G]you so long + De[Am]lighting [E]in your [Am]companie +{end_of_verse} + {start_of_chorus} - [C]Green[B]sleeves was [G]all my joy - [Am]Greensleeves was [E]my delight - [C]Greensleeves was my [G]heart of gold - And [Am]who but [E]Ladie [Am]Greensleeves + [C]Green[B]sleeves was [G]all my joy + [Am]Greensleeves was [E]my delight + [C]Greensleeves was my [G]heart of gold + And [Am]who but [E]Ladie [Am]Greensleeves {end_of_chorus} -I [Am]have been ready [G]at your hand -To [Am]grant what ever [E]you would crave -I [Am]have both waged [G]life and land -Your [Am]love and [E]good will [Am]for to have -I [Am]bought thee kerchers [G]to thy head -That [Am]were wrought fine and [E]gallantly -I [Am]kept thee both at [G]boord and bed -Which [Am]cost my [E]purse well [Am]favouredly +{start_of_verse} + I [Am]have been ready [G]at your hand + To [Am]grant what ever [E]you would crave + I [Am]have both waged [G]life and land + Your [Am]love and [E]good will [Am]for to have +{end_of_verse} + + +{start_of_verse} + I [Am]bought thee kerchers [G]to thy head + That [Am]were wrought fine and [E]gallantly + I [Am]kept thee both at [G]boord and bed + Which [Am]cost my [E]purse well [Am]favouredly +{end_of_verse} + -I [Am]bought thee peticotes [G]of the best -The [Am]cloth so fine as [E]fine might be -I [Am]gave thee jewels [G]for thy chest -And [Am]all this [E]cost I [Am]spent on thee +{start_of_verse} + I [Am]bought thee peticotes [G]of the best + The [Am]cloth so fine as [E]fine might be + I [Am]gave thee jewels [G]for thy chest + And [Am]all this [E]cost I [Am]spent on thee +{end_of_verse} -Thy [Am]smock of silke, both [G]faire and white -With [Am]gold embrodered [E]gorgeously -Thy [Am]peticote of [G]sendall right -And [Am]this I [E]bought thee [Am]gladly +{start_of_verse} + Thy [Am]smock of silke, both [G]faire and white + With [Am]gold embrodered [E]gorgeously + Thy [Am]peticote of [G]sendall right + And [Am]this I [E]bought thee [Am]gladly +{end_of_verse} diff --git a/patacrep/songs/chordpro/test/greensleeves.source b/patacrep/songs/chordpro/test/greensleeves.source new file mode 100644 index 00000000..1dee93ff --- /dev/null +++ b/patacrep/songs/chordpro/test/greensleeves.source @@ -0,0 +1,44 @@ +{language : english} +{columns : 2} +{subtitle : Un sous titre} +{ title : Greensleeves} +{title : Un autre sous-titre} +{artist: Traditionnel} +{cover : traditionnel } +{album :Angleterre} + +{partition : greensleeves.ly} + + +A[Am]las, my love, ye [G]do me wrong +To [Am]cast me oft dis[E]curteously +And [Am]I have loved [G]you so long +De[Am]lighting [E]in your [Am]companie + +{start_of_chorus} + [C]Green[B]sleeves was [G]all my joy + [Am]Greensleeves was [E]my delight + [C]Greensleeves was my [G]heart of gold + And [Am]who but [E]Ladie [Am]Greensleeves +{end_of_chorus} + +I [Am]have been ready [G]at your hand +To [Am]grant what ever [E]you would crave +I [Am]have both waged [G]life and land +Your [Am]love and [E]good will [Am]for to have + +I [Am]bought thee kerchers [G]to thy head +That [Am]were wrought fine and [E]gallantly +I [Am]kept thee both at [G]boord and bed +Which [Am]cost my [E]purse well [Am]favouredly + +I [Am]bought thee peticotes [G]of the best +The [Am]cloth so fine as [E]fine might be +I [Am]gave thee jewels [G]for thy chest +And [Am]all this [E]cost I [Am]spent on thee + + +Thy [Am]smock of silke, both [G]faire and white +With [Am]gold embrodered [E]gorgeously +Thy [Am]peticote of [G]sendall right +And [Am]this I [E]bought thee [Am]gladly diff --git a/patacrep/songs/chordpro/test/greensleeves.tex b/patacrep/songs/chordpro/test/greensleeves.tex new file mode 100644 index 00000000..6a745a81 --- /dev/null +++ b/patacrep/songs/chordpro/test/greensleeves.tex @@ -0,0 +1,67 @@ +\selectlanguage{english} +\songcolumns{2} + +\beginsong{Greensleeves\\ +Un autre sous-titre\\ +Un sous titre}[ + by={ + Traditionnel }, + album={Angleterre}, + cov={traditionnel}, +] + +\cover + + + +\lilypond{greensleeves.ly} + + +\begin{verse} + A\[Am]las, my love, ye \[G]do me wrong + To \[Am]cast me oft dis\[E]curteously + And \[Am]I have loved \[G]you so long + De\[Am]lighting \[E]in your \[Am]companie +\end{verse} + + +\begin{chorus} + \[C]Green\[B]sleeves was \[G]all my joy + \[Am]Greensleeves was \[E]my delight + \[C]Greensleeves was my \[G]heart of gold + And \[Am]who but \[E]Ladie \[Am]Greensleeves +\end{chorus} + + +\begin{verse} + I \[Am]have been ready \[G]at your hand + To \[Am]grant what ever \[E]you would crave + I \[Am]have both waged \[G]life and land + Your \[Am]love and \[E]good will \[Am]for to have +\end{verse} + + +\begin{verse} + I \[Am]bought thee kerchers \[G]to thy head + That \[Am]were wrought fine and \[E]gallantly + I \[Am]kept thee both at \[G]boord and bed + Which \[Am]cost my \[E]purse well \[Am]favouredly +\end{verse} + + +\begin{verse} + I \[Am]bought thee peticotes \[G]of the best + The \[Am]cloth so fine as \[E]fine might be + I \[Am]gave thee jewels \[G]for thy chest + And \[Am]all this \[E]cost I \[Am]spent on thee +\end{verse} + + +\begin{verse} + Thy \[Am]smock of silke, both \[G]faire and white + With \[Am]gold embrodered \[E]gorgeously + Thy \[Am]peticote of \[G]sendall right + And \[Am]this I \[E]bought thee \[Am]gladly +\end{verse} + +\endsong diff --git a/patacrep/songs/chordpro/test/greensleeves.txt b/patacrep/songs/chordpro/test/greensleeves.txt deleted file mode 100644 index 069fbba8..00000000 --- a/patacrep/songs/chordpro/test/greensleeves.txt +++ /dev/null @@ -1,52 +0,0 @@ -{title: Greensleeves} -{title: Un autre sous-titre} -{title: Un sous titre} -{by: Traditionnel} -{album: Angleterre} -{columns: 2} -{cov: DIRNAME/traditionnel} -{language: english} -======== -{partition: DIRNAME/greensleeves.ly} - -{start_of_verse} - A[Am]las, my love, ye [G]do me wrong - To [Am]cast me oft dis[E]curteously - And [Am]I have loved [G]you so long - De[Am]lighting [E]in your [Am]companie -{end_of_verse} - -{start_of_chorus} - [C]Green[B]sleeves was [G]all my joy - [Am]Greensleeves was [E]my delight - [C]Greensleeves was my [G]heart of gold - And [Am]who but [E]Ladie [Am]Greensleeves -{end_of_chorus} - -{start_of_verse} - I [Am]have been ready [G]at your hand - To [Am]grant what ever [E]you would crave - I [Am]have both waged [G]life and land - Your [Am]love and [E]good will [Am]for to have -{end_of_verse} - -{start_of_verse} - I [Am]bought thee kerchers [G]to thy head - That [Am]were wrought fine and [E]gallantly - I [Am]kept thee both at [G]boord and bed - Which [Am]cost my [E]purse well [Am]favouredly -{end_of_verse} - -{start_of_verse} - I [Am]bought thee peticotes [G]of the best - The [Am]cloth so fine as [E]fine might be - I [Am]gave thee jewels [G]for thy chest - And [Am]all this [E]cost I [Am]spent on thee -{end_of_verse} - -{start_of_verse} - Thy [Am]smock of silke, both [G]faire and white - With [Am]gold embrodered [E]gorgeously - Thy [Am]peticote of [G]sendall right - And [Am]this I [E]bought thee [Am]gladly -{end_of_verse} diff --git a/patacrep/songs/chordpro/test/invalid_chord.sgc b/patacrep/songs/chordpro/test/invalid_chord.sgc new file mode 100644 index 00000000..7ec4fd65 --- /dev/null +++ b/patacrep/songs/chordpro/test/invalid_chord.sgc @@ -0,0 +1,5 @@ +{language: english} + +{start_of_verse} + This is invalid. +{end_of_verse} diff --git a/patacrep/songs/chordpro/test/invalid_chord.source b/patacrep/songs/chordpro/test/invalid_chord.source new file mode 100644 index 00000000..0e63a90b --- /dev/null +++ b/patacrep/songs/chordpro/test/invalid_chord.source @@ -0,0 +1 @@ +This is [] invalid. diff --git a/patacrep/songs/chordpro/test/invalid_chord.tex b/patacrep/songs/chordpro/test/invalid_chord.tex new file mode 100644 index 00000000..476d776a --- /dev/null +++ b/patacrep/songs/chordpro/test/invalid_chord.tex @@ -0,0 +1,13 @@ +\selectlanguage{english} + +\beginsong{}[ + by={ + }, +] + + +\begin{verse} + This is invalid. +\end{verse} + +\endsong diff --git a/patacrep/songs/chordpro/test/invalid_customchord.sgc b/patacrep/songs/chordpro/test/invalid_customchord.sgc new file mode 100644 index 00000000..341c9bd4 --- /dev/null +++ b/patacrep/songs/chordpro/test/invalid_customchord.sgc @@ -0,0 +1,2 @@ +{language: english} + diff --git a/patacrep/songs/chordpro/test/invalid_customchord.source b/patacrep/songs/chordpro/test/invalid_customchord.source new file mode 100644 index 00000000..d0baf679 --- /dev/null +++ b/patacrep/songs/chordpro/test/invalid_customchord.source @@ -0,0 +1,5 @@ +{define : } +{define: base-fret 7 frets 0 1 3 3 x x} +{define: E4 base-fret frets 0 1 3 3 x x} +{define: E4 base-fret H frets 0 1 3 3 x A} +{define: E5 base-fret 7 frets 0 1 3 3 x x fingers - 1 2 3 - A} diff --git a/patacrep/songs/chordpro/test/invalid_customchord.tex b/patacrep/songs/chordpro/test/invalid_customchord.tex new file mode 100644 index 00000000..bd99a922 --- /dev/null +++ b/patacrep/songs/chordpro/test/invalid_customchord.tex @@ -0,0 +1,10 @@ +\selectlanguage{english} + +\beginsong{}[ + by={ + }, +] + + + +\endsong diff --git a/patacrep/songs/chordpro/test/metadata.sgc b/patacrep/songs/chordpro/test/metadata.sgc index eee1bf9d..e4bb1b21 100644 --- a/patacrep/songs/chordpro/test/metadata.sgc +++ b/patacrep/songs/chordpro/test/metadata.sgc @@ -1,19 +1,18 @@ -{subtitle: Subtitle3} +{language: french} +{capo: Capo} {title: Title} {title: Subtitle1} -{subtitle: Subtitle4} -{t: Subtitle2} -{st: Subtitle5} -{language: french} -{language: english} -{by: Author1} -{artist: Author2} -{album: Albom} +{title: Subtitle2} +{title: Subtitle3} +{title: Subtitle4} +{title: Subtitle5} +{artist: Author1} +{artist: Author2} +{album: Album} {copyright: Copyright} -{cover: Cover} -{vcover: VCover} -{capo: Capo} +{cov: Cover} {key: foo: Foo} + {comment: Comment} {guitar_comment: GuitarComment} {image: Image} diff --git a/patacrep/songs/chordpro/test/metadata.source b/patacrep/songs/chordpro/test/metadata.source new file mode 100644 index 00000000..2e106444 --- /dev/null +++ b/patacrep/songs/chordpro/test/metadata.source @@ -0,0 +1,19 @@ +{subtitle: Subtitle3} +{title: Title} +{title: Subtitle1} +{subtitle: Subtitle4} +{t: Subtitle2} +{st: Subtitle5} +{language: french} +{language: english} +{by: Author1} +{artist: Author2} +{album: Album} +{copyright: Copyright} +{cover: Cover} +{capo: Capo} +{key: foo: Foo} +{comment: Comment} +{guitar_comment: GuitarComment} +{image: Image} +{partition: Lilypond} diff --git a/patacrep/songs/chordpro/test/metadata.tex b/patacrep/songs/chordpro/test/metadata.tex new file mode 100644 index 00000000..11004ef6 --- /dev/null +++ b/patacrep/songs/chordpro/test/metadata.tex @@ -0,0 +1,25 @@ +\selectlanguage{french} + +\beginsong{Title\\ +Subtitle1\\ +Subtitle2\\ +Subtitle3\\ +Subtitle4\\ +Subtitle5}[ + by={ + Author1, + Author2 }, + album={Album}, + copyright={Copyright}, + cov={Cover}, + foo={Foo}, +] + +\cover + +\textnote{Comment} +\musicnote{GuitarComment} +\image{Image} +\lilypond{Lilypond} + +\endsong diff --git a/patacrep/songs/chordpro/test/metadata.txt b/patacrep/songs/chordpro/test/metadata.txt deleted file mode 100644 index 1ba5f5c6..00000000 --- a/patacrep/songs/chordpro/test/metadata.txt +++ /dev/null @@ -1,21 +0,0 @@ -{title: Title} -{title: Subtitle1} -{title: Subtitle2} -{title: Subtitle3} -{title: Subtitle4} -{title: Subtitle5} -{by: Author1} -{by: Author2} -{key: {foo: Foo}} -{album: Albom} -{capo: Capo} -{copyright: Copyright} -{cov: DIRNAME/Cover} -{language: english} -{language: french} -{vcov: VCover} -======== -{comment: Comment} -{guitar_comment: GuitarComment} -{image: DIRNAME/Image} -{partition: DIRNAME/Lilypond} diff --git a/patacrep/songs/chordpro/test/test_parser.py b/patacrep/songs/chordpro/test/test_parser.py index 7f1c2586..3a1e9b7c 100644 --- a/patacrep/songs/chordpro/test/test_parser.py +++ b/patacrep/songs/chordpro/test/test_parser.py @@ -6,51 +6,49 @@ import glob import os import unittest -from patacrep.songs.chordpro import syntax as chordpro +from patacrep.build import DEFAULT_CONFIG +from patacrep.songs.chordpro import ChordproSong +from patacrep.test import disable_logging -class ParserTxtRenderer(unittest.TestCase): - """Test parser, and renderer as a txt file.""" +LANGUAGES = { + 'tex': 'latex', + 'sgc': 'chordpro', +} + +class TestParsingRendering(unittest.TestCase): + """Test parsing and rendering""" maxDiff = None - def __init__(self, methodname="runTest", basename=None): - super().__init__(methodname) - self.basename = basename - - def shortDescription(self): - return "Parsing file '{}.txt'.".format(self.basename) - - def runTest(self): - """Test txt output (default, debug output).""" - # pylint: disable=invalid-name - - if self.basename is None: - return - with open("{}.sgc".format(self.basename), 'r', encoding='utf8') as sourcefile: - with open("{}.txt".format(self.basename), 'r', encoding='utf8') as expectfile: - #print(os.path.basename(sourcefile.name)) - #with open("{}.txt.diff".format(self.basename), 'w', encoding='utf8') as difffile: - # difffile.write( - # str(chordpro.parse_song( - # sourcefile.read(), - # os.path.basename(sourcefile.name), - # )).strip() - # ) - # sourcefile.seek(0) - self.assertMultiLineEqual( - str(chordpro.parse_song( - sourcefile.read(), - os.path.abspath(sourcefile.name), - )).strip(), - expectfile.read().strip().replace("DIRNAME", os.path.dirname(self.basename)), - ) - -def load_tests(__loader, tests, __pattern): - """Load several tests given test files present in the directory.""" - # Load all txt files as tests - for txt in sorted(glob.glob(os.path.join( - os.path.dirname(__file__), - '*.txt', - ))): - tests.addTest(ParserTxtRenderer(basename=txt[:-len('.txt')])) - return tests + def test_all(self): + """Test all `*.source` files. + + For any given `foo.source`, it is parsed as a chordpro file, and + should be rendered as `foo.sgc` with the chordpro renderer, and + `foo.tex` with the latex renderer. + """ + config = DEFAULT_CONFIG.copy() + config.update({ + 'encoding': 'utf8', + }) + for source in sorted(glob.glob(os.path.join( + os.path.dirname(__file__), + '*.source', + ))): + base = source[:-len(".source")] + for dest in LANGUAGES: + destname = "{}.{}".format(base, dest) + if not os.path.exists(destname): + continue + with open(destname, 'r', encoding='utf8') as expectfile: + chordproname = "{}.source".format(base) + config['filename'] = chordproname + with disable_logging(): + 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(), + ) diff --git a/patacrep/songs/latex/__init__.py b/patacrep/songs/latex/__init__.py index 8a0893c1..a0d9c945 100644 --- a/patacrep/songs/latex/__init__.py +++ b/patacrep/songs/latex/__init__.py @@ -22,16 +22,19 @@ class LatexSong(Song): del self.data['@titles'] self.languages = self.data['@languages'] del self.data['@languages'] - self.authors = [self.data['by']] - del self.data['by'] + if "by" in self.data: + self.authors = [self.data['by']] + del self.data['by'] + else: + self.authors = [] - def tex(self, output): - """Return the LaTeX code rendering the song.""" - return r'\input{{{}}}'.format(files.path2posix( - files.relpath( - self.fullpath, - os.path.dirname(output) - ))) + def render_latex(self, output): + """Return the code rendering the song.""" + path = files.path2posix(files.relpath( + self.fullpath, + os.path.dirname(output) + )) + return r'\import{{{}/}}{{{}}}'.format(os.path.dirname(path), os.path.basename(path)) SONG_PARSERS = { 'is': LatexSong, diff --git a/patacrep/songs/syntax.py b/patacrep/songs/syntax.py index aa2075a2..7f019374 100644 --- a/patacrep/songs/syntax.py +++ b/patacrep/songs/syntax.py @@ -20,14 +20,31 @@ class Parser: column = (token.lexpos - last_cr) + 1 return column + @staticmethod + def error(*, line=None, column=None, message=""): + """Display an error message""" + coordinates = [] + if line is not None: + coordinates.append("line {}".format(line)) + if column is not None: + coordinates.append("column {}".format(column)) + text = ", ".join(coordinates) + if message and text: + text += ": " + message + elif message: + text += message + else: + text += "." + LOGGER.error(text) + def p_error(self, token): """Manage parsing errors.""" - if token: - LOGGER.error( - "Error in file {}, line {}:{}.".format( - str(self.filename), - token.lineno, - self.__find_column(token), - ) + if token is None: + self.error( + message="Unexpected end of file.", + ) + else: + self.error( + line=token.lineno, + column=self.__find_column(token), ) - diff --git a/patacrep/templates.py b/patacrep/templates.py index 95c06469..4b81c08d 100644 --- a/patacrep/templates.py +++ b/patacrep/templates.py @@ -22,22 +22,22 @@ _LATEX_SUBS = ( _VARIABLE_REGEXP = re.compile( r""" - \(\*\ *variables\ *\*\) # Match (* variables *) - ( # Match and capture the following: - (?: # Start of non-capturing group, used to match a single character - (?! # only if it's impossible to match the following: - \(\*\ * # - a literal (* - (?: # Inner non-capturing group, used for the following alternation: - variables # - Either match the word variables - | # or - endvariables # - the word endvariables - ) # End of inner non-capturing group - \ *\*\) # - a literal *) - ) # End of negative lookahead assertion - . # Match any single character - )* # Repeat as often as possible - ) # End of capturing group 1 - \(\*\ *endvariables\ *\*\) # until (* endvariables *) is matched. + \(\*-?\ *variables\ *\*\) # Match (* variables *) or (*- variables *) + ( # Match and capture the following: + (?: # Start of non-capturing group, used to match a single character + (?! # only if it's impossible to match the following: + \(\*-?\ * # - a literal (* or (*- + (?: # Inner non-capturing group, used for the following alternation: + variables # - Either match the word variables + | # or + endvariables # - the word endvariables + ) # End of inner non-capturing group + \ *-?\*\) # - a literal *) or -*) + ) # End of negative lookahead assertion + . # Match any single character + )* # Repeat as often as possible + ) # End of capturing group 1 + \(\*\ *endvariables\ *-?\*\) # until (* endvariables *) or (* endvariables -*) is matched. """, re.VERBOSE|re.DOTALL) @@ -66,28 +66,28 @@ def _escape_tex(value): return newval -class TexRenderer: +class Renderer: """Render a template to a LaTeX file.""" # pylint: disable=too-few-public-methods - def __init__(self, template, texenv, encoding=None): + def __init__(self, template, jinjaenv, encoding=None): self.encoding = encoding - self.texenv = texenv - self.texenv.block_start_string = '(*' - self.texenv.block_end_string = '*)' - self.texenv.variable_start_string = '((' - self.texenv.variable_end_string = '))' - self.texenv.comment_start_string = '(% comment %)' - self.texenv.comment_end_string = '(% endcomment %)' - self.texenv.line_comment_prefix = '%!' - self.texenv.filters['escape_tex'] = _escape_tex - self.texenv.trim_blocks = True - self.texenv.lstrip_blocks = True - self.texenv.globals["path2posix"] = files.path2posix - self.template = self.texenv.get_template(template) - - -class TexBookRenderer(TexRenderer): + self.jinjaenv = jinjaenv + self.jinjaenv.block_start_string = '(*' + self.jinjaenv.block_end_string = '*)' + self.jinjaenv.variable_start_string = '((' + self.jinjaenv.variable_end_string = '))' + self.jinjaenv.comment_start_string = '(% comment %)' + self.jinjaenv.comment_end_string = '(% endcomment %)' + self.jinjaenv.line_comment_prefix = '%!' + self.jinjaenv.filters['escape_tex'] = _escape_tex + self.jinjaenv.trim_blocks = True + self.jinjaenv.lstrip_blocks = True + self.jinjaenv.globals["path2posix"] = files.path2posix + self.template = self.jinjaenv.get_template(template) + + +class TexBookRenderer(Renderer): """Tex renderer for the whole songbook""" def __init__(self, template, datadirs, lang, encoding=None): @@ -106,17 +106,17 @@ class TexBookRenderer(TexRenderer): FileSystemLoader(os.path.join(datadir, 'templates')) for datadir in datadirs ] - texenv = Environment( + jinjaenv = Environment( loader=ChoiceLoader(loaders), extensions=[VariablesExtension], ) try: - super().__init__(template, texenv, encoding) + super().__init__(template, jinjaenv, encoding) except TemplateNotFound as exception: # Only works if all loaders are FileSystemLoader(). paths = [ item - for loader in self.texenv.loader.loaders + for loader in self.jinjaenv.loader.loaders for item in loader.searchpath ] raise errors.TemplateError( @@ -199,13 +199,13 @@ class TexBookRenderer(TexRenderer): """ subvariables = {} - templatename = self.texenv.get_template(template).filename + templatename = self.jinjaenv.get_template(template).filename with patacrep.encoding.open_read( templatename, encoding=self.encoding ) as template_file: content = template_file.read() - subtemplates = list(find_templates(self.texenv.parse(content))) + subtemplates = list(find_templates(self.jinjaenv.parse(content))) match = re.findall(_VARIABLE_REGEXP, content) if match: for var in match: diff --git a/patacrep/test.py b/patacrep/test.py index ce135fef..1a1eaae4 100644 --- a/patacrep/test.py +++ b/patacrep/test.py @@ -1,11 +1,20 @@ """Tests""" +import contextlib import doctest +import logging import os import unittest import patacrep +@contextlib.contextmanager +def disable_logging(): + """Context locally disabling logging.""" + logging.disable(logging.CRITICAL) + yield + logging.disable(logging.NOTSET) + def suite(): """Return a TestSuite object, to test whole `patacrep` package. @@ -24,3 +33,4 @@ def load_tests(__loader, tests, __pattern): if __name__ == "__main__": unittest.TextTestRunner().run(suite()) +