diff --git a/patacrep/songs/chordpro/__init__.py b/patacrep/songs/chordpro/__init__.py index cb0be42a..d594a0b3 100644 --- a/patacrep/songs/chordpro/__init__.py +++ b/patacrep/songs/chordpro/__init__.py @@ -22,28 +22,30 @@ 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): context = { - 'language': self.cached['song'].get_directive('language', self.config['lang']), - 'columns': self.cached['song'].get_directive('columns', 1), + 'language': self.config.get( + 'lang', + self.cached['song'].get_data_argument('language', 'english'), + ), + #'columns': self.cached['song'].get_data_argument('columns', 1), "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]), "metadata": self.data, - "beginsong": self.cached['song'].meta_beginsong(), "render": self.render_tex, } self.texenv = Environment(loader=FileSystemLoader(os.path.join( os.path.abspath(pkg_resources.resource_filename(__name__, 'data')), 'latex' ))) - return self.render_tex(context, self.cached['song'].content, template="chordpro.tex") + return self.render_tex(context, self.cached['song'].content, template="song.tex") @contextfunction def render_tex(self, context, content, template=None): diff --git a/patacrep/songs/chordpro/ast.py b/patacrep/songs/chordpro/ast.py index 5db13afc..c74a628b 100644 --- a/patacrep/songs/chordpro/ast.py +++ b/patacrep/songs/chordpro/ast.py @@ -2,12 +2,41 @@ # 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): + self._keys = [] + self._values = {} + + 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 +50,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 = { @@ -62,6 +82,10 @@ class AST: base = self._template return "content_{}.{}".format(base, extension) + def chordpro(self): + """Return the chordpro string corresponding to this object.""" + raise NotImplementedError() + class Line(AST): """A line is a sequence of (possibly truncated) words, spaces and chords.""" @@ -76,8 +100,8 @@ class Line(AST): self.line.insert(0, data) return self - def __str__(self): - return "".join([str(item) for item in self.line]) + def chordpro(self): + return "".join([item.chordpro() for item in self.line]) def strip(self): """Remove spaces at the beginning and end of line.""" @@ -94,6 +118,7 @@ class Line(AST): class LineElement(AST): """Something present on a line.""" + # pylint: disable=abstract-method pass class Word(LineElement): @@ -104,7 +129,7 @@ class Word(LineElement): super().__init__() self.value = value - def __str__(self): + def chordpro(self): return self.value class Space(LineElement): @@ -114,7 +139,7 @@ class Space(LineElement): def __init__(self): super().__init__() - def __str__(self): + def chordpro(self): return " " class ChordList(LineElement): @@ -124,9 +149,9 @@ class ChordList(LineElement): def __init__(self, *chords): self.chords = chords - def __str__(self): + def chordpro(self): return "[{}]".format(" ".join( - [str(chord) for chord in self.chords] + [chord.chordpro() for chord in self.chords] )) class Chord(AST): @@ -151,7 +176,7 @@ class Chord(AST): self.basskey = basskey self.bassalteration = bassalteration - def __str__(self): + def chordpro(self): text = "" text += self.key if self.alteration is not None: @@ -166,50 +191,6 @@ class Chord(AST): text += self.bassalteration return text -class Define(AST): - """A chord definition. - - Attributes: - - .. 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. - """ - _template = "define" - inline = True - - 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 - - def __str__(self): - text = str(self.key) - if self.basefret is not None: - text += " base-fret " + str(self.basefret) - text += " frets" - for fret in self.frets: - if fret is None: - text += " x" - else: - text += " " + str(fret) - if self.fingers: - text += " fingers" - for finger in self.fingers: - if finger is None: - text += " -" - else: - text += " " + str(finger) - return "{{define: {}}}".format(text) - class Verse(AST): """A verse (or bridge, or chorus)""" _template = "verse" @@ -225,10 +206,10 @@ class Verse(AST): self.lines.insert(0, data) return self - def __str__(self): + def chordpro(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])), + content=_indent("\n".join([line.chordpro() for line in self.lines])), ) class Chorus(Verse): @@ -248,17 +229,17 @@ 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", + "define": "add_cumulative", + "language": "add_cumulative", } #: Some directives have to be processed before being considered. @@ -271,7 +252,7 @@ class Song(AST): def __init__(self, filename): super().__init__() self.content = [] - self.meta = [] + self.meta = OrderedLifoDict() self._authors = [] self._titles = [] self._subtitles = [] @@ -282,9 +263,8 @@ class Song(AST): """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.keyword in self.PROCESS_DIRECTIVE: + data = getattr(self, self.PROCESS_DIRECTIVE[data.keyword])(data) if data is None: # New line @@ -300,12 +280,11 @@ 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 @@ -316,62 +295,71 @@ class Song(AST): 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) + for key in self.keys: + yield "{{key: {}}}".format(key.chordpro()) + for value in self.meta.values(): + if isinstance(value, list): + yield "\n".join([item.chordpro() for item in value]) + else: + yield value.chordpro() - def __str__(self): + def chordpro(self): return ( "\n".join(self.str_meta()).strip() + - "\n========\n" + "\n\n" + - "\n".join([str(item) for item in self.content]).strip() + "\n".join([item.chordpro() for item in self.content]).strip() ) - def add_title(self, __ignored, title): + def add_title(self, data): """Add a title""" - self._titles.insert(0, 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 add_subtitle(self, __ignored, title): + def get_data_argument(self, keyword, default): + """Return `self.meta[keyword].argument`. + + Return `default` if `self.meta[keyword]` does not exist. + + 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, 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(":") + self._keys.insert(0, Directive( key.strip(), ":".join(argument).strip(), )) @@ -384,15 +372,6 @@ class Song(AST): """ 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 @@ -410,17 +389,15 @@ class Newline(AST): """New line""" _template = "newline" - def __str__(self): + def chordpro(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 @@ -431,26 +408,13 @@ 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): + def chordpro(self): if self.argument is not None: return "{{{}: {}}}".format( self.keyword, @@ -459,16 +423,54 @@ class Directive(AST): else: return "{{{}}}".format(self.keyword) - @property - def as_tuple(self): - """Return the directive as a tuple.""" - return (self.keyword, self.argument) + def __str__(self): + return self.argument + +class Define(Directive): + """A chord definition. + + Attributes: + + .. 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 __eq__(self, other): - return self.as_tuple == other.as_tuple + 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 chordpro(self): + text = self.key.chordpro() + if self.basefret is not None: + text += " base-fret " + str(self.basefret) + text += " frets" + for fret in self.frets: + if fret is None: + text += " x" + else: + text += " " + str(fret) + if self.fingers: + text += " fingers" + for finger in self.fingers: + if finger is None: + text += " -" + else: + text += " " + str(finger) + return "{{define: {}}}".format(text) - def __lt__(self, other): - return self.as_tuple < other.as_tuple + def __str__(self): + return None class Tab(AST): """Tablature""" @@ -484,7 +486,7 @@ class Tab(AST): self.content.insert(0, data) return self - def __str__(self): + def chordpro(self): return '{{start_of_tab}}\n{}\n{{end_of_tab}}'.format( _indent("\n".join(self.content)), ) diff --git a/patacrep/songs/chordpro/data/latex/chordpro.tex b/patacrep/songs/chordpro/data/latex/song.tex similarity index 68% rename from patacrep/songs/chordpro/data/latex/chordpro.tex rename to patacrep/songs/chordpro/data/latex/song.tex index dec5f3f5..8da583af 100644 --- a/patacrep/songs/chordpro/data/latex/chordpro.tex +++ b/patacrep/songs/chordpro/data/latex/song.tex @@ -6,12 +6,14 @@ (* if language is defined -*) \selectlanguage{((language))} (* endif *) -\songcolumns{((metadata.columns))} +\songcolumns{(( metadata.columns ))} \beginsong{((titles))}[ by={((authors))}, - (* for (key, argument) in beginsong *) - ((key))={((argument))}, + (* for key in ['album', 'copyright', 'cov', 'vcov', 'tag'] *) + (* if key in metadata *) + (( key ))={(( metadata[key] ))}, + (* endif *) (* endfor *) ] @@ -19,6 +21,10 @@ \cover (* endif -*) +(* for chord in metadata['define'] *) + (( render(chord) )) +(* endfor *) + (* for item in content -*) (( render(item) )) (* endfor *) diff --git a/patacrep/songs/chordpro/syntax.py b/patacrep/songs/chordpro/syntax.py index 91a0cb41..ea50e267 100644 --- a/patacrep/songs/chordpro/syntax.py +++ b/patacrep/songs/chordpro/syntax.py @@ -130,12 +130,13 @@ class ChordproParser(Parser): | 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: - symbols[4].keyword = symbols[3] - symbols[0] = symbols[4] - if symbols[0].keyword == 'define': + keyword = symbols[3] + argument = symbols[4] + + if keyword == "define": match = re.compile( r""" (?P[^\ ]*)\ * @@ -144,12 +145,14 @@ class ChordproParser(Parser): (fingers\ *(?P(([0-4-])\ *)*))? """, re.VERBOSE - ).match(symbols[0].argument) + ).match(argument) if match is None: TODO symbols[0] = _parse_define(**match.groupdict()) + else: + symbols[0] = ast.Directive(keyword, argument) @staticmethod def p_directive_next(symbols): @@ -157,11 +160,12 @@ class ChordproParser(Parser): | COLON TEXT | 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() + else: + symbols[0] = None @staticmethod def p_line(symbols): diff --git a/patacrep/songs/chordpro/test/00.txt b/patacrep/songs/chordpro/test/00.txt index dbbd9c50..8b137891 100644 --- a/patacrep/songs/chordpro/test/00.txt +++ b/patacrep/songs/chordpro/test/00.txt @@ -1 +1 @@ -======== + diff --git a/patacrep/songs/chordpro/test/01.txt b/patacrep/songs/chordpro/test/01.txt index 84cf4364..9665cac0 100644 --- a/patacrep/songs/chordpro/test/01.txt +++ b/patacrep/songs/chordpro/test/01.txt @@ -1,4 +1,4 @@ -======== + {start_of_verse} A verse line {end_of_verse} diff --git a/patacrep/songs/chordpro/test/02.txt b/patacrep/songs/chordpro/test/02.txt index f3fbd9e9..ef03158b 100644 --- a/patacrep/songs/chordpro/test/02.txt +++ b/patacrep/songs/chordpro/test/02.txt @@ -1,2 +1,2 @@ {title: A directive} -======== + diff --git a/patacrep/songs/chordpro/test/03.txt b/patacrep/songs/chordpro/test/03.txt index dbbd9c50..8b137891 100644 --- a/patacrep/songs/chordpro/test/03.txt +++ b/patacrep/songs/chordpro/test/03.txt @@ -1 +1 @@ -======== + diff --git a/patacrep/songs/chordpro/test/04.txt b/patacrep/songs/chordpro/test/04.txt index 3336d565..9e9932a3 100644 --- a/patacrep/songs/chordpro/test/04.txt +++ b/patacrep/songs/chordpro/test/04.txt @@ -1,4 +1,4 @@ -======== + {start_of_chorus} A one line chorus {end_of_chorus} diff --git a/patacrep/songs/chordpro/test/05.txt b/patacrep/songs/chordpro/test/05.txt index b2f99be2..b7736212 100644 --- a/patacrep/songs/chordpro/test/05.txt +++ b/patacrep/songs/chordpro/test/05.txt @@ -1,4 +1,4 @@ -======== + {start_of_bridge} A one line bridge {end_of_bridge} diff --git a/patacrep/songs/chordpro/test/06.txt b/patacrep/songs/chordpro/test/06.txt index dbbd9c50..8b137891 100644 --- a/patacrep/songs/chordpro/test/06.txt +++ b/patacrep/songs/chordpro/test/06.txt @@ -1 +1 @@ -======== + diff --git a/patacrep/songs/chordpro/test/07.txt b/patacrep/songs/chordpro/test/07.txt index 7fb8bc64..3c45010c 100644 --- a/patacrep/songs/chordpro/test/07.txt +++ b/patacrep/songs/chordpro/test/07.txt @@ -1,4 +1,4 @@ -======== + {start_of_tab} A tab {end_of_tab} diff --git a/patacrep/songs/chordpro/test/08.txt b/patacrep/songs/chordpro/test/08.txt index 92c183b1..d224789c 100644 --- a/patacrep/songs/chordpro/test/08.txt +++ b/patacrep/songs/chordpro/test/08.txt @@ -1,4 +1,4 @@ -======== + {start_of_verse} A lot of new lines {end_of_verse} diff --git a/patacrep/songs/chordpro/test/09.txt b/patacrep/songs/chordpro/test/09.txt index b7669e62..6d19ba36 100644 --- a/patacrep/songs/chordpro/test/09.txt +++ b/patacrep/songs/chordpro/test/09.txt @@ -1,5 +1,5 @@ {title: and a directive} -======== + {start_of_verse} A lot of new lines {end_of_verse} diff --git a/patacrep/songs/chordpro/test/10.txt b/patacrep/songs/chordpro/test/10.txt index b96d8637..c289fda9 100644 --- a/patacrep/songs/chordpro/test/10.txt +++ b/patacrep/songs/chordpro/test/10.txt @@ -1,4 +1,4 @@ -======== + {start_of_verse} A line[A] with a chord {end_of_verse} diff --git a/patacrep/songs/chordpro/test/11.txt b/patacrep/songs/chordpro/test/11.txt index 2a9eaf17..ccf1d520 100644 --- a/patacrep/songs/chordpro/test/11.txt +++ b/patacrep/songs/chordpro/test/11.txt @@ -1,4 +1,4 @@ -======== + {start_of_verse} A line ending with a chord[A] {end_of_verse} diff --git a/patacrep/songs/chordpro/test/12.txt b/patacrep/songs/chordpro/test/12.txt index 83c11625..72a5b745 100644 --- a/patacrep/songs/chordpro/test/12.txt +++ b/patacrep/songs/chordpro/test/12.txt @@ -1,4 +1,4 @@ -======== + {start_of_verse} [A]A line starting with a chord {end_of_verse} diff --git a/patacrep/songs/chordpro/test/13.txt b/patacrep/songs/chordpro/test/13.txt index 447f67dd..b2f0526f 100644 --- a/patacrep/songs/chordpro/test/13.txt +++ b/patacrep/songs/chordpro/test/13.txt @@ -1,4 +1,4 @@ -======== + {start_of_tab} A table wit many # weir [ diff --git a/patacrep/songs/chordpro/test/21.txt b/patacrep/songs/chordpro/test/21.txt index 84cf4364..9665cac0 100644 --- a/patacrep/songs/chordpro/test/21.txt +++ b/patacrep/songs/chordpro/test/21.txt @@ -1,4 +1,4 @@ -======== + {start_of_verse} A verse line {end_of_verse} diff --git a/patacrep/songs/chordpro/test/22.txt b/patacrep/songs/chordpro/test/22.txt index f3fbd9e9..ef03158b 100644 --- a/patacrep/songs/chordpro/test/22.txt +++ b/patacrep/songs/chordpro/test/22.txt @@ -1,2 +1,2 @@ {title: A directive} -======== + diff --git a/patacrep/songs/chordpro/test/23.txt b/patacrep/songs/chordpro/test/23.txt index dbbd9c50..8b137891 100644 --- a/patacrep/songs/chordpro/test/23.txt +++ b/patacrep/songs/chordpro/test/23.txt @@ -1 +1 @@ -======== + diff --git a/patacrep/songs/chordpro/test/24.txt b/patacrep/songs/chordpro/test/24.txt index 3336d565..9e9932a3 100644 --- a/patacrep/songs/chordpro/test/24.txt +++ b/patacrep/songs/chordpro/test/24.txt @@ -1,4 +1,4 @@ -======== + {start_of_chorus} A one line chorus {end_of_chorus} diff --git a/patacrep/songs/chordpro/test/25.txt b/patacrep/songs/chordpro/test/25.txt index b2f99be2..b7736212 100644 --- a/patacrep/songs/chordpro/test/25.txt +++ b/patacrep/songs/chordpro/test/25.txt @@ -1,4 +1,4 @@ -======== + {start_of_bridge} A one line bridge {end_of_bridge} diff --git a/patacrep/songs/chordpro/test/26.txt b/patacrep/songs/chordpro/test/26.txt index dbbd9c50..8b137891 100644 --- a/patacrep/songs/chordpro/test/26.txt +++ b/patacrep/songs/chordpro/test/26.txt @@ -1 +1 @@ -======== + diff --git a/patacrep/songs/chordpro/test/27.txt b/patacrep/songs/chordpro/test/27.txt index 7fb8bc64..3c45010c 100644 --- a/patacrep/songs/chordpro/test/27.txt +++ b/patacrep/songs/chordpro/test/27.txt @@ -1,4 +1,4 @@ -======== + {start_of_tab} A tab {end_of_tab} diff --git a/patacrep/songs/chordpro/test/28.txt b/patacrep/songs/chordpro/test/28.txt index 92c183b1..d224789c 100644 --- a/patacrep/songs/chordpro/test/28.txt +++ b/patacrep/songs/chordpro/test/28.txt @@ -1,4 +1,4 @@ -======== + {start_of_verse} A lot of new lines {end_of_verse} diff --git a/patacrep/songs/chordpro/test/29.txt b/patacrep/songs/chordpro/test/29.txt index b7669e62..6d19ba36 100644 --- a/patacrep/songs/chordpro/test/29.txt +++ b/patacrep/songs/chordpro/test/29.txt @@ -1,5 +1,5 @@ {title: and a directive} -======== + {start_of_verse} A lot of new lines {end_of_verse} diff --git a/patacrep/songs/chordpro/test/chords.txt b/patacrep/songs/chordpro/test/chords.txt index 462bb182..2a98ce94 100644 --- a/patacrep/songs/chordpro/test/chords.txt +++ b/patacrep/songs/chordpro/test/chords.txt @@ -1,4 +1,4 @@ -======== + {start_of_verse} [A]Simple [Bb]BĂ©mol diff --git a/patacrep/songs/chordpro/test/customchords.txt b/patacrep/songs/chordpro/test/customchords.txt index c8d99d13..52c9f0e3 100644 --- a/patacrep/songs/chordpro/test/customchords.txt +++ b/patacrep/songs/chordpro/test/customchords.txt @@ -1,3 +1,3 @@ -======== {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 - -} + diff --git a/patacrep/songs/chordpro/test/greensleeves.txt b/patacrep/songs/chordpro/test/greensleeves.txt index 069fbba8..538a146d 100644 --- a/patacrep/songs/chordpro/test/greensleeves.txt +++ b/patacrep/songs/chordpro/test/greensleeves.txt @@ -2,11 +2,11 @@ {title: Un autre sous-titre} {title: Un sous titre} {by: Traditionnel} -{album: Angleterre} +{language: english} {columns: 2} {cov: DIRNAME/traditionnel} -{language: english} -======== +{album: Angleterre} + {partition: DIRNAME/greensleeves.ly} {start_of_verse} diff --git a/patacrep/songs/chordpro/test/metadata.txt b/patacrep/songs/chordpro/test/metadata.txt index 1ba5f5c6..77b9d08b 100644 --- a/patacrep/songs/chordpro/test/metadata.txt +++ b/patacrep/songs/chordpro/test/metadata.txt @@ -7,14 +7,14 @@ {by: Author1} {by: Author2} {key: {foo: Foo}} +{language: french} +{language: english} {album: Albom} -{capo: Capo} {copyright: Copyright} {cov: DIRNAME/Cover} -{language: english} -{language: french} {vcov: VCover} -======== +{capo: Capo} + {comment: Comment} {guitar_comment: GuitarComment} {image: DIRNAME/Image} diff --git a/patacrep/songs/chordpro/test/test_parser.py b/patacrep/songs/chordpro/test/test_parser.py index 55610bf4..ff2b628f 100644 --- a/patacrep/songs/chordpro/test/test_parser.py +++ b/patacrep/songs/chordpro/test/test_parser.py @@ -29,10 +29,10 @@ class ParserTxtRenderer(unittest.TestCase): with open("{}.sgc".format(self.basename), 'r', encoding='utf8') as sourcefile: with open("{}.txt".format(self.basename), 'r', encoding='utf8') as expectfile: self.assertMultiLineEqual( - str(chordpro.parse_song( + chordpro.parse_song( sourcefile.read(), os.path.abspath(sourcefile.name), - )).strip(), + ).chordpro().strip(), expectfile.read().strip().replace("DIRNAME", os.path.dirname(self.basename)), )