From 80b0fbabaf6408beb23ce2822d3f74f6b82903c2 Mon Sep 17 00:00:00 2001 From: Louis Date: Sun, 23 Aug 2015 15:20:53 +0200 Subject: [PATCH 01/32] Deleting useless comment --- patacrep/songs/chordpro/test/test_parser.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/patacrep/songs/chordpro/test/test_parser.py b/patacrep/songs/chordpro/test/test_parser.py index 7f1c2586..55610bf4 100644 --- a/patacrep/songs/chordpro/test/test_parser.py +++ b/patacrep/songs/chordpro/test/test_parser.py @@ -28,15 +28,6 @@ class ParserTxtRenderer(unittest.TestCase): 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(), From 89805761393e272c59e7e858f8a32cb44092060c Mon Sep 17 00:00:00 2001 From: Louis Date: Sun, 23 Aug 2015 17:27:33 +0200 Subject: [PATCH 02/32] [WIP] First draft to chords parsing and rendering --- patacrep/data/examples/songs/chords.sgc | 17 +++++++ patacrep/songs/chordpro/ast.py | 22 +++++++-- .../chordpro/data/latex/content_chord.tex | 14 +++++- patacrep/songs/chordpro/lexer.py | 12 ++++- patacrep/songs/chordpro/syntax.py | 46 +++++++++++++++++-- patacrep/songs/chordpro/test/chords.sgc | 12 +++++ patacrep/songs/chordpro/test/chords.txt | 15 ++++++ 7 files changed, 129 insertions(+), 9 deletions(-) create mode 100644 patacrep/data/examples/songs/chords.sgc create mode 100644 patacrep/songs/chordpro/test/chords.sgc create mode 100644 patacrep/songs/chordpro/test/chords.txt diff --git a/patacrep/data/examples/songs/chords.sgc b/patacrep/data/examples/songs/chords.sgc new file mode 100644 index 00000000..a1076a44 --- /dev/null +++ b/patacrep/data/examples/songs/chords.sgc @@ -0,0 +1,17 @@ +{language: english} +{columns: 1} +{title: Chords testing} +{subtitle: Test of the chords specification and LaTeX translation} + +[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 diff --git a/patacrep/songs/chordpro/ast.py b/patacrep/songs/chordpro/ast.py index b82b46a9..033103a7 100644 --- a/patacrep/songs/chordpro/ast.py +++ b/patacrep/songs/chordpro/ast.py @@ -122,12 +122,28 @@ class Chord(LineElement): _template = "chord" - def __init__(self, value): + def __init__(self, todo_note, todo_diesebemol, todo_mdimmajsus, todo_chiffre, todo_chordbis): super().__init__() - self.value = value + self.todo_note = todo_note + self.todo_diesebemol = todo_diesebemol + self.todo_mdimmajsus = todo_mdimmajsus + self.todo_chiffre = todo_chiffre + self.todo_chordbis = todo_chordbis def __str__(self): - return "[{}]".format(self.value) + text = "" + text += self.todo_note + if self.todo_diesebemol is not None: + text += self.todo_diesebemol + if self.todo_mdimmajsus is not None: + text += self.todo_mdimmajsus + if self.todo_chiffre is not None: + text += str(self.todo_chiffre) + if self.todo_chordbis is not None: + text += "/" + self.todo_chordbis[0] + if self.todo_chordbis[1] is not None: + text += self.todo_chordbis[1] + return "[{}]".format(text) class Verse(AST): """A verse (or bridge, or chorus)""" diff --git a/patacrep/songs/chordpro/data/latex/content_chord.tex b/patacrep/songs/chordpro/data/latex/content_chord.tex index bd2bd8b8..f6639511 100644 --- a/patacrep/songs/chordpro/data/latex/content_chord.tex +++ b/patacrep/songs/chordpro/data/latex/content_chord.tex @@ -1 +1,13 @@ -\[(( content.value ))] +\[ + ((- content.todo_note -)) + (* if content.todo_diesebemol == '#' *)#(* endif -*) + (* if content.todo_diesebemol == 'b' *)&(* endif -*) + (* if content.todo_mdimmajsus *)((content.todo_mdimmajsus))(* endif -*) + (* if content.todo_chiffre *)((content.todo_chiffre))(* endif -*) + (* if content.todo_chordbis -*) + / + ((- content.todo_chordbis[0] -)) + (* if content.todo_chordbis[1] == '#' *)#(* endif -*) + (* if content.todo_chordbis[1] == 'b' *)&(* endif -*) + (* endif -*) +] diff --git a/patacrep/songs/chordpro/lexer.py b/patacrep/songs/chordpro/lexer.py index 7f1582e6..de7422b4 100644 --- a/patacrep/songs/chordpro/lexer.py +++ b/patacrep/songs/chordpro/lexer.py @@ -9,7 +9,11 @@ LOGGER = logging.getLogger() tokens = ( 'LBRACE', 'RBRACE', - 'CHORD', + 'TODONOTE', + 'TODODIESEBEMOL', + 'TODOMDIMMAJSUS', + 'TODOCHIFFRE', + 'TODOSLASH', 'NEWLINE', 'COLON', 'WORD', @@ -39,7 +43,11 @@ class ChordProLexer: t_SPACE = r'[ \t]+' - t_chord_CHORD = r'[A-G7#m]+' + t_chord_TODONOTE = r'[A-G]' + t_chord_TODODIESEBEMOL = r'[#b]' + t_chord_TODOMDIMMAJSUS = r'(maj|dim|m|sus)' + t_chord_TODOCHIFFRE = r'[2-9]' + t_chord_TODOSLASH = r'/' t_directive_SPACE = r'[ \t]+' t_directive_KEYWORD = r'[a-zA-Z_]+' diff --git a/patacrep/songs/chordpro/syntax.py b/patacrep/songs/chordpro/syntax.py index fdcf9b72..d7711564 100644 --- a/patacrep/songs/chordpro/syntax.py +++ b/patacrep/songs/chordpro/syntax.py @@ -11,6 +11,7 @@ LOGGER = logging.getLogger() class ChordproParser(Parser): """ChordPro parser class""" + # pylint: disable=too-many-public-methods start = "song" @@ -23,7 +24,6 @@ class ChordproParser(Parser): """song : block song | empty """ - #if isinstance(symbols[1], str): if len(symbols) == 2: symbols[0] = ast.Song(self.filename) else: @@ -108,8 +108,48 @@ class ChordproParser(Parser): @staticmethod def p_chord(symbols): - """chord : CHORD""" - symbols[0] = ast.Chord(symbols[1]) + """chord : TODONOTE chordtododiesebemol chordtodomdimmajsus chordtodochiffre chordtodoautre""" + symbols[0] = ast.Chord( + symbols[1], + symbols[2], + symbols[3], + symbols[4], + symbols[5], + ) + + @staticmethod + def p_chordtododiesebemol(symbols): + """chordtododiesebemol : TODODIESEBEMOL + | empty + """ + symbols[0] = symbols[1] + + @staticmethod + def p_chordtodomdimmajsus(symbols): + """chordtodomdimmajsus : TODOMDIMMAJSUS + | empty + """ + symbols[0] = symbols[1] + + @staticmethod + def p_chordtodochiffre(symbols): + """chordtodochiffre : TODOCHIFFRE + | empty + """ + if symbols[1] is None: + symbols[0] = symbols[1] + else: + symbols[0] = int(symbols[1]) + + @staticmethod + def p_chordtodoautre(symbols): + """chordtodoautre : TODOSLASH TODONOTE chordtododiesebemol + | empty + """ + if len(symbols) == 2: + symbols[0] = None + else: + symbols[0] = (symbols[2], symbols[3]) @staticmethod def p_chorus(symbols): diff --git a/patacrep/songs/chordpro/test/chords.sgc b/patacrep/songs/chordpro/test/chords.sgc new file mode 100644 index 00000000..1eb5b2da --- /dev/null +++ b/patacrep/songs/chordpro/test/chords.sgc @@ -0,0 +1,12 @@ +[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 diff --git a/patacrep/songs/chordpro/test/chords.txt b/patacrep/songs/chordpro/test/chords.txt new file mode 100644 index 00000000..ad96f2c8 --- /dev/null +++ b/patacrep/songs/chordpro/test/chords.txt @@ -0,0 +1,15 @@ +======== +{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 +{end_of_verse} From 87532f784e75e274a7700076893155f6caba65c0 Mon Sep 17 00:00:00 2001 From: Louis Date: Sun, 23 Aug 2015 23:19:12 +0200 Subject: [PATCH 03/32] Replaced temporary variable names with correct ones --- patacrep/songs/__init__.py | 2 +- patacrep/songs/chordpro/ast.py | 34 +++++++++---------- .../chordpro/data/latex/content_chord.tex | 18 +++++----- patacrep/songs/chordpro/lexer.py | 20 +++++------ patacrep/songs/chordpro/syntax.py | 26 +++++++------- 5 files changed, 50 insertions(+), 50 deletions(-) diff --git a/patacrep/songs/__init__.py b/patacrep/songs/__init__.py index 2afbb8b5..59a85f7a 100644 --- a/patacrep/songs/__init__.py +++ b/patacrep/songs/__init__.py @@ -81,7 +81,7 @@ class Song(Content): # 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 = [ diff --git a/patacrep/songs/chordpro/ast.py b/patacrep/songs/chordpro/ast.py index 033103a7..48345672 100644 --- a/patacrep/songs/chordpro/ast.py +++ b/patacrep/songs/chordpro/ast.py @@ -122,27 +122,27 @@ class Chord(LineElement): _template = "chord" - def __init__(self, todo_note, todo_diesebemol, todo_mdimmajsus, todo_chiffre, todo_chordbis): + def __init__(self, key, alteration, modifier, add_note, bass): super().__init__() - self.todo_note = todo_note - self.todo_diesebemol = todo_diesebemol - self.todo_mdimmajsus = todo_mdimmajsus - self.todo_chiffre = todo_chiffre - self.todo_chordbis = todo_chordbis + self.key = key + self.alteration = alteration + self.modifier = modifier + self.add_note = add_note + self.bass = bass def __str__(self): text = "" - text += self.todo_note - if self.todo_diesebemol is not None: - text += self.todo_diesebemol - if self.todo_mdimmajsus is not None: - text += self.todo_mdimmajsus - if self.todo_chiffre is not None: - text += str(self.todo_chiffre) - if self.todo_chordbis is not None: - text += "/" + self.todo_chordbis[0] - if self.todo_chordbis[1] is not None: - text += self.todo_chordbis[1] + text += self.key + if self.alteration is not None: + text += self.alteration + if self.modifier is not None: + text += self.modifier + if self.add_note is not None: + text += str(self.add_note) + if self.bass is not None: + text += "/" + self.bass[0] + if self.bass[1] is not None: + text += self.bass[1] return "[{}]".format(text) class Verse(AST): diff --git a/patacrep/songs/chordpro/data/latex/content_chord.tex b/patacrep/songs/chordpro/data/latex/content_chord.tex index f6639511..5b5aaa1b 100644 --- a/patacrep/songs/chordpro/data/latex/content_chord.tex +++ b/patacrep/songs/chordpro/data/latex/content_chord.tex @@ -1,13 +1,13 @@ \[ - ((- content.todo_note -)) - (* if content.todo_diesebemol == '#' *)#(* endif -*) - (* if content.todo_diesebemol == 'b' *)&(* endif -*) - (* if content.todo_mdimmajsus *)((content.todo_mdimmajsus))(* endif -*) - (* if content.todo_chiffre *)((content.todo_chiffre))(* endif -*) - (* if content.todo_chordbis -*) + ((- content.key -)) + (* if content.alteration == '#' *)#(* endif -*) + (* if content.alteration == 'b' *)&(* endif -*) + (* if content.modifier *)((content.modifier))(* endif -*) + (* if content.add_note *)((content.add_note))(* endif -*) + (* if content.bass -*) / - ((- content.todo_chordbis[0] -)) - (* if content.todo_chordbis[1] == '#' *)#(* endif -*) - (* if content.todo_chordbis[1] == 'b' *)&(* endif -*) + ((- content.bass[0] -)) + (* if content.bass[1] == '#' *)#(* endif -*) + (* if content.bass[1] == 'b' *)&(* endif -*) (* endif -*) ] diff --git a/patacrep/songs/chordpro/lexer.py b/patacrep/songs/chordpro/lexer.py index de7422b4..bec084b6 100644 --- a/patacrep/songs/chordpro/lexer.py +++ b/patacrep/songs/chordpro/lexer.py @@ -9,11 +9,11 @@ LOGGER = logging.getLogger() tokens = ( 'LBRACE', 'RBRACE', - 'TODONOTE', - 'TODODIESEBEMOL', - 'TODOMDIMMAJSUS', - 'TODOCHIFFRE', - 'TODOSLASH', + 'KEY', + 'ALTERATION', + 'MODIFIER', + 'ADDNOTE', + 'SLASH', 'NEWLINE', 'COLON', 'WORD', @@ -43,11 +43,11 @@ class ChordProLexer: t_SPACE = r'[ \t]+' - t_chord_TODONOTE = r'[A-G]' - t_chord_TODODIESEBEMOL = r'[#b]' - t_chord_TODOMDIMMAJSUS = r'(maj|dim|m|sus)' - t_chord_TODOCHIFFRE = r'[2-9]' - t_chord_TODOSLASH = r'/' + t_chord_KEY = r'[A-G]' + t_chord_ALTERATION = r'[#b]' + t_chord_MODIFIER = r'(maj|dim|m|sus)' + t_chord_ADDNOTE = r'[2-9]' + t_chord_SLASH = r'/' t_directive_SPACE = r'[ \t]+' t_directive_KEYWORD = r'[a-zA-Z_]+' diff --git a/patacrep/songs/chordpro/syntax.py b/patacrep/songs/chordpro/syntax.py index d7711564..d801cb1d 100644 --- a/patacrep/songs/chordpro/syntax.py +++ b/patacrep/songs/chordpro/syntax.py @@ -108,7 +108,7 @@ class ChordproParser(Parser): @staticmethod def p_chord(symbols): - """chord : TODONOTE chordtododiesebemol chordtodomdimmajsus chordtodochiffre chordtodoautre""" + """chord : KEY chordalteration chordmodifier chordaddnote chordbass""" symbols[0] = ast.Chord( symbols[1], symbols[2], @@ -118,23 +118,23 @@ class ChordproParser(Parser): ) @staticmethod - def p_chordtododiesebemol(symbols): - """chordtododiesebemol : TODODIESEBEMOL - | empty + def p_chordalteration(symbols): + """chordalteration : ALTERATION + | empty """ symbols[0] = symbols[1] @staticmethod - def p_chordtodomdimmajsus(symbols): - """chordtodomdimmajsus : TODOMDIMMAJSUS - | empty + def p_chordmodifier(symbols): + """chordmodifier : MODIFIER + | empty """ symbols[0] = symbols[1] @staticmethod - def p_chordtodochiffre(symbols): - """chordtodochiffre : TODOCHIFFRE - | empty + def p_chordaddnote(symbols): + """chordaddnote : ADDNOTE + | empty """ if symbols[1] is None: symbols[0] = symbols[1] @@ -142,9 +142,9 @@ class ChordproParser(Parser): symbols[0] = int(symbols[1]) @staticmethod - def p_chordtodoautre(symbols): - """chordtodoautre : TODOSLASH TODONOTE chordtododiesebemol - | empty + def p_chordbass(symbols): + """chordbass : SLASH KEY chordalteration + | empty """ if len(symbols) == 2: symbols[0] = None From fe7c6aecaab70096d753d9f457be3065466b03a4 Mon Sep 17 00:00:00 2001 From: Louis Date: Sun, 23 Aug 2015 23:20:44 +0200 Subject: [PATCH 04/32] [pylint] Removed pylint error --- patacrep/songs/chordpro/ast.py | 1 + 1 file changed, 1 insertion(+) diff --git a/patacrep/songs/chordpro/ast.py b/patacrep/songs/chordpro/ast.py index 48345672..e9192517 100644 --- a/patacrep/songs/chordpro/ast.py +++ b/patacrep/songs/chordpro/ast.py @@ -123,6 +123,7 @@ class Chord(LineElement): _template = "chord" def __init__(self, key, alteration, modifier, add_note, bass): + # pylint: disable=too-many-arguments super().__init__() self.key = key self.alteration = alteration From 43448ab788306136205eca3a66ad9bb64faa4362 Mon Sep 17 00:00:00 2001 From: Louis Date: Mon, 24 Aug 2015 23:16:11 +0200 Subject: [PATCH 05/32] Chords are now parsed with a regular expression: ply is overkill here * Preparing for parsing of `{define: FOO}` statements * Brackets can now contain several space-separated chords (as in `[A/A B#]`). --- patacrep/data/examples/songs/chords.sgc | 1 + patacrep/songs/chordpro/ast.py | 46 ++++++++---- .../chordpro/data/latex/content_chord.tex | 25 ++++--- patacrep/songs/chordpro/lexer.py | 12 +--- patacrep/songs/chordpro/syntax.py | 71 ++++++++----------- patacrep/songs/chordpro/test/chords.sgc | 1 + patacrep/songs/chordpro/test/chords.txt | 1 + 7 files changed, 80 insertions(+), 77 deletions(-) diff --git a/patacrep/data/examples/songs/chords.sgc b/patacrep/data/examples/songs/chords.sgc index a1076a44..96390d2b 100644 --- a/patacrep/data/examples/songs/chords.sgc +++ b/patacrep/data/examples/songs/chords.sgc @@ -15,3 +15,4 @@ [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/songs/chordpro/ast.py b/patacrep/songs/chordpro/ast.py index e9192517..4e20bd97 100644 --- a/patacrep/songs/chordpro/ast.py +++ b/patacrep/songs/chordpro/ast.py @@ -117,19 +117,37 @@ class Space(LineElement): def __str__(self): return " " -class Chord(LineElement): - """A chord.""" - +class ChordList(LineElement): + """A list of chords.""" _template = "chord" - def __init__(self, key, alteration, modifier, add_note, bass): + def __init__(self, *chords): + self.chords = chords + + def __str__(self): + return "[{}]".format(" ".join( + [str(chord) for chord in self.chords] + )) + +class Chord: + """A chord.""" + + def __init__( + self, + key, + alteration=None, + modifier=None, + addnote=None, + basskey=None, + bassalteration=None, + ): # pylint: disable=too-many-arguments - super().__init__() self.key = key self.alteration = alteration self.modifier = modifier - self.add_note = add_note - self.bass = bass + self.addnote = addnote + self.basskey = basskey + self.bassalteration = bassalteration def __str__(self): text = "" @@ -138,13 +156,13 @@ class Chord(LineElement): text += self.alteration if self.modifier is not None: text += self.modifier - if self.add_note is not None: - text += str(self.add_note) - if self.bass is not None: - text += "/" + self.bass[0] - if self.bass[1] is not None: - text += self.bass[1] - return "[{}]".format(text) + if self.addnote is not None: + text += str(self.addnote) + if self.basskey is not None: + text += "/" + self.basskey + if self.bassalteration is not None: + text += self.bassalteration + return text class Verse(AST): """A verse (or bridge, or chorus)""" diff --git a/patacrep/songs/chordpro/data/latex/content_chord.tex b/patacrep/songs/chordpro/data/latex/content_chord.tex index 5b5aaa1b..c3f62f22 100644 --- a/patacrep/songs/chordpro/data/latex/content_chord.tex +++ b/patacrep/songs/chordpro/data/latex/content_chord.tex @@ -1,13 +1,16 @@ \[ - ((- content.key -)) - (* if content.alteration == '#' *)#(* endif -*) - (* if content.alteration == 'b' *)&(* endif -*) - (* if content.modifier *)((content.modifier))(* endif -*) - (* if content.add_note *)((content.add_note))(* endif -*) - (* if content.bass -*) - / - ((- content.bass[0] -)) - (* if content.bass[1] == '#' *)#(* endif -*) - (* if content.bass[1] == 'b' *)&(* endif -*) - (* endif -*) + (*- for chord in content.chords -*) + (* if not loop.first *) (* endif *) + ((- chord.key -)) + (* if chord.alteration == '#' *)#(* endif -*) + (* if chord.alteration == 'b' *)&(* endif -*) + (* if chord.modifier *)((chord.modifier))(* endif -*) + (* if chord.add_note *)((chord.add_note))(* endif -*) + (* if chord.basskey -*) + / + ((- chord.basskey -)) + (* if chord.bassalteration == '#' *)#(* endif -*) + (* if chord.bassalteration == 'b' *)&(* endif -*) + (* endif -*) + (* endfor -*) ] diff --git a/patacrep/songs/chordpro/lexer.py b/patacrep/songs/chordpro/lexer.py index bec084b6..af8be763 100644 --- a/patacrep/songs/chordpro/lexer.py +++ b/patacrep/songs/chordpro/lexer.py @@ -9,15 +9,11 @@ LOGGER = logging.getLogger() tokens = ( 'LBRACE', 'RBRACE', - 'KEY', - 'ALTERATION', - 'MODIFIER', - 'ADDNOTE', - 'SLASH', 'NEWLINE', 'COLON', 'WORD', 'SPACE', + 'CHORD', 'TEXT', 'KEYWORD', 'SOC', @@ -43,11 +39,7 @@ class ChordProLexer: t_SPACE = r'[ \t]+' - t_chord_KEY = r'[A-G]' - t_chord_ALTERATION = r'[#b]' - t_chord_MODIFIER = r'(maj|dim|m|sus)' - t_chord_ADDNOTE = r'[2-9]' - t_chord_SLASH = r'/' + t_chord_CHORD = r'[A-G#bmajdisus2-9/ ]+' t_directive_SPACE = r'[ \t]+' t_directive_KEYWORD = r'[a-zA-Z_]+' diff --git a/patacrep/songs/chordpro/syntax.py b/patacrep/songs/chordpro/syntax.py index d801cb1d..de6b5a28 100644 --- a/patacrep/songs/chordpro/syntax.py +++ b/patacrep/songs/chordpro/syntax.py @@ -2,6 +2,7 @@ import logging import ply.yacc as yacc +import re from patacrep.songs.syntax import Parser from patacrep.songs.chordpro import ast @@ -9,6 +10,32 @@ from patacrep.songs.chordpro.lexer import tokens, ChordProLexer LOGGER = logging.getLogger() +CHORD_RE = re.compile( + r""" + (?P[A-G]) + (?P[b#])? + (?P(maj|sus|dim|m))? + (?P[2-9])? + ( + / + (?P[A-G]) + (?P[b#])? + )? + """, + re.VERBOSE + ) + +def _parse_chords(string): + """Parse a list of chords. + + Iterate over :class:`ast.Chord` objects. + """ + for chord in string.split(): + match = CHORD_RE.match(chord) + if match is None: + TODO + yield ast.Chord(**match.groupdict()) + class ChordproParser(Parser): """ChordPro parser class""" # pylint: disable=too-many-public-methods @@ -108,48 +135,8 @@ class ChordproParser(Parser): @staticmethod def p_chord(symbols): - """chord : KEY chordalteration chordmodifier chordaddnote chordbass""" - symbols[0] = ast.Chord( - symbols[1], - symbols[2], - symbols[3], - symbols[4], - symbols[5], - ) - - @staticmethod - def p_chordalteration(symbols): - """chordalteration : ALTERATION - | empty - """ - symbols[0] = symbols[1] - - @staticmethod - def p_chordmodifier(symbols): - """chordmodifier : MODIFIER - | empty - """ - symbols[0] = symbols[1] - - @staticmethod - def p_chordaddnote(symbols): - """chordaddnote : ADDNOTE - | empty - """ - if symbols[1] is None: - symbols[0] = symbols[1] - else: - symbols[0] = int(symbols[1]) - - @staticmethod - def p_chordbass(symbols): - """chordbass : SLASH KEY chordalteration - | empty - """ - if len(symbols) == 2: - symbols[0] = None - else: - symbols[0] = (symbols[2], symbols[3]) + """chord : CHORD""" + symbols[0] = ast.ChordList(*_parse_chords(symbols[1])) @staticmethod def p_chorus(symbols): diff --git a/patacrep/songs/chordpro/test/chords.sgc b/patacrep/songs/chordpro/test/chords.sgc index 1eb5b2da..84397df2 100644 --- a/patacrep/songs/chordpro/test/chords.sgc +++ b/patacrep/songs/chordpro/test/chords.sgc @@ -10,3 +10,4 @@ [A/A]Deux notes [F/Fb]Deux notes, bémol [B/C#]Deux notes, dièse +[Ab B#/A]Plusieurs notes à la suite diff --git a/patacrep/songs/chordpro/test/chords.txt b/patacrep/songs/chordpro/test/chords.txt index ad96f2c8..462bb182 100644 --- a/patacrep/songs/chordpro/test/chords.txt +++ b/patacrep/songs/chordpro/test/chords.txt @@ -12,4 +12,5 @@ [A/A]Deux notes [F/Fb]Deux notes, bémol [B/C#]Deux notes, dièse + [Ab B#/A]Plusieurs notes à la suite {end_of_verse} From 47e4f960994adfdbb01bea7e3831c992c95ddec2 Mon Sep 17 00:00:00 2001 From: Louis Date: Tue, 25 Aug 2015 14:04:45 +0200 Subject: [PATCH 06/32] [chordpro] Parsing of {define: FOO} works (some TODOs are left for error handling) --- patacrep/data/examples/example-all.sb | 2 +- patacrep/data/examples/songs/chords.sgc | 5 ++ patacrep/songs/chordpro/ast.py | 50 +++++++++++++++- .../chordpro/data/latex/content_chord.tex | 27 ++++----- .../chordpro/data/latex/content_chordlist.tex | 6 ++ .../chordpro/data/latex/content_define.tex | 24 ++++++++ patacrep/songs/chordpro/syntax.py | 59 +++++++++++++++++++ patacrep/songs/chordpro/test/customchords.sgc | 2 + patacrep/songs/chordpro/test/customchords.txt | 3 + 9 files changed, 159 insertions(+), 19 deletions(-) create mode 100644 patacrep/songs/chordpro/data/latex/content_chordlist.tex create mode 100644 patacrep/songs/chordpro/data/latex/content_define.tex create mode 100644 patacrep/songs/chordpro/test/customchords.sgc create mode 100644 patacrep/songs/chordpro/test/customchords.txt diff --git a/patacrep/data/examples/example-all.sb b/patacrep/data/examples/example-all.sb index ca35b622..a9599a26 100644 --- a/patacrep/data/examples/example-all.sb +++ b/patacrep/data/examples/example-all.sb @@ -1,6 +1,6 @@ { "bookoptions" : [ - "importantdiagramonly", + "diagram", "repeatchords", "lilypond", "pictures" diff --git a/patacrep/data/examples/songs/chords.sgc b/patacrep/data/examples/songs/chords.sgc index 96390d2b..8779a140 100644 --- a/patacrep/data/examples/songs/chords.sgc +++ b/patacrep/data/examples/songs/chords.sgc @@ -3,6 +3,11 @@ {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 diff --git a/patacrep/songs/chordpro/ast.py b/patacrep/songs/chordpro/ast.py index 4e20bd97..5db13afc 100644 --- a/patacrep/songs/chordpro/ast.py +++ b/patacrep/songs/chordpro/ast.py @@ -119,7 +119,7 @@ class Space(LineElement): class ChordList(LineElement): """A list of chords.""" - _template = "chord" + _template = "chordlist" def __init__(self, *chords): self.chords = chords @@ -129,9 +129,11 @@ class ChordList(LineElement): [str(chord) for chord in self.chords] )) -class Chord: +class Chord(AST): """A chord.""" + _template = "chord" + def __init__( self, key, @@ -164,6 +166,50 @@ class Chord: 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" diff --git a/patacrep/songs/chordpro/data/latex/content_chord.tex b/patacrep/songs/chordpro/data/latex/content_chord.tex index c3f62f22..29a1cc30 100644 --- a/patacrep/songs/chordpro/data/latex/content_chord.tex +++ b/patacrep/songs/chordpro/data/latex/content_chord.tex @@ -1,16 +1,11 @@ -\[ - (*- for chord in content.chords -*) - (* if not loop.first *) (* endif *) - ((- chord.key -)) - (* if chord.alteration == '#' *)#(* endif -*) - (* if chord.alteration == 'b' *)&(* endif -*) - (* if chord.modifier *)((chord.modifier))(* endif -*) - (* if chord.add_note *)((chord.add_note))(* endif -*) - (* if chord.basskey -*) - / - ((- chord.basskey -)) - (* if chord.bassalteration == '#' *)#(* endif -*) - (* if chord.bassalteration == 'b' *)&(* endif -*) - (* endif -*) - (* endfor -*) -] +((- content.key -)) +(* if content.alteration == '#' *)#(* endif -*) +(* if content.alteration == 'b' *)&(* endif -*) +(* if content.modifier *)((content.modifier))(* endif -*) +(* if content.addnote *)((content.addnote))(* endif -*) +(* if content.basskey -*) + / + ((- content.basskey -)) + (* if content.bassalteration == '#' *)#(* endif -*) + (* if content.bassalteration == 'b' *)&(* endif -*) +(* endif -*) diff --git a/patacrep/songs/chordpro/data/latex/content_chordlist.tex b/patacrep/songs/chordpro/data/latex/content_chordlist.tex new file mode 100644 index 00000000..d5ad7c3c --- /dev/null +++ b/patacrep/songs/chordpro/data/latex/content_chordlist.tex @@ -0,0 +1,6 @@ +\[ + (*- for chord in content.chords -*) + (* if not loop.first *) (* endif -*) + (( render(chord) -)) + (* endfor -*) +] diff --git a/patacrep/songs/chordpro/data/latex/content_define.tex b/patacrep/songs/chordpro/data/latex/content_define.tex new file mode 100644 index 00000000..ca899ff3 --- /dev/null +++ b/patacrep/songs/chordpro/data/latex/content_define.tex @@ -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/syntax.py b/patacrep/songs/chordpro/syntax.py index de6b5a28..91a0cb41 100644 --- a/patacrep/songs/chordpro/syntax.py +++ b/patacrep/songs/chordpro/syntax.py @@ -36,6 +36,50 @@ def _parse_chords(string): TODO yield ast.Chord(**match.groupdict()) +def _parse_define(key, basefret, frets, fingers): + """Parse a `{define: KEY base-fret BASE frets FRETS fingers FINGERS}` directive + + Return a :class:`ast.Define` object. + """ + # pylint: disable=too-many-branches + key = list(_parse_chords(key)) + if len(key) != 1: + TODO + else: + processed_key = key[0] + + if basefret is None: + processed_basefret = None + else: + processed_basefret = int(basefret) + + if frets is None: + processed_frets = None + else: + processed_frets = [] + for fret in frets.split(): + if fret == "x": + processed_frets.append(None) + else: + processed_frets.append(int(fret)) + + if fingers is None: + processed_fingers = None + else: + processed_fingers = [] + for finger in fingers.split(): + if finger == '-': + processed_fingers.append(None) + else: + processed_fingers.append(int(finger)) + + return ast.Define( + key=processed_key, + basefret=processed_basefret, + frets=processed_frets, + fingers=processed_fingers, + ) + class ChordproParser(Parser): """ChordPro parser class""" # pylint: disable=too-many-public-methods @@ -91,6 +135,21 @@ class ChordproParser(Parser): else: symbols[4].keyword = symbols[3] symbols[0] = symbols[4] + if symbols[0].keyword == 'define': + match = re.compile( + r""" + (?P[^\ ]*)\ * + (base-fret\ *(?P[2-9]))?\ * + frets\ *(?P((\d+|x)\ *)+)\ * + (fingers\ *(?P(([0-4-])\ *)*))? + """, + re.VERBOSE + ).match(symbols[0].argument) + + if match is None: + TODO + + symbols[0] = _parse_define(**match.groupdict()) @staticmethod def p_directive_next(symbols): diff --git a/patacrep/songs/chordpro/test/customchords.sgc b/patacrep/songs/chordpro/test/customchords.sgc new file mode 100644 index 00000000..b7192c87 --- /dev/null +++ b/patacrep/songs/chordpro/test/customchords.sgc @@ -0,0 +1,2 @@ +{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/customchords.txt b/patacrep/songs/chordpro/test/customchords.txt new file mode 100644 index 00000000..c8d99d13 --- /dev/null +++ b/patacrep/songs/chordpro/test/customchords.txt @@ -0,0 +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 - -} From ea1b382f5f4b52caef43dca0775c25b8bd7f5641 Mon Sep 17 00:00:00 2001 From: Louis Date: Tue, 25 Aug 2015 19:28:34 +0200 Subject: [PATCH 07/32] Generated LaTeX file contains nicer spaces No weird indentation, no trailing whitespaces, no long long paragraph breaks (one line or two are sufficient), etc. --- patacrep/data/examples/example-all.sb | 1 + patacrep/data/templates/default.tex | 119 +++++++++--------- patacrep/data/templates/layout.tex | 56 ++++----- patacrep/data/templates/patacrep.tex | 111 ++++++++-------- patacrep/data/templates/songs.tex | 99 ++++++++------- .../songs/chordpro/data/latex/chordpro.tex | 21 ++-- .../chordpro/data/latex/content_line.tex | 4 +- .../chordpro/data/latex/content_verse.tex | 3 +- patacrep/templates.py | 32 ++--- 9 files changed, 229 insertions(+), 217 deletions(-) diff --git a/patacrep/data/examples/example-all.sb b/patacrep/data/examples/example-all.sb index a9599a26..dba08cc0 100644 --- a/patacrep/data/examples/example-all.sb +++ b/patacrep/data/examples/example-all.sb @@ -6,6 +6,7 @@ "pictures" ], "booktype" : "chorded", +"template" : "patacrep.tex", "lang" : "french", "encoding": "utf8", "authwords" : { 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..1ef8ea7a 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(content) )) (* endblock *) diff --git a/patacrep/songs/chordpro/data/latex/chordpro.tex b/patacrep/songs/chordpro/data/latex/chordpro.tex index 1f21adb1..dec5f3f5 100644 --- a/patacrep/songs/chordpro/data/latex/chordpro.tex +++ b/patacrep/songs/chordpro/data/latex/chordpro.tex @@ -1,26 +1,27 @@ + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % ((path)) -(* if language is defined *) -\selectlanguage{((language))} +(* if language is defined -*) + \selectlanguage{((language))} (* endif *) \songcolumns{((metadata.columns))} \beginsong{((titles))}[ by={((authors))}, (* for (key, argument) in beginsong *) - ((key))={((argument))}, + ((key))={((argument))}, (* endfor *) - ] +] - (* if (metadata.cov is defined) or (metadata.vcov is defined) *) - \cover - (* endif *) +(* if (metadata.cov is defined) or (metadata.vcov is defined) *) +\cover +(* endif -*) - (* for item in content *) - (( render(item) )) - (* endfor *) +(* for item in content -*) + (( render(item) )) +(* endfor *) \endsong %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/patacrep/songs/chordpro/data/latex/content_line.tex b/patacrep/songs/chordpro/data/latex/content_line.tex index bdad1100..03ca80b7 100644 --- a/patacrep/songs/chordpro/data/latex/content_line.tex +++ b/patacrep/songs/chordpro/data/latex/content_line.tex @@ -1 +1,3 @@ -(* for item in content.line *)(( render(item) ))(* endfor *) +(* for item in content.line -*) + (( render(item) )) +(*- endfor *) diff --git a/patacrep/songs/chordpro/data/latex/content_verse.tex b/patacrep/songs/chordpro/data/latex/content_verse.tex index dc50f3f0..ac169e98 100644 --- a/patacrep/songs/chordpro/data/latex/content_verse.tex +++ b/patacrep/songs/chordpro/data/latex/content_verse.tex @@ -1,6 +1,5 @@ \begin{(( content.type ))} - (* for line in content.lines *) + (* for line in content.lines -*) (( render(line) )) (* endfor *) \end{(( content.type ))} - diff --git a/patacrep/templates.py b/patacrep/templates.py index 95c06469..69e5f10c 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) From 6afb5fd8e089456a64638308119838e653e4d6e9 Mon Sep 17 00:00:00 2001 From: Louis Date: Wed, 26 Aug 2015 18:20:39 +0200 Subject: [PATCH 08/32] [chordpro] `{define: FOO}` directive are now meta information. Generated AST changed too. --- patacrep/songs/chordpro/__init__.py | 14 +- patacrep/songs/chordpro/ast.py | 288 +++++++++--------- .../data/latex/{chordpro.tex => song.tex} | 12 +- patacrep/songs/chordpro/syntax.py | 22 +- patacrep/songs/chordpro/test/00.txt | 2 +- patacrep/songs/chordpro/test/01.txt | 2 +- patacrep/songs/chordpro/test/02.txt | 2 +- patacrep/songs/chordpro/test/03.txt | 2 +- patacrep/songs/chordpro/test/04.txt | 2 +- patacrep/songs/chordpro/test/05.txt | 2 +- patacrep/songs/chordpro/test/06.txt | 2 +- patacrep/songs/chordpro/test/07.txt | 2 +- patacrep/songs/chordpro/test/08.txt | 2 +- patacrep/songs/chordpro/test/09.txt | 2 +- patacrep/songs/chordpro/test/10.txt | 2 +- patacrep/songs/chordpro/test/11.txt | 2 +- patacrep/songs/chordpro/test/12.txt | 2 +- patacrep/songs/chordpro/test/13.txt | 2 +- patacrep/songs/chordpro/test/21.txt | 2 +- patacrep/songs/chordpro/test/22.txt | 2 +- patacrep/songs/chordpro/test/23.txt | 2 +- patacrep/songs/chordpro/test/24.txt | 2 +- patacrep/songs/chordpro/test/25.txt | 2 +- patacrep/songs/chordpro/test/26.txt | 2 +- patacrep/songs/chordpro/test/27.txt | 2 +- patacrep/songs/chordpro/test/28.txt | 2 +- patacrep/songs/chordpro/test/29.txt | 2 +- patacrep/songs/chordpro/test/chords.txt | 2 +- patacrep/songs/chordpro/test/customchords.txt | 2 +- patacrep/songs/chordpro/test/greensleeves.txt | 6 +- patacrep/songs/chordpro/test/metadata.txt | 8 +- patacrep/songs/chordpro/test/test_parser.py | 4 +- 32 files changed, 209 insertions(+), 195 deletions(-) rename patacrep/songs/chordpro/data/latex/{chordpro.tex => song.tex} (68%) 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)), ) From 48637e60fdc24f5b6e95b101917888ac2a305aec Mon Sep 17 00:00:00 2001 From: Louis Date: Thu, 27 Aug 2015 23:47:34 +0200 Subject: [PATCH 09/32] [chordpro] Better error handling --- patacrep/data/examples/songs/errors.sgc | 13 ++ patacrep/songs/chordpro/ast.py | 10 +- patacrep/songs/chordpro/lexer.py | 34 ++-- patacrep/songs/chordpro/syntax.py | 154 ++++++++++-------- .../songs/chordpro/test/invalid_chord.sgc | 3 + .../songs/chordpro/test/invalid_chord.txt | 6 + .../chordpro/test/invalid_customchord.sgc | 5 + .../chordpro/test/invalid_customchord.txt | 0 patacrep/songs/syntax.py | 29 +++- 9 files changed, 165 insertions(+), 89 deletions(-) create mode 100644 patacrep/data/examples/songs/errors.sgc create mode 100644 patacrep/songs/chordpro/test/invalid_chord.sgc create mode 100644 patacrep/songs/chordpro/test/invalid_chord.txt create mode 100644 patacrep/songs/chordpro/test/invalid_customchord.sgc create mode 100644 patacrep/songs/chordpro/test/invalid_customchord.txt 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/songs/chordpro/ast.py b/patacrep/songs/chordpro/ast.py index c74a628b..049a3b2f 100644 --- a/patacrep/songs/chordpro/ast.py +++ b/patacrep/songs/chordpro/ast.py @@ -86,6 +86,12 @@ class AST: """Return the chordpro string corresponding to this object.""" raise NotImplementedError() +class Error(AST): + """Parsing error. To be ignored.""" + + def chordpro(self): + return "" + class Line(AST): """A line is a sequence of (possibly truncated) words, spaces and chords.""" @@ -266,7 +272,9 @@ class Song(AST): if data.keyword in self.PROCESS_DIRECTIVE: data = getattr(self, self.PROCESS_DIRECTIVE[data.keyword])(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()) diff --git a/patacrep/songs/chordpro/lexer.py b/patacrep/songs/chordpro/lexer.py index af8be763..813c42b0 100644 --- a/patacrep/songs/chordpro/lexer.py +++ b/patacrep/songs/chordpro/lexer.py @@ -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 ea50e267..1e1420bc 100644 --- a/patacrep/songs/chordpro/syntax.py +++ b/patacrep/songs/chordpro/syntax.py @@ -1,6 +1,5 @@ """ChordPro parser""" -import logging import ply.yacc as yacc import re @@ -8,10 +7,9 @@ from patacrep.songs.syntax import Parser from patacrep.songs.chordpro import ast from patacrep.songs.chordpro.lexer import tokens, ChordProLexer -LOGGER = logging.getLogger() - CHORD_RE = re.compile( r""" + ^ (?P[A-G]) (?P[b#])? (?P(maj|sus|dim|m))? @@ -21,65 +19,11 @@ CHORD_RE = re.compile( (?P[A-G]) (?P[b#])? )? + $ """, re.VERBOSE ) -def _parse_chords(string): - """Parse a list of chords. - - Iterate over :class:`ast.Chord` objects. - """ - for chord in string.split(): - match = CHORD_RE.match(chord) - if match is None: - TODO - yield ast.Chord(**match.groupdict()) - -def _parse_define(key, basefret, frets, fingers): - """Parse a `{define: KEY base-fret BASE frets FRETS fingers FINGERS}` directive - - Return a :class:`ast.Define` object. - """ - # pylint: disable=too-many-branches - key = list(_parse_chords(key)) - if len(key) != 1: - TODO - else: - processed_key = key[0] - - if basefret is None: - processed_basefret = None - else: - processed_basefret = int(basefret) - - if frets is None: - processed_frets = None - else: - processed_frets = [] - for fret in frets.split(): - if fret == "x": - processed_frets.append(None) - else: - processed_frets.append(int(fret)) - - if fingers is None: - processed_fingers = None - else: - processed_fingers = [] - for finger in fingers.split(): - if finger == '-': - processed_fingers.append(None) - else: - processed_fingers.append(int(finger)) - - return ast.Define( - key=processed_key, - basefret=processed_basefret, - frets=processed_frets, - fingers=processed_fingers, - ) - class ChordproParser(Parser): """ChordPro parser class""" # pylint: disable=too-many-public-methods @@ -124,8 +68,51 @@ class ChordproParser(Parser): """ symbols[0] = None - @staticmethod - def p_directive(symbols): + def _parse_define(self, groups, *, symbols): + """Parse a `{define: KEY base-fret BASE frets FRETS fingers FINGERS}` directive + + Return a :class:`ast.Define` object. + """ + # pylint: disable=too-many-branches + key = list(self._parse_chords(groups['key'], symbols=symbols)) + if len(key) != 1: + return None + else: + key = key[0] + + 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 == "x": + 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 """ @@ -139,18 +126,38 @@ class ChordproParser(Parser): if keyword == "define": match = re.compile( r""" + ^ (?P[^\ ]*)\ * (base-fret\ *(?P[2-9]))?\ * frets\ *(?P((\d+|x)\ *)+)\ * (fingers\ *(?P(([0-4-])\ *)*))? + $ """, re.VERBOSE ).match(argument) if match is None: - TODO + 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(), symbols=symbols) + if symbols[0] is None: + self.error( + line=symbols.lexer.lineno, + message="Invalid chord definition '{}'.".format(argument), + ) + symbols[0] = ast.Error() - symbols[0] = _parse_define(**match.groupdict()) else: symbols[0] = ast.Directive(keyword, argument) @@ -158,12 +165,15 @@ class ChordproParser(Parser): def p_directive_next(symbols): """directive_next : SPACE COLON TEXT | COLON TEXT + | COLON | empty """ if len(symbols) == 3: symbols[0] = symbols[2].strip() elif len(symbols) == 4: symbols[0] = symbols[3].strip() + elif len(symbols) == 2 and symbols[1] == ":": + symbols[0] = "" else: symbols[0] = None @@ -196,10 +206,24 @@ class ChordproParser(Parser): """space : SPACE""" symbols[0] = ast.Space() - @staticmethod - def p_chord(symbols): + def _parse_chords(self, string, *, symbols): + """Parse a list of chords. + + Iterate over :class:`ast.Chord` objects. + """ + for chord in string.split(): + match = CHORD_RE.match(chord) + if match is None: + self.error( + line=symbols.lexer.lineno, + message="Invalid chord '{}'.".format(chord), + ) + continue + yield ast.Chord(**match.groupdict()) + + def p_chord(self, symbols): """chord : CHORD""" - symbols[0] = ast.ChordList(*_parse_chords(symbols[1])) + symbols[0] = ast.ChordList(*self._parse_chords(symbols[1], symbols=symbols)) @staticmethod def p_chorus(symbols): diff --git a/patacrep/songs/chordpro/test/invalid_chord.sgc b/patacrep/songs/chordpro/test/invalid_chord.sgc new file mode 100644 index 00000000..872697b3 --- /dev/null +++ b/patacrep/songs/chordpro/test/invalid_chord.sgc @@ -0,0 +1,3 @@ +This is [H] invalid. +This [A+]too. +And [Amm]as well. diff --git a/patacrep/songs/chordpro/test/invalid_chord.txt b/patacrep/songs/chordpro/test/invalid_chord.txt new file mode 100644 index 00000000..e72a02d0 --- /dev/null +++ b/patacrep/songs/chordpro/test/invalid_chord.txt @@ -0,0 +1,6 @@ + +{start_of_verse} + This is invalid. + This [A]too. + And []as well. +{end_of_verse} diff --git a/patacrep/songs/chordpro/test/invalid_customchord.sgc b/patacrep/songs/chordpro/test/invalid_customchord.sgc new file mode 100644 index 00000000..9754318f --- /dev/null +++ b/patacrep/songs/chordpro/test/invalid_customchord.sgc @@ -0,0 +1,5 @@ +{define : } +{define: H base-fret 7 frets 0 1 3 3 x x} +{define: E4 base-fret H frets 0 1 3 3 x x} +{define: E4 base-fret 7 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.txt b/patacrep/songs/chordpro/test/invalid_customchord.txt new file mode 100644 index 00000000..e69de29b diff --git a/patacrep/songs/syntax.py b/patacrep/songs/syntax.py index aa2075a2..00768019 100644 --- a/patacrep/songs/syntax.py +++ b/patacrep/songs/syntax.py @@ -20,14 +20,27 @@ class Parser: column = (token.lexpos - last_cr) + 1 return column + @staticmethod + def error(*, line, column=None, message=""): + """Display an error message""" + text = "Line {}".format(line) + if column is not None: + text += ", column {}".format(column) + if 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( + line=token.lineno, + message="Unexpected end of file.", + ) + else: + self.error( + line=token.lineno, + column=self.__find_column(token), ) - From 8f910441080f4255dc12821d9e7352f7b85fb6c6 Mon Sep 17 00:00:00 2001 From: Louis Date: Fri, 28 Aug 2015 20:09:03 +0200 Subject: [PATCH 10/32] [chordpro] Template job is done by the template --- patacrep/songs/chordpro/__init__.py | 5 ++--- patacrep/songs/chordpro/data/latex/song.tex | 18 ++++++++++++++++-- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/patacrep/songs/chordpro/__init__.py b/patacrep/songs/chordpro/__init__.py index d594a0b3..d5efd135 100644 --- a/patacrep/songs/chordpro/__init__.py +++ b/patacrep/songs/chordpro/__init__.py @@ -34,10 +34,9 @@ class ChordproSong(Song): '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]), + "titles": self.titles, + "authors": self.authors, "metadata": self.data, "render": self.render_tex, } diff --git a/patacrep/songs/chordpro/data/latex/song.tex b/patacrep/songs/chordpro/data/latex/song.tex index 8da583af..a4f4d9ca 100644 --- a/patacrep/songs/chordpro/data/latex/song.tex +++ b/patacrep/songs/chordpro/data/latex/song.tex @@ -8,8 +8,22 @@ (* endif *) \songcolumns{(( metadata.columns ))} -\beginsong{((titles))}[ - by={((authors))}, +\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', 'cov', 'vcov', 'tag'] *) (* if key in metadata *) (( key ))={(( metadata[key] ))}, From eba5d404d13cebf367b75626e398747bbd497f0f Mon Sep 17 00:00:00 2001 From: Louis Date: Fri, 28 Aug 2015 22:43:19 +0200 Subject: [PATCH 11/32] [chordpro] More generic song renderer --- patacrep/build.py | 2 +- patacrep/content/__init__.py | 2 +- patacrep/content/song.py | 2 +- patacrep/data/templates/songs.tex | 2 +- patacrep/songs/__init__.py | 15 +++--- patacrep/songs/chordpro/__init__.py | 28 ++++++----- patacrep/songs/chordpro/ast.py | 4 +- .../{content_chord.tex => content_chord} | 0 ...ontent_chordlist.tex => content_chordlist} | 0 .../{content_comment.tex => content_comment} | 0 .../{content_define.tex => content_define} | 0 .../{content_error.tex => content_error} | 0 ...tar_comment.tex => content_guitar_comment} | 0 .../{content_image.tex => content_image} | 0 .../latex/{content_line.tex => content_line} | 0 .../{content_newline.tex => content_newline} | 0 ...ontent_partition.tex => content_partition} | 0 .../{content_space.tex => content_space} | 0 .../{content_verse.tex => content_verse} | 0 .../latex/{content_word.tex => content_word} | 0 .../chordpro/data/latex/{song.tex => song} | 0 patacrep/songs/latex/__init__.py | 4 +- patacrep/templates.py | 46 +++++++++---------- 23 files changed, 56 insertions(+), 49 deletions(-) rename patacrep/songs/chordpro/data/latex/{content_chord.tex => content_chord} (100%) rename patacrep/songs/chordpro/data/latex/{content_chordlist.tex => content_chordlist} (100%) rename patacrep/songs/chordpro/data/latex/{content_comment.tex => content_comment} (100%) rename patacrep/songs/chordpro/data/latex/{content_define.tex => content_define} (100%) rename patacrep/songs/chordpro/data/latex/{content_error.tex => content_error} (100%) rename patacrep/songs/chordpro/data/latex/{content_guitar_comment.tex => content_guitar_comment} (100%) rename patacrep/songs/chordpro/data/latex/{content_image.tex => content_image} (100%) rename patacrep/songs/chordpro/data/latex/{content_line.tex => content_line} (100%) rename patacrep/songs/chordpro/data/latex/{content_newline.tex => content_newline} (100%) rename patacrep/songs/chordpro/data/latex/{content_partition.tex => content_partition} (100%) rename patacrep/songs/chordpro/data/latex/{content_space.tex => content_space} (100%) rename patacrep/songs/chordpro/data/latex/{content_verse.tex => content_verse} (100%) rename patacrep/songs/chordpro/data/latex/{content_word.tex => content_word} (100%) rename patacrep/songs/chordpro/data/latex/{song.tex => song} (100%) diff --git a/patacrep/build.py b/patacrep/build.py index c9aa87e3..679fc82b 100644 --- a/patacrep/build.py +++ b/patacrep/build.py @@ -113,7 +113,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..4f8cd8f4 100755 --- a/patacrep/content/song.py +++ b/patacrep/content/song.py @@ -34,7 +34,7 @@ class SongRenderer(Content): def render(self, context): """Return the string that will render the song.""" - return self.song.tex(output=context['filename']) + return self.song.render(output=context['filename'], output_format="latex") #pylint: disable=unused-argument def parse(keyword, argument, contentlist, config): diff --git a/patacrep/data/templates/songs.tex b/patacrep/data/templates/songs.tex index 1ef8ea7a..bdfcf7bb 100644 --- a/patacrep/data/templates/songs.tex +++ b/patacrep/data/templates/songs.tex @@ -108,6 +108,6 @@ \phantomsection \addcontentsline{toc}{section}{\songlistname} -((render_content(content) )) +(( render(content) )) (* endblock *) diff --git a/patacrep/songs/__init__.py b/patacrep/songs/__init__.py index 59a85f7a..c1af76e7 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,20 +62,20 @@ 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 @@ -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 diff --git a/patacrep/songs/chordpro/__init__.py b/patacrep/songs/chordpro/__init__.py index d5efd135..8be6ad5e 100644 --- a/patacrep/songs/chordpro/__init__.py +++ b/patacrep/songs/chordpro/__init__.py @@ -7,14 +7,14 @@ import os from patacrep import encoding, files from patacrep.songs import Song 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.""" @@ -28,7 +28,7 @@ class ChordproSong(Song): 'song': song, } - def tex(self, output): + def render(self, output, output_format): context = { 'language': self.config.get( 'lang', @@ -38,27 +38,31 @@ class ChordproSong(Song): "titles": self.titles, "authors": self.authors, "metadata": self.data, - "render": self.render_tex, + "render": self._render_ast, } - 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="song.tex") + 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 049a3b2f..173f73f4 100644 --- a/patacrep/songs/chordpro/ast.py +++ b/patacrep/songs/chordpro/ast.py @@ -73,14 +73,14 @@ 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) def chordpro(self): """Return the chordpro string corresponding to this object.""" diff --git a/patacrep/songs/chordpro/data/latex/content_chord.tex b/patacrep/songs/chordpro/data/latex/content_chord similarity index 100% rename from patacrep/songs/chordpro/data/latex/content_chord.tex rename to patacrep/songs/chordpro/data/latex/content_chord diff --git a/patacrep/songs/chordpro/data/latex/content_chordlist.tex b/patacrep/songs/chordpro/data/latex/content_chordlist similarity index 100% rename from patacrep/songs/chordpro/data/latex/content_chordlist.tex rename to patacrep/songs/chordpro/data/latex/content_chordlist 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.tex b/patacrep/songs/chordpro/data/latex/content_define similarity index 100% rename from patacrep/songs/chordpro/data/latex/content_define.tex rename to patacrep/songs/chordpro/data/latex/content_define diff --git a/patacrep/songs/chordpro/data/latex/content_error.tex b/patacrep/songs/chordpro/data/latex/content_error similarity index 100% rename from patacrep/songs/chordpro/data/latex/content_error.tex rename to patacrep/songs/chordpro/data/latex/content_error 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.tex b/patacrep/songs/chordpro/data/latex/content_image similarity index 100% rename from patacrep/songs/chordpro/data/latex/content_image.tex rename to patacrep/songs/chordpro/data/latex/content_image diff --git a/patacrep/songs/chordpro/data/latex/content_line.tex b/patacrep/songs/chordpro/data/latex/content_line similarity index 100% rename from patacrep/songs/chordpro/data/latex/content_line.tex rename to patacrep/songs/chordpro/data/latex/content_line diff --git a/patacrep/songs/chordpro/data/latex/content_newline.tex b/patacrep/songs/chordpro/data/latex/content_newline similarity index 100% rename from patacrep/songs/chordpro/data/latex/content_newline.tex rename to patacrep/songs/chordpro/data/latex/content_newline diff --git a/patacrep/songs/chordpro/data/latex/content_partition.tex b/patacrep/songs/chordpro/data/latex/content_partition similarity index 100% rename from patacrep/songs/chordpro/data/latex/content_partition.tex rename to patacrep/songs/chordpro/data/latex/content_partition diff --git a/patacrep/songs/chordpro/data/latex/content_space.tex b/patacrep/songs/chordpro/data/latex/content_space similarity index 100% rename from patacrep/songs/chordpro/data/latex/content_space.tex rename to patacrep/songs/chordpro/data/latex/content_space diff --git a/patacrep/songs/chordpro/data/latex/content_verse.tex b/patacrep/songs/chordpro/data/latex/content_verse similarity index 100% rename from patacrep/songs/chordpro/data/latex/content_verse.tex rename to patacrep/songs/chordpro/data/latex/content_verse diff --git a/patacrep/songs/chordpro/data/latex/content_word.tex b/patacrep/songs/chordpro/data/latex/content_word similarity index 100% rename from patacrep/songs/chordpro/data/latex/content_word.tex rename to patacrep/songs/chordpro/data/latex/content_word diff --git a/patacrep/songs/chordpro/data/latex/song.tex b/patacrep/songs/chordpro/data/latex/song similarity index 100% rename from patacrep/songs/chordpro/data/latex/song.tex rename to patacrep/songs/chordpro/data/latex/song diff --git a/patacrep/songs/latex/__init__.py b/patacrep/songs/latex/__init__.py index 8a0893c1..1c84e3f1 100644 --- a/patacrep/songs/latex/__init__.py +++ b/patacrep/songs/latex/__init__.py @@ -25,8 +25,8 @@ class LatexSong(Song): self.authors = [self.data['by']] del self.data['by'] - def tex(self, output): - """Return the LaTeX code rendering the song.""" + def render_latex(self, output): + """Return the code rendering the song.""" return r'\input{{{}}}'.format(files.path2posix( files.relpath( self.fullpath, diff --git a/patacrep/templates.py b/patacrep/templates.py index 69e5f10c..4b81c08d 100644 --- a/patacrep/templates.py +++ b/patacrep/templates.py @@ -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: From 3c89a70f736a6864e92073195589f07e398c4553 Mon Sep 17 00:00:00 2001 From: Louis Date: Sat, 29 Aug 2015 00:37:38 +0200 Subject: [PATCH 12/32] [chordpro] Songs can now be rendered in any format (given that it has been implemented) --- patacrep/songs/chordpro/__init__.py | 5 +- patacrep/songs/chordpro/ast.py | 13 ++-- .../chordpro/data/chordpro/content_chord | 9 +++ .../chordpro/data/chordpro/content_chordlist | 6 ++ .../chordpro/data/chordpro/content_comment | 1 + .../chordpro/data/chordpro/content_define | 25 ++++++++ .../chordpro/data/chordpro/content_error | 3 + .../data/chordpro/content_guitar_comment | 1 + .../chordpro/data/chordpro/content_image | 1 + .../songs/chordpro/data/chordpro/content_line | 3 + .../chordpro/data/chordpro/content_newline | 2 + .../chordpro/data/chordpro/content_partition | 1 + .../chordpro/data/chordpro/content_space | 1 + .../chordpro/data/chordpro/content_tablature | 5 ++ .../chordpro/data/chordpro/content_verse | 5 ++ .../songs/chordpro/data/chordpro/content_word | 1 + patacrep/songs/chordpro/data/chordpro/song | 34 ++++++++++ .../songs/chordpro/data/latex/content_error | 2 +- patacrep/songs/chordpro/test/00.txt | 2 +- patacrep/songs/chordpro/test/01.txt | 3 +- patacrep/songs/chordpro/test/02.txt | 1 + patacrep/songs/chordpro/test/03.txt | 1 + patacrep/songs/chordpro/test/04.txt | 3 +- patacrep/songs/chordpro/test/05.txt | 3 +- patacrep/songs/chordpro/test/06.txt | 1 + patacrep/songs/chordpro/test/07.txt | 3 +- patacrep/songs/chordpro/test/08.txt | 5 +- patacrep/songs/chordpro/test/09.txt | 5 +- patacrep/songs/chordpro/test/10.txt | 3 +- patacrep/songs/chordpro/test/11.txt | 3 +- patacrep/songs/chordpro/test/12.txt | 3 +- patacrep/songs/chordpro/test/13.txt | 7 +- patacrep/songs/chordpro/test/21.txt | 3 +- patacrep/songs/chordpro/test/22.txt | 1 + patacrep/songs/chordpro/test/23.txt | 2 +- patacrep/songs/chordpro/test/24.txt | 3 +- patacrep/songs/chordpro/test/25.txt | 3 +- patacrep/songs/chordpro/test/26.txt | 1 + patacrep/songs/chordpro/test/27.txt | 3 +- patacrep/songs/chordpro/test/28.txt | 5 +- patacrep/songs/chordpro/test/29.txt | 5 +- patacrep/songs/chordpro/test/chords.txt | 27 ++++---- patacrep/songs/chordpro/test/customchords.txt | 2 +- patacrep/songs/chordpro/test/greensleeves.txt | 64 +++++++++++-------- .../songs/chordpro/test/invalid_chord.txt | 7 +- .../chordpro/test/invalid_customchord.txt | 2 + patacrep/songs/chordpro/test/metadata.sgc | 2 +- patacrep/songs/chordpro/test/metadata.txt | 13 ++-- patacrep/songs/chordpro/test/test_parser.py | 23 ++++--- patacrep/songs/syntax.py | 14 ++-- 50 files changed, 239 insertions(+), 102 deletions(-) create mode 100644 patacrep/songs/chordpro/data/chordpro/content_chord create mode 100644 patacrep/songs/chordpro/data/chordpro/content_chordlist create mode 100644 patacrep/songs/chordpro/data/chordpro/content_comment create mode 100644 patacrep/songs/chordpro/data/chordpro/content_define create mode 100644 patacrep/songs/chordpro/data/chordpro/content_error create mode 100644 patacrep/songs/chordpro/data/chordpro/content_guitar_comment create mode 100644 patacrep/songs/chordpro/data/chordpro/content_image create mode 100644 patacrep/songs/chordpro/data/chordpro/content_line create mode 100644 patacrep/songs/chordpro/data/chordpro/content_newline create mode 100644 patacrep/songs/chordpro/data/chordpro/content_partition create mode 100644 patacrep/songs/chordpro/data/chordpro/content_space create mode 100644 patacrep/songs/chordpro/data/chordpro/content_tablature create mode 100644 patacrep/songs/chordpro/data/chordpro/content_verse create mode 100644 patacrep/songs/chordpro/data/chordpro/content_word create mode 100644 patacrep/songs/chordpro/data/chordpro/song diff --git a/patacrep/songs/chordpro/__init__.py b/patacrep/songs/chordpro/__init__.py index 8be6ad5e..97b83670 100644 --- a/patacrep/songs/chordpro/__init__.py +++ b/patacrep/songs/chordpro/__init__.py @@ -30,10 +30,7 @@ class ChordproSong(Song): def render(self, output, output_format): context = { - 'language': self.config.get( - 'lang', - self.cached['song'].get_data_argument('language', 'english'), - ), + 'language': self.languages[0], "path": files.relpath(self.fullpath, os.path.dirname(output)), "titles": self.titles, "authors": self.authors, diff --git a/patacrep/songs/chordpro/ast.py b/patacrep/songs/chordpro/ast.py index 173f73f4..8b6690c2 100644 --- a/patacrep/songs/chordpro/ast.py +++ b/patacrep/songs/chordpro/ast.py @@ -367,19 +367,13 @@ class Song(AST): def add_key(self, data): """Add a new {key: foo: bar} directive.""" key, *argument = data.argument.split(":") - self._keys.insert(0, Directive( + 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 _process_relative(self, directive): """Return the directive, in which the argument is given relative to file @@ -484,6 +478,7 @@ class Tab(AST): """Tablature""" inline = True + _template = "tablature" def __init__(self): super().__init__() diff --git a/patacrep/songs/chordpro/data/chordpro/content_chord b/patacrep/songs/chordpro/data/chordpro/content_chord new file mode 100644 index 00000000..6fce5be6 --- /dev/null +++ b/patacrep/songs/chordpro/data/chordpro/content_chord @@ -0,0 +1,9 @@ +((- content.key -)) +(* if content.alteration *)(( content.alteration ))(* endif -*) +(* if content.modifier *)((content.modifier))(* endif -*) +(* if content.addnote *)((content.addnote))(* endif -*) +(* if content.basskey -*) + / + ((- content.basskey -)) + (* if content.bassalteration *)(( content.bassalteration ))(* endif -*) +(* endif -*) 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/chordpro/content_newline b/patacrep/songs/chordpro/data/chordpro/content_newline new file mode 100644 index 00000000..139597f9 --- /dev/null +++ b/patacrep/songs/chordpro/data/chordpro/content_newline @@ -0,0 +1,2 @@ + + 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/chordpro/content_space b/patacrep/songs/chordpro/data/chordpro/content_space new file mode 100644 index 00000000..8d1c8b69 --- /dev/null +++ b/patacrep/songs/chordpro/data/chordpro/content_space @@ -0,0 +1 @@ + diff --git a/patacrep/songs/chordpro/data/chordpro/content_tablature b/patacrep/songs/chordpro/data/chordpro/content_tablature new file mode 100644 index 00000000..d8924b00 --- /dev/null +++ b/patacrep/songs/chordpro/data/chordpro/content_tablature @@ -0,0 +1,5 @@ +{start_of_tab} + (* for foo in content.content *) + (( foo )) + (* 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/chordpro/content_word b/patacrep/songs/chordpro/data/chordpro/content_word new file mode 100644 index 00000000..d9dd7a30 --- /dev/null +++ b/patacrep/songs/chordpro/data/chordpro/content_word @@ -0,0 +1 @@ +(( content.value )) diff --git a/patacrep/songs/chordpro/data/chordpro/song b/patacrep/songs/chordpro/data/chordpro/song new file mode 100644 index 00000000..95a5e492 --- /dev/null +++ b/patacrep/songs/chordpro/data/chordpro/song @@ -0,0 +1,34 @@ +(* 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', 'vcov', '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/content_error b/patacrep/songs/chordpro/data/latex/content_error index a41faeb5..cee78a38 100644 --- a/patacrep/songs/chordpro/data/latex/content_error +++ b/patacrep/songs/chordpro/data/latex/content_error @@ -1,3 +1,3 @@ -ERROR : Template not found for \verb+(( content.__class__))+. See the logs for details. +ERROR : Template not found for \verb+(( content.__class__.__name__ ))+. See the logs for details. diff --git a/patacrep/songs/chordpro/test/00.txt b/patacrep/songs/chordpro/test/00.txt index 8b137891..3e2185b7 100644 --- a/patacrep/songs/chordpro/test/00.txt +++ b/patacrep/songs/chordpro/test/00.txt @@ -1 +1 @@ - +{language: english} diff --git a/patacrep/songs/chordpro/test/01.txt b/patacrep/songs/chordpro/test/01.txt index 9665cac0..ae7eabc4 100644 --- a/patacrep/songs/chordpro/test/01.txt +++ b/patacrep/songs/chordpro/test/01.txt @@ -1,4 +1,5 @@ +{language: english} {start_of_verse} - A verse line + A verse line {end_of_verse} diff --git a/patacrep/songs/chordpro/test/02.txt b/patacrep/songs/chordpro/test/02.txt index ef03158b..2a8629e0 100644 --- a/patacrep/songs/chordpro/test/02.txt +++ b/patacrep/songs/chordpro/test/02.txt @@ -1,2 +1,3 @@ +{language: english} {title: A directive} diff --git a/patacrep/songs/chordpro/test/03.txt b/patacrep/songs/chordpro/test/03.txt index 8b137891..341c9bd4 100644 --- a/patacrep/songs/chordpro/test/03.txt +++ b/patacrep/songs/chordpro/test/03.txt @@ -1 +1,2 @@ +{language: english} diff --git a/patacrep/songs/chordpro/test/04.txt b/patacrep/songs/chordpro/test/04.txt index 9e9932a3..e9c2a952 100644 --- a/patacrep/songs/chordpro/test/04.txt +++ b/patacrep/songs/chordpro/test/04.txt @@ -1,4 +1,5 @@ +{language: english} {start_of_chorus} - A one line 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 b7736212..9bc7f016 100644 --- a/patacrep/songs/chordpro/test/05.txt +++ b/patacrep/songs/chordpro/test/05.txt @@ -1,4 +1,5 @@ +{language: english} {start_of_bridge} - A one line 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 8b137891..341c9bd4 100644 --- a/patacrep/songs/chordpro/test/06.txt +++ b/patacrep/songs/chordpro/test/06.txt @@ -1 +1,2 @@ +{language: english} diff --git a/patacrep/songs/chordpro/test/07.txt b/patacrep/songs/chordpro/test/07.txt index 3c45010c..741fee4a 100644 --- a/patacrep/songs/chordpro/test/07.txt +++ b/patacrep/songs/chordpro/test/07.txt @@ -1,4 +1,5 @@ +{language: english} {start_of_tab} - A tab + A tab {end_of_tab} diff --git a/patacrep/songs/chordpro/test/08.txt b/patacrep/songs/chordpro/test/08.txt index d224789c..61224d41 100644 --- a/patacrep/songs/chordpro/test/08.txt +++ b/patacrep/songs/chordpro/test/08.txt @@ -1,4 +1,7 @@ +{language: english} + + {start_of_verse} - A lot of new lines + 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 6d19ba36..942a91e1 100644 --- a/patacrep/songs/chordpro/test/09.txt +++ b/patacrep/songs/chordpro/test/09.txt @@ -1,5 +1,8 @@ +{language: english} {title: and a directive} + + {start_of_verse} - A lot of new lines + 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 c289fda9..23bce4fa 100644 --- a/patacrep/songs/chordpro/test/10.txt +++ b/patacrep/songs/chordpro/test/10.txt @@ -1,4 +1,5 @@ +{language: english} {start_of_verse} - A line[A] with a chord + 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 ccf1d520..79d44702 100644 --- a/patacrep/songs/chordpro/test/11.txt +++ b/patacrep/songs/chordpro/test/11.txt @@ -1,4 +1,5 @@ +{language: english} {start_of_verse} - A line ending with a chord[A] + 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 72a5b745..6afb5bf8 100644 --- a/patacrep/songs/chordpro/test/12.txt +++ b/patacrep/songs/chordpro/test/12.txt @@ -1,4 +1,5 @@ +{language: english} {start_of_verse} - [A]A line starting with a chord + [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 b2f0526f..a2b60a5e 100644 --- a/patacrep/songs/chordpro/test/13.txt +++ b/patacrep/songs/chordpro/test/13.txt @@ -1,6 +1,7 @@ +{language: english} {start_of_tab} - A table - wit many # weir [ - [ symbols + A table + wit many # weir [ + [ symbols {end_of_tab} diff --git a/patacrep/songs/chordpro/test/21.txt b/patacrep/songs/chordpro/test/21.txt index 9665cac0..ae7eabc4 100644 --- a/patacrep/songs/chordpro/test/21.txt +++ b/patacrep/songs/chordpro/test/21.txt @@ -1,4 +1,5 @@ +{language: english} {start_of_verse} - A verse line + A verse line {end_of_verse} diff --git a/patacrep/songs/chordpro/test/22.txt b/patacrep/songs/chordpro/test/22.txt index ef03158b..2a8629e0 100644 --- a/patacrep/songs/chordpro/test/22.txt +++ b/patacrep/songs/chordpro/test/22.txt @@ -1,2 +1,3 @@ +{language: english} {title: A directive} diff --git a/patacrep/songs/chordpro/test/23.txt b/patacrep/songs/chordpro/test/23.txt index 8b137891..3e2185b7 100644 --- a/patacrep/songs/chordpro/test/23.txt +++ b/patacrep/songs/chordpro/test/23.txt @@ -1 +1 @@ - +{language: english} diff --git a/patacrep/songs/chordpro/test/24.txt b/patacrep/songs/chordpro/test/24.txt index 9e9932a3..e9c2a952 100644 --- a/patacrep/songs/chordpro/test/24.txt +++ b/patacrep/songs/chordpro/test/24.txt @@ -1,4 +1,5 @@ +{language: english} {start_of_chorus} - A one line 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 b7736212..9bc7f016 100644 --- a/patacrep/songs/chordpro/test/25.txt +++ b/patacrep/songs/chordpro/test/25.txt @@ -1,4 +1,5 @@ +{language: english} {start_of_bridge} - A one line 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 8b137891..341c9bd4 100644 --- a/patacrep/songs/chordpro/test/26.txt +++ b/patacrep/songs/chordpro/test/26.txt @@ -1 +1,2 @@ +{language: english} diff --git a/patacrep/songs/chordpro/test/27.txt b/patacrep/songs/chordpro/test/27.txt index 3c45010c..741fee4a 100644 --- a/patacrep/songs/chordpro/test/27.txt +++ b/patacrep/songs/chordpro/test/27.txt @@ -1,4 +1,5 @@ +{language: english} {start_of_tab} - A tab + A tab {end_of_tab} diff --git a/patacrep/songs/chordpro/test/28.txt b/patacrep/songs/chordpro/test/28.txt index d224789c..61224d41 100644 --- a/patacrep/songs/chordpro/test/28.txt +++ b/patacrep/songs/chordpro/test/28.txt @@ -1,4 +1,7 @@ +{language: english} + + {start_of_verse} - A lot of new lines + 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 6d19ba36..942a91e1 100644 --- a/patacrep/songs/chordpro/test/29.txt +++ b/patacrep/songs/chordpro/test/29.txt @@ -1,5 +1,8 @@ +{language: english} {title: and a directive} + + {start_of_verse} - A lot of new lines + 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 2a98ce94..955f44d6 100644 --- a/patacrep/songs/chordpro/test/chords.txt +++ b/patacrep/songs/chordpro/test/chords.txt @@ -1,16 +1,17 @@ +{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 + [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 {end_of_verse} diff --git a/patacrep/songs/chordpro/test/customchords.txt b/patacrep/songs/chordpro/test/customchords.txt index 52c9f0e3..1148a901 100644 --- a/patacrep/songs/chordpro/test/customchords.txt +++ b/patacrep/songs/chordpro/test/customchords.txt @@ -1,3 +1,3 @@ +{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 - -} - diff --git a/patacrep/songs/chordpro/test/greensleeves.txt b/patacrep/songs/chordpro/test/greensleeves.txt index 538a146d..98248e83 100644 --- a/patacrep/songs/chordpro/test/greensleeves.txt +++ b/patacrep/songs/chordpro/test/greensleeves.txt @@ -1,52 +1,60 @@ +{language: english} +{columns: 2} {title: Greensleeves} {title: Un autre sous-titre} {title: Un sous titre} -{by: Traditionnel} -{language: english} -{columns: 2} -{cov: DIRNAME/traditionnel} +{artist: Traditionnel} {album: Angleterre} +{cov: DIRNAME/traditionnel} + + {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 + 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} + {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 + 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 + 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 + 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 + 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.txt b/patacrep/songs/chordpro/test/invalid_chord.txt index e72a02d0..2a17e6e7 100644 --- a/patacrep/songs/chordpro/test/invalid_chord.txt +++ b/patacrep/songs/chordpro/test/invalid_chord.txt @@ -1,6 +1,7 @@ +{language: english} {start_of_verse} - This is invalid. - This [A]too. - And []as well. + This is invalid. + This [A]too. + And []as well. {end_of_verse} diff --git a/patacrep/songs/chordpro/test/invalid_customchord.txt b/patacrep/songs/chordpro/test/invalid_customchord.txt index e69de29b..341c9bd4 100644 --- a/patacrep/songs/chordpro/test/invalid_customchord.txt +++ b/patacrep/songs/chordpro/test/invalid_customchord.txt @@ -0,0 +1,2 @@ +{language: english} + diff --git a/patacrep/songs/chordpro/test/metadata.sgc b/patacrep/songs/chordpro/test/metadata.sgc index eee1bf9d..6e221446 100644 --- a/patacrep/songs/chordpro/test/metadata.sgc +++ b/patacrep/songs/chordpro/test/metadata.sgc @@ -8,7 +8,7 @@ {language: english} {by: Author1} {artist: Author2} -{album: Albom} +{album: Album} {copyright: Copyright} {cover: Cover} {vcover: VCover} diff --git a/patacrep/songs/chordpro/test/metadata.txt b/patacrep/songs/chordpro/test/metadata.txt index 77b9d08b..45509d2d 100644 --- a/patacrep/songs/chordpro/test/metadata.txt +++ b/patacrep/songs/chordpro/test/metadata.txt @@ -1,19 +1,18 @@ +{language: french} +{capo: Capo} {title: Title} {title: Subtitle1} {title: Subtitle2} {title: Subtitle3} {title: Subtitle4} {title: Subtitle5} -{by: Author1} -{by: Author2} -{key: {foo: Foo}} -{language: french} -{language: english} -{album: Albom} +{artist: Author1} +{artist: Author2} +{album: Album} {copyright: Copyright} {cov: DIRNAME/Cover} {vcov: VCover} -{capo: Capo} +{key: foo: Foo} {comment: Comment} {guitar_comment: GuitarComment} diff --git a/patacrep/songs/chordpro/test/test_parser.py b/patacrep/songs/chordpro/test/test_parser.py index ff2b628f..c82338b3 100644 --- a/patacrep/songs/chordpro/test/test_parser.py +++ b/patacrep/songs/chordpro/test/test_parser.py @@ -6,7 +6,8 @@ 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 class ParserTxtRenderer(unittest.TestCase): """Test parser, and renderer as a txt file.""" @@ -26,15 +27,17 @@ class ParserTxtRenderer(unittest.TestCase): 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: - self.assertMultiLineEqual( - chordpro.parse_song( - sourcefile.read(), - os.path.abspath(sourcefile.name), - ).chordpro().strip(), - expectfile.read().strip().replace("DIRNAME", os.path.dirname(self.basename)), - ) + config = DEFAULT_CONFIG.copy() + config.update({ + 'encoding': 'utf8', + '_compiled_authwords': {}, + }) + with open("{}.txt".format(self.basename), 'r', encoding='utf8') as expectfile: + chordproname = "{}.sgc".format(self.basename) + self.assertMultiLineEqual( + ChordproSong(None, chordproname, config).render(output=chordproname, output_format="chordpro").strip(), + expectfile.read().strip().replace("DIRNAME", os.path.dirname(self.basename)).strip(), + ) def load_tests(__loader, tests, __pattern): """Load several tests given test files present in the directory.""" diff --git a/patacrep/songs/syntax.py b/patacrep/songs/syntax.py index 00768019..7f019374 100644 --- a/patacrep/songs/syntax.py +++ b/patacrep/songs/syntax.py @@ -21,13 +21,18 @@ class Parser: return column @staticmethod - def error(*, line, column=None, message=""): + def error(*, line=None, column=None, message=""): """Display an error message""" - text = "Line {}".format(line) + coordinates = [] + if line is not None: + coordinates.append("line {}".format(line)) if column is not None: - text += ", column {}".format(column) - if message: + coordinates.append("column {}".format(column)) + text = ", ".join(coordinates) + if message and text: text += ": " + message + elif message: + text += message else: text += "." LOGGER.error(text) @@ -36,7 +41,6 @@ class Parser: """Manage parsing errors.""" if token is None: self.error( - line=token.lineno, message="Unexpected end of file.", ) else: From fefada9f14916bf74ce30eaa0c1c562ff52a9b88 Mon Sep 17 00:00:00 2001 From: Louis Date: Sat, 29 Aug 2015 09:11:01 +0200 Subject: [PATCH 13/32] [chordpro] Removed useless methods (has been replaced by templates in previous commit) --- patacrep/songs/chordpro/ast.py | 103 --------------------------------- 1 file changed, 103 deletions(-) diff --git a/patacrep/songs/chordpro/ast.py b/patacrep/songs/chordpro/ast.py index 8b6690c2..0e68f6dc 100644 --- a/patacrep/songs/chordpro/ast.py +++ b/patacrep/songs/chordpro/ast.py @@ -82,16 +82,9 @@ class AST: base = self._template return "content_{}".format(base) - def chordpro(self): - """Return the chordpro string corresponding to this object.""" - raise NotImplementedError() - class Error(AST): """Parsing error. To be ignored.""" - def chordpro(self): - return "" - class Line(AST): """A line is a sequence of (possibly truncated) words, spaces and chords.""" @@ -106,9 +99,6 @@ class Line(AST): self.line.insert(0, data) return self - def chordpro(self): - return "".join([item.chordpro() for item in self.line]) - def strip(self): """Remove spaces at the beginning and end of line.""" while True: @@ -135,9 +125,6 @@ class Word(LineElement): super().__init__() self.value = value - def chordpro(self): - return self.value - class Space(LineElement): """A space between words""" _template = "space" @@ -145,9 +132,6 @@ class Space(LineElement): def __init__(self): super().__init__() - def chordpro(self): - return " " - class ChordList(LineElement): """A list of chords.""" _template = "chordlist" @@ -155,11 +139,6 @@ class ChordList(LineElement): def __init__(self, *chords): self.chords = chords - def chordpro(self): - return "[{}]".format(" ".join( - [chord.chordpro() for chord in self.chords] - )) - class Chord(AST): """A chord.""" @@ -182,21 +161,6 @@ class Chord(AST): self.basskey = basskey self.bassalteration = bassalteration - def chordpro(self): - text = "" - text += self.key - if self.alteration is not None: - text += self.alteration - if self.modifier is not None: - text += self.modifier - if self.addnote is not None: - text += str(self.addnote) - if self.basskey is not None: - text += "/" + self.basskey - if self.bassalteration is not None: - text += self.bassalteration - return text - class Verse(AST): """A verse (or bridge, or chorus)""" _template = "verse" @@ -212,12 +176,6 @@ class Verse(AST): self.lines.insert(0, data) return self - def chordpro(self): - return '{{start_of_{type}}}\n{content}\n{{end_of_{type}}}'.format( - type=self.type, - content=_indent("\n".join([line.chordpro() for line in self.lines])), - ) - class Chorus(Verse): """Chorus""" type = 'chorus' @@ -297,30 +255,6 @@ class Song(AST): 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 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 chordpro(self): - return ( - "\n".join(self.str_meta()).strip() - + - "\n\n" - + - "\n".join([item.chordpro() for item in self.content]).strip() - ) - - def add_title(self, data): """Add a title""" self._titles.insert(0, data.argument) @@ -391,9 +325,6 @@ class Newline(AST): """New line""" _template = "newline" - def chordpro(self): - return "" - class Directive(AST): """A directive""" @@ -416,15 +347,6 @@ class Directive(AST): """ return self.keyword in INLINE_PROPERTIES - def chordpro(self): - if self.argument is not None: - return "{{{}: {}}}".format( - self.keyword, - self.argument, - ) - else: - return "{{{}}}".format(self.keyword) - def __str__(self): return self.argument @@ -452,25 +374,6 @@ class Define(Directive): 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 __str__(self): return None @@ -488,9 +391,3 @@ class Tab(AST): """Add an element at the beginning of content.""" self.content.insert(0, data) return self - - def chordpro(self): - return '{{start_of_tab}}\n{}\n{{end_of_tab}}'.format( - _indent("\n".join(self.content)), - ) - From acdc94b3e484a002b0dbe2132bed3ebbfe17cb6a Mon Sep 17 00:00:00 2001 From: Louis Date: Sat, 29 Aug 2015 09:10:56 +0200 Subject: [PATCH 14/32] pylint --- patacrep/songs/chordpro/test/test_parser.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/patacrep/songs/chordpro/test/test_parser.py b/patacrep/songs/chordpro/test/test_parser.py index c82338b3..8fdedc22 100644 --- a/patacrep/songs/chordpro/test/test_parser.py +++ b/patacrep/songs/chordpro/test/test_parser.py @@ -35,8 +35,14 @@ class ParserTxtRenderer(unittest.TestCase): with open("{}.txt".format(self.basename), 'r', encoding='utf8') as expectfile: chordproname = "{}.sgc".format(self.basename) self.assertMultiLineEqual( - ChordproSong(None, chordproname, config).render(output=chordproname, output_format="chordpro").strip(), - expectfile.read().strip().replace("DIRNAME", os.path.dirname(self.basename)).strip(), + ChordproSong(None, chordproname, config).render( + output=chordproname, + output_format="chordpro", + ).strip(), + expectfile.read().replace( + "DIRNAME", + os.path.dirname(self.basename), + ).strip(), ) def load_tests(__loader, tests, __pattern): From eb9c8618d88b94def00ba95c1fc3ad8b6907936f Mon Sep 17 00:00:00 2001 From: Louis Date: Sat, 29 Aug 2015 11:22:09 +0200 Subject: [PATCH 15/32] [test] Disabling logging during tests --- patacrep/songs/chordpro/test/test_parser.py | 23 ++++++++++++--------- patacrep/test.py | 10 +++++++++ 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/patacrep/songs/chordpro/test/test_parser.py b/patacrep/songs/chordpro/test/test_parser.py index 8fdedc22..2fc89ca6 100644 --- a/patacrep/songs/chordpro/test/test_parser.py +++ b/patacrep/songs/chordpro/test/test_parser.py @@ -8,6 +8,8 @@ import unittest 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.""" @@ -34,16 +36,17 @@ class ParserTxtRenderer(unittest.TestCase): }) with open("{}.txt".format(self.basename), 'r', encoding='utf8') as expectfile: chordproname = "{}.sgc".format(self.basename) - self.assertMultiLineEqual( - ChordproSong(None, chordproname, config).render( - output=chordproname, - output_format="chordpro", - ).strip(), - expectfile.read().replace( - "DIRNAME", - os.path.dirname(self.basename), - ).strip(), - ) + with disable_logging(): + self.assertMultiLineEqual( + ChordproSong(None, chordproname, config).render( + output=chordproname, + output_format="chordpro", + ).strip(), + expectfile.read().replace( + "DIRNAME", + os.path.dirname(self.basename), + ).strip(), + ) def load_tests(__loader, tests, __pattern): """Load several tests given test files present in the directory.""" 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()) + From 96697be9d1a990bab9e36a9ba53751223701d8fd Mon Sep 17 00:00:00 2001 From: Louis Date: Sat, 29 Aug 2015 11:49:56 +0200 Subject: [PATCH 16/32] [chorpro][test] Simplifying parsing and compilation tests: preparation for LaTeX tests --- patacrep/songs/chordpro/data/chordpro/song | 3 +- .../chordpro/test/{00.txt => 00.sgc.sgc} | 0 .../chordpro/test/{00.sgc => 00.sgc.source} | 0 .../chordpro/test/{01.txt => 01.sgc.sgc} | 0 .../chordpro/test/{01.sgc => 01.sgc.source} | 0 .../chordpro/test/{02.txt => 02.sgc.sgc} | 0 .../chordpro/test/{02.sgc => 02.sgc.source} | 0 .../chordpro/test/{03.txt => 03.sgc.sgc} | 0 .../chordpro/test/{03.sgc => 03.sgc.source} | 0 .../chordpro/test/{04.txt => 04.sgc.sgc} | 0 .../chordpro/test/{04.sgc => 04.sgc.source} | 0 .../chordpro/test/{05.txt => 05.sgc.sgc} | 0 .../chordpro/test/{05.sgc => 05.sgc.source} | 0 .../chordpro/test/{06.txt => 06.sgc.sgc} | 0 .../chordpro/test/{06.sgc => 06.sgc.source} | 0 .../chordpro/test/{07.txt => 07.sgc.sgc} | 0 .../chordpro/test/{07.sgc => 07.sgc.source} | 0 .../chordpro/test/{08.txt => 08.sgc.sgc} | 0 .../chordpro/test/{08.sgc => 08.sgc.source} | 0 .../chordpro/test/{09.txt => 09.sgc.sgc} | 0 .../chordpro/test/{09.sgc => 09.sgc.source} | 0 .../chordpro/test/{10.txt => 10.sgc.sgc} | 0 .../chordpro/test/{10.sgc => 10.sgc.source} | 0 .../chordpro/test/{11.txt => 11.sgc.sgc} | 0 .../chordpro/test/{11.sgc => 11.sgc.source} | 0 .../chordpro/test/{12.txt => 12.sgc.sgc} | 0 .../chordpro/test/{12.sgc => 12.sgc.source} | 0 .../chordpro/test/{13.txt => 13.sgc.sgc} | 0 .../chordpro/test/{13.sgc => 13.sgc.source} | 0 .../chordpro/test/{21.txt => 21.sgc.sgc} | 0 .../chordpro/test/{21.sgc => 21.sgc.source} | 0 .../chordpro/test/{22.txt => 22.sgc.sgc} | 0 .../chordpro/test/{22.sgc => 22.sgc.source} | 0 .../chordpro/test/{23.txt => 23.sgc.sgc} | 0 .../chordpro/test/{23.sgc => 23.sgc.source} | 0 .../chordpro/test/{24.txt => 24.sgc.sgc} | 0 .../chordpro/test/{24.sgc => 24.sgc.source} | 0 .../chordpro/test/{25.txt => 25.sgc.sgc} | 0 .../chordpro/test/{25.sgc => 25.sgc.source} | 0 .../chordpro/test/{26.txt => 26.sgc.sgc} | 0 .../chordpro/test/{26.sgc => 26.sgc.source} | 0 .../chordpro/test/{27.txt => 27.sgc.sgc} | 0 .../chordpro/test/{27.sgc => 27.sgc.source} | 0 .../chordpro/test/{28.txt => 28.sgc.sgc} | 0 .../chordpro/test/{28.sgc => 28.sgc.source} | 0 .../chordpro/test/{29.txt => 29.sgc.sgc} | 0 .../chordpro/test/{29.sgc => 29.sgc.source} | 0 patacrep/songs/chordpro/test/30.sgc | 1 - .../test/{chords.txt => chords.sgc.sgc} | 0 .../test/{chords.sgc => chords.sgc.source} | 0 ...{customchords.txt => customchords.sgc.sgc} | 0 ...stomchords.sgc => customchords.sgc.source} | 0 ...{greensleeves.txt => greensleeves.sgc.sgc} | 0 ...eensleeves.sgc => greensleeves.sgc.source} | 0 ...nvalid_chord.txt => invalid_chord.sgc.sgc} | 0 ...lid_chord.sgc => invalid_chord.sgc.source} | 0 ...mchord.txt => invalid_customchord.sgc.sgc} | 0 ...ord.sgc => invalid_customchord.sgc.source} | 0 .../test/{metadata.txt => metadata.sgc.sgc} | 0 .../{metadata.sgc => metadata.sgc.source} | 0 patacrep/songs/chordpro/test/test_parser.py | 60 +++++++------------ 61 files changed, 24 insertions(+), 40 deletions(-) rename patacrep/songs/chordpro/test/{00.txt => 00.sgc.sgc} (100%) rename patacrep/songs/chordpro/test/{00.sgc => 00.sgc.source} (100%) rename patacrep/songs/chordpro/test/{01.txt => 01.sgc.sgc} (100%) rename patacrep/songs/chordpro/test/{01.sgc => 01.sgc.source} (100%) rename patacrep/songs/chordpro/test/{02.txt => 02.sgc.sgc} (100%) rename patacrep/songs/chordpro/test/{02.sgc => 02.sgc.source} (100%) rename patacrep/songs/chordpro/test/{03.txt => 03.sgc.sgc} (100%) rename patacrep/songs/chordpro/test/{03.sgc => 03.sgc.source} (100%) rename patacrep/songs/chordpro/test/{04.txt => 04.sgc.sgc} (100%) rename patacrep/songs/chordpro/test/{04.sgc => 04.sgc.source} (100%) rename patacrep/songs/chordpro/test/{05.txt => 05.sgc.sgc} (100%) rename patacrep/songs/chordpro/test/{05.sgc => 05.sgc.source} (100%) rename patacrep/songs/chordpro/test/{06.txt => 06.sgc.sgc} (100%) rename patacrep/songs/chordpro/test/{06.sgc => 06.sgc.source} (100%) rename patacrep/songs/chordpro/test/{07.txt => 07.sgc.sgc} (100%) rename patacrep/songs/chordpro/test/{07.sgc => 07.sgc.source} (100%) rename patacrep/songs/chordpro/test/{08.txt => 08.sgc.sgc} (100%) rename patacrep/songs/chordpro/test/{08.sgc => 08.sgc.source} (100%) rename patacrep/songs/chordpro/test/{09.txt => 09.sgc.sgc} (100%) rename patacrep/songs/chordpro/test/{09.sgc => 09.sgc.source} (100%) rename patacrep/songs/chordpro/test/{10.txt => 10.sgc.sgc} (100%) rename patacrep/songs/chordpro/test/{10.sgc => 10.sgc.source} (100%) rename patacrep/songs/chordpro/test/{11.txt => 11.sgc.sgc} (100%) rename patacrep/songs/chordpro/test/{11.sgc => 11.sgc.source} (100%) rename patacrep/songs/chordpro/test/{12.txt => 12.sgc.sgc} (100%) rename patacrep/songs/chordpro/test/{12.sgc => 12.sgc.source} (100%) rename patacrep/songs/chordpro/test/{13.txt => 13.sgc.sgc} (100%) rename patacrep/songs/chordpro/test/{13.sgc => 13.sgc.source} (100%) rename patacrep/songs/chordpro/test/{21.txt => 21.sgc.sgc} (100%) rename patacrep/songs/chordpro/test/{21.sgc => 21.sgc.source} (100%) rename patacrep/songs/chordpro/test/{22.txt => 22.sgc.sgc} (100%) rename patacrep/songs/chordpro/test/{22.sgc => 22.sgc.source} (100%) rename patacrep/songs/chordpro/test/{23.txt => 23.sgc.sgc} (100%) rename patacrep/songs/chordpro/test/{23.sgc => 23.sgc.source} (100%) rename patacrep/songs/chordpro/test/{24.txt => 24.sgc.sgc} (100%) rename patacrep/songs/chordpro/test/{24.sgc => 24.sgc.source} (100%) rename patacrep/songs/chordpro/test/{25.txt => 25.sgc.sgc} (100%) rename patacrep/songs/chordpro/test/{25.sgc => 25.sgc.source} (100%) rename patacrep/songs/chordpro/test/{26.txt => 26.sgc.sgc} (100%) rename patacrep/songs/chordpro/test/{26.sgc => 26.sgc.source} (100%) rename patacrep/songs/chordpro/test/{27.txt => 27.sgc.sgc} (100%) rename patacrep/songs/chordpro/test/{27.sgc => 27.sgc.source} (100%) rename patacrep/songs/chordpro/test/{28.txt => 28.sgc.sgc} (100%) rename patacrep/songs/chordpro/test/{28.sgc => 28.sgc.source} (100%) rename patacrep/songs/chordpro/test/{29.txt => 29.sgc.sgc} (100%) rename patacrep/songs/chordpro/test/{29.sgc => 29.sgc.source} (100%) delete mode 100644 patacrep/songs/chordpro/test/30.sgc rename patacrep/songs/chordpro/test/{chords.txt => chords.sgc.sgc} (100%) rename patacrep/songs/chordpro/test/{chords.sgc => chords.sgc.source} (100%) rename patacrep/songs/chordpro/test/{customchords.txt => customchords.sgc.sgc} (100%) rename patacrep/songs/chordpro/test/{customchords.sgc => customchords.sgc.source} (100%) rename patacrep/songs/chordpro/test/{greensleeves.txt => greensleeves.sgc.sgc} (100%) rename patacrep/songs/chordpro/test/{greensleeves.sgc => greensleeves.sgc.source} (100%) rename patacrep/songs/chordpro/test/{invalid_chord.txt => invalid_chord.sgc.sgc} (100%) rename patacrep/songs/chordpro/test/{invalid_chord.sgc => invalid_chord.sgc.source} (100%) rename patacrep/songs/chordpro/test/{invalid_customchord.txt => invalid_customchord.sgc.sgc} (100%) rename patacrep/songs/chordpro/test/{invalid_customchord.sgc => invalid_customchord.sgc.source} (100%) rename patacrep/songs/chordpro/test/{metadata.txt => metadata.sgc.sgc} (100%) rename patacrep/songs/chordpro/test/{metadata.sgc => metadata.sgc.source} (100%) diff --git a/patacrep/songs/chordpro/data/chordpro/song b/patacrep/songs/chordpro/data/chordpro/song index 95a5e492..30bf9a3e 100644 --- a/patacrep/songs/chordpro/data/chordpro/song +++ b/patacrep/songs/chordpro/data/chordpro/song @@ -11,7 +11,8 @@ (*- for title in titles -*) {title: (( title ))} (* endfor -*) -(* for author in authors -*) + +(*- for author in authors -*) {artist: (( author[1] )) (( author[0] ))} (* endfor *) diff --git a/patacrep/songs/chordpro/test/00.txt b/patacrep/songs/chordpro/test/00.sgc.sgc similarity index 100% rename from patacrep/songs/chordpro/test/00.txt rename to patacrep/songs/chordpro/test/00.sgc.sgc diff --git a/patacrep/songs/chordpro/test/00.sgc b/patacrep/songs/chordpro/test/00.sgc.source similarity index 100% rename from patacrep/songs/chordpro/test/00.sgc rename to patacrep/songs/chordpro/test/00.sgc.source diff --git a/patacrep/songs/chordpro/test/01.txt b/patacrep/songs/chordpro/test/01.sgc.sgc similarity index 100% rename from patacrep/songs/chordpro/test/01.txt rename to patacrep/songs/chordpro/test/01.sgc.sgc diff --git a/patacrep/songs/chordpro/test/01.sgc b/patacrep/songs/chordpro/test/01.sgc.source similarity index 100% rename from patacrep/songs/chordpro/test/01.sgc rename to patacrep/songs/chordpro/test/01.sgc.source diff --git a/patacrep/songs/chordpro/test/02.txt b/patacrep/songs/chordpro/test/02.sgc.sgc similarity index 100% rename from patacrep/songs/chordpro/test/02.txt rename to patacrep/songs/chordpro/test/02.sgc.sgc diff --git a/patacrep/songs/chordpro/test/02.sgc b/patacrep/songs/chordpro/test/02.sgc.source similarity index 100% rename from patacrep/songs/chordpro/test/02.sgc rename to patacrep/songs/chordpro/test/02.sgc.source diff --git a/patacrep/songs/chordpro/test/03.txt b/patacrep/songs/chordpro/test/03.sgc.sgc similarity index 100% rename from patacrep/songs/chordpro/test/03.txt rename to patacrep/songs/chordpro/test/03.sgc.sgc diff --git a/patacrep/songs/chordpro/test/03.sgc b/patacrep/songs/chordpro/test/03.sgc.source similarity index 100% rename from patacrep/songs/chordpro/test/03.sgc rename to patacrep/songs/chordpro/test/03.sgc.source diff --git a/patacrep/songs/chordpro/test/04.txt b/patacrep/songs/chordpro/test/04.sgc.sgc similarity index 100% rename from patacrep/songs/chordpro/test/04.txt rename to patacrep/songs/chordpro/test/04.sgc.sgc diff --git a/patacrep/songs/chordpro/test/04.sgc b/patacrep/songs/chordpro/test/04.sgc.source similarity index 100% rename from patacrep/songs/chordpro/test/04.sgc rename to patacrep/songs/chordpro/test/04.sgc.source diff --git a/patacrep/songs/chordpro/test/05.txt b/patacrep/songs/chordpro/test/05.sgc.sgc similarity index 100% rename from patacrep/songs/chordpro/test/05.txt rename to patacrep/songs/chordpro/test/05.sgc.sgc diff --git a/patacrep/songs/chordpro/test/05.sgc b/patacrep/songs/chordpro/test/05.sgc.source similarity index 100% rename from patacrep/songs/chordpro/test/05.sgc rename to patacrep/songs/chordpro/test/05.sgc.source diff --git a/patacrep/songs/chordpro/test/06.txt b/patacrep/songs/chordpro/test/06.sgc.sgc similarity index 100% rename from patacrep/songs/chordpro/test/06.txt rename to patacrep/songs/chordpro/test/06.sgc.sgc diff --git a/patacrep/songs/chordpro/test/06.sgc b/patacrep/songs/chordpro/test/06.sgc.source similarity index 100% rename from patacrep/songs/chordpro/test/06.sgc rename to patacrep/songs/chordpro/test/06.sgc.source diff --git a/patacrep/songs/chordpro/test/07.txt b/patacrep/songs/chordpro/test/07.sgc.sgc similarity index 100% rename from patacrep/songs/chordpro/test/07.txt rename to patacrep/songs/chordpro/test/07.sgc.sgc diff --git a/patacrep/songs/chordpro/test/07.sgc b/patacrep/songs/chordpro/test/07.sgc.source similarity index 100% rename from patacrep/songs/chordpro/test/07.sgc rename to patacrep/songs/chordpro/test/07.sgc.source diff --git a/patacrep/songs/chordpro/test/08.txt b/patacrep/songs/chordpro/test/08.sgc.sgc similarity index 100% rename from patacrep/songs/chordpro/test/08.txt rename to patacrep/songs/chordpro/test/08.sgc.sgc diff --git a/patacrep/songs/chordpro/test/08.sgc b/patacrep/songs/chordpro/test/08.sgc.source similarity index 100% rename from patacrep/songs/chordpro/test/08.sgc rename to patacrep/songs/chordpro/test/08.sgc.source diff --git a/patacrep/songs/chordpro/test/09.txt b/patacrep/songs/chordpro/test/09.sgc.sgc similarity index 100% rename from patacrep/songs/chordpro/test/09.txt rename to patacrep/songs/chordpro/test/09.sgc.sgc diff --git a/patacrep/songs/chordpro/test/09.sgc b/patacrep/songs/chordpro/test/09.sgc.source similarity index 100% rename from patacrep/songs/chordpro/test/09.sgc rename to patacrep/songs/chordpro/test/09.sgc.source diff --git a/patacrep/songs/chordpro/test/10.txt b/patacrep/songs/chordpro/test/10.sgc.sgc similarity index 100% rename from patacrep/songs/chordpro/test/10.txt rename to patacrep/songs/chordpro/test/10.sgc.sgc diff --git a/patacrep/songs/chordpro/test/10.sgc b/patacrep/songs/chordpro/test/10.sgc.source similarity index 100% rename from patacrep/songs/chordpro/test/10.sgc rename to patacrep/songs/chordpro/test/10.sgc.source diff --git a/patacrep/songs/chordpro/test/11.txt b/patacrep/songs/chordpro/test/11.sgc.sgc similarity index 100% rename from patacrep/songs/chordpro/test/11.txt rename to patacrep/songs/chordpro/test/11.sgc.sgc diff --git a/patacrep/songs/chordpro/test/11.sgc b/patacrep/songs/chordpro/test/11.sgc.source similarity index 100% rename from patacrep/songs/chordpro/test/11.sgc rename to patacrep/songs/chordpro/test/11.sgc.source diff --git a/patacrep/songs/chordpro/test/12.txt b/patacrep/songs/chordpro/test/12.sgc.sgc similarity index 100% rename from patacrep/songs/chordpro/test/12.txt rename to patacrep/songs/chordpro/test/12.sgc.sgc diff --git a/patacrep/songs/chordpro/test/12.sgc b/patacrep/songs/chordpro/test/12.sgc.source similarity index 100% rename from patacrep/songs/chordpro/test/12.sgc rename to patacrep/songs/chordpro/test/12.sgc.source diff --git a/patacrep/songs/chordpro/test/13.txt b/patacrep/songs/chordpro/test/13.sgc.sgc similarity index 100% rename from patacrep/songs/chordpro/test/13.txt rename to patacrep/songs/chordpro/test/13.sgc.sgc diff --git a/patacrep/songs/chordpro/test/13.sgc b/patacrep/songs/chordpro/test/13.sgc.source similarity index 100% rename from patacrep/songs/chordpro/test/13.sgc rename to patacrep/songs/chordpro/test/13.sgc.source diff --git a/patacrep/songs/chordpro/test/21.txt b/patacrep/songs/chordpro/test/21.sgc.sgc similarity index 100% rename from patacrep/songs/chordpro/test/21.txt rename to patacrep/songs/chordpro/test/21.sgc.sgc diff --git a/patacrep/songs/chordpro/test/21.sgc b/patacrep/songs/chordpro/test/21.sgc.source similarity index 100% rename from patacrep/songs/chordpro/test/21.sgc rename to patacrep/songs/chordpro/test/21.sgc.source diff --git a/patacrep/songs/chordpro/test/22.txt b/patacrep/songs/chordpro/test/22.sgc.sgc similarity index 100% rename from patacrep/songs/chordpro/test/22.txt rename to patacrep/songs/chordpro/test/22.sgc.sgc diff --git a/patacrep/songs/chordpro/test/22.sgc b/patacrep/songs/chordpro/test/22.sgc.source similarity index 100% rename from patacrep/songs/chordpro/test/22.sgc rename to patacrep/songs/chordpro/test/22.sgc.source diff --git a/patacrep/songs/chordpro/test/23.txt b/patacrep/songs/chordpro/test/23.sgc.sgc similarity index 100% rename from patacrep/songs/chordpro/test/23.txt rename to patacrep/songs/chordpro/test/23.sgc.sgc diff --git a/patacrep/songs/chordpro/test/23.sgc b/patacrep/songs/chordpro/test/23.sgc.source similarity index 100% rename from patacrep/songs/chordpro/test/23.sgc rename to patacrep/songs/chordpro/test/23.sgc.source diff --git a/patacrep/songs/chordpro/test/24.txt b/patacrep/songs/chordpro/test/24.sgc.sgc similarity index 100% rename from patacrep/songs/chordpro/test/24.txt rename to patacrep/songs/chordpro/test/24.sgc.sgc diff --git a/patacrep/songs/chordpro/test/24.sgc b/patacrep/songs/chordpro/test/24.sgc.source similarity index 100% rename from patacrep/songs/chordpro/test/24.sgc rename to patacrep/songs/chordpro/test/24.sgc.source diff --git a/patacrep/songs/chordpro/test/25.txt b/patacrep/songs/chordpro/test/25.sgc.sgc similarity index 100% rename from patacrep/songs/chordpro/test/25.txt rename to patacrep/songs/chordpro/test/25.sgc.sgc diff --git a/patacrep/songs/chordpro/test/25.sgc b/patacrep/songs/chordpro/test/25.sgc.source similarity index 100% rename from patacrep/songs/chordpro/test/25.sgc rename to patacrep/songs/chordpro/test/25.sgc.source diff --git a/patacrep/songs/chordpro/test/26.txt b/patacrep/songs/chordpro/test/26.sgc.sgc similarity index 100% rename from patacrep/songs/chordpro/test/26.txt rename to patacrep/songs/chordpro/test/26.sgc.sgc diff --git a/patacrep/songs/chordpro/test/26.sgc b/patacrep/songs/chordpro/test/26.sgc.source similarity index 100% rename from patacrep/songs/chordpro/test/26.sgc rename to patacrep/songs/chordpro/test/26.sgc.source diff --git a/patacrep/songs/chordpro/test/27.txt b/patacrep/songs/chordpro/test/27.sgc.sgc similarity index 100% rename from patacrep/songs/chordpro/test/27.txt rename to patacrep/songs/chordpro/test/27.sgc.sgc diff --git a/patacrep/songs/chordpro/test/27.sgc b/patacrep/songs/chordpro/test/27.sgc.source similarity index 100% rename from patacrep/songs/chordpro/test/27.sgc rename to patacrep/songs/chordpro/test/27.sgc.source diff --git a/patacrep/songs/chordpro/test/28.txt b/patacrep/songs/chordpro/test/28.sgc.sgc similarity index 100% rename from patacrep/songs/chordpro/test/28.txt rename to patacrep/songs/chordpro/test/28.sgc.sgc diff --git a/patacrep/songs/chordpro/test/28.sgc b/patacrep/songs/chordpro/test/28.sgc.source similarity index 100% rename from patacrep/songs/chordpro/test/28.sgc rename to patacrep/songs/chordpro/test/28.sgc.source diff --git a/patacrep/songs/chordpro/test/29.txt b/patacrep/songs/chordpro/test/29.sgc.sgc similarity index 100% rename from patacrep/songs/chordpro/test/29.txt rename to patacrep/songs/chordpro/test/29.sgc.sgc diff --git a/patacrep/songs/chordpro/test/29.sgc b/patacrep/songs/chordpro/test/29.sgc.source similarity index 100% rename from patacrep/songs/chordpro/test/29.sgc rename to patacrep/songs/chordpro/test/29.sgc.source 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.txt b/patacrep/songs/chordpro/test/chords.sgc.sgc similarity index 100% rename from patacrep/songs/chordpro/test/chords.txt rename to patacrep/songs/chordpro/test/chords.sgc.sgc diff --git a/patacrep/songs/chordpro/test/chords.sgc b/patacrep/songs/chordpro/test/chords.sgc.source similarity index 100% rename from patacrep/songs/chordpro/test/chords.sgc rename to patacrep/songs/chordpro/test/chords.sgc.source diff --git a/patacrep/songs/chordpro/test/customchords.txt b/patacrep/songs/chordpro/test/customchords.sgc.sgc similarity index 100% rename from patacrep/songs/chordpro/test/customchords.txt rename to patacrep/songs/chordpro/test/customchords.sgc.sgc diff --git a/patacrep/songs/chordpro/test/customchords.sgc b/patacrep/songs/chordpro/test/customchords.sgc.source similarity index 100% rename from patacrep/songs/chordpro/test/customchords.sgc rename to patacrep/songs/chordpro/test/customchords.sgc.source diff --git a/patacrep/songs/chordpro/test/greensleeves.txt b/patacrep/songs/chordpro/test/greensleeves.sgc.sgc similarity index 100% rename from patacrep/songs/chordpro/test/greensleeves.txt rename to patacrep/songs/chordpro/test/greensleeves.sgc.sgc diff --git a/patacrep/songs/chordpro/test/greensleeves.sgc b/patacrep/songs/chordpro/test/greensleeves.sgc.source similarity index 100% rename from patacrep/songs/chordpro/test/greensleeves.sgc rename to patacrep/songs/chordpro/test/greensleeves.sgc.source diff --git a/patacrep/songs/chordpro/test/invalid_chord.txt b/patacrep/songs/chordpro/test/invalid_chord.sgc.sgc similarity index 100% rename from patacrep/songs/chordpro/test/invalid_chord.txt rename to patacrep/songs/chordpro/test/invalid_chord.sgc.sgc diff --git a/patacrep/songs/chordpro/test/invalid_chord.sgc b/patacrep/songs/chordpro/test/invalid_chord.sgc.source similarity index 100% rename from patacrep/songs/chordpro/test/invalid_chord.sgc rename to patacrep/songs/chordpro/test/invalid_chord.sgc.source diff --git a/patacrep/songs/chordpro/test/invalid_customchord.txt b/patacrep/songs/chordpro/test/invalid_customchord.sgc.sgc similarity index 100% rename from patacrep/songs/chordpro/test/invalid_customchord.txt rename to patacrep/songs/chordpro/test/invalid_customchord.sgc.sgc diff --git a/patacrep/songs/chordpro/test/invalid_customchord.sgc b/patacrep/songs/chordpro/test/invalid_customchord.sgc.source similarity index 100% rename from patacrep/songs/chordpro/test/invalid_customchord.sgc rename to patacrep/songs/chordpro/test/invalid_customchord.sgc.source diff --git a/patacrep/songs/chordpro/test/metadata.txt b/patacrep/songs/chordpro/test/metadata.sgc.sgc similarity index 100% rename from patacrep/songs/chordpro/test/metadata.txt rename to patacrep/songs/chordpro/test/metadata.sgc.sgc diff --git a/patacrep/songs/chordpro/test/metadata.sgc b/patacrep/songs/chordpro/test/metadata.sgc.source similarity index 100% rename from patacrep/songs/chordpro/test/metadata.sgc rename to patacrep/songs/chordpro/test/metadata.sgc.source diff --git a/patacrep/songs/chordpro/test/test_parser.py b/patacrep/songs/chordpro/test/test_parser.py index 2fc89ca6..669610a9 100644 --- a/patacrep/songs/chordpro/test/test_parser.py +++ b/patacrep/songs/chordpro/test/test_parser.py @@ -11,49 +11,33 @@ from patacrep.songs.chordpro import ChordproSong from patacrep.test import disable_logging -class ParserTxtRenderer(unittest.TestCase): - """Test parser, and renderer as a txt file.""" +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 + def test_all(self): config = DEFAULT_CONFIG.copy() config.update({ 'encoding': 'utf8', '_compiled_authwords': {}, }) - with open("{}.txt".format(self.basename), 'r', encoding='utf8') as expectfile: - chordproname = "{}.sgc".format(self.basename) - with disable_logging(): - self.assertMultiLineEqual( - ChordproSong(None, chordproname, config).render( - output=chordproname, - output_format="chordpro", - ).strip(), - expectfile.read().replace( - "DIRNAME", - os.path.dirname(self.basename), - ).strip(), - ) - -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 + for source in sorted(glob.glob(os.path.join( + os.path.dirname(__file__), + '*.source', + ))): + base = source[:-len(".source")] + with open("{}.sgc".format(base), 'r', encoding='utf8') as expectfile: + chordproname = "{}.source".format(base) + with disable_logging(): + with self.subTest(base=os.path.basename(base)): + self.assertMultiLineEqual( + ChordproSong(None, chordproname, config).render( + output=chordproname, + output_format="chordpro", + ).strip(), + expectfile.read().replace( + "DIRNAME", + os.path.dirname(base), + ).strip(), + ) From a8aaf654f975b43d6f657706e7fc4e0828a69476 Mon Sep 17 00:00:00 2001 From: Louis Date: Sat, 29 Aug 2015 11:51:13 +0200 Subject: [PATCH 17/32] Configuration option `_compiled_authwords` is no longer required --- patacrep/songs/__init__.py | 2 +- patacrep/songs/chordpro/test/test_parser.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/patacrep/songs/__init__.py b/patacrep/songs/__init__.py index c1af76e7..cbc5d9aa 100644 --- a/patacrep/songs/__init__.py +++ b/patacrep/songs/__init__.py @@ -143,7 +143,7 @@ class Song: ] self.authors = process_listauthors( self.authors, - **config["_compiled_authwords"] + **config.get("_compiled_authwords", {}) ) # Cache management diff --git a/patacrep/songs/chordpro/test/test_parser.py b/patacrep/songs/chordpro/test/test_parser.py index 669610a9..394e9966 100644 --- a/patacrep/songs/chordpro/test/test_parser.py +++ b/patacrep/songs/chordpro/test/test_parser.py @@ -20,7 +20,6 @@ class TestParsingRendering(unittest.TestCase): config = DEFAULT_CONFIG.copy() config.update({ 'encoding': 'utf8', - '_compiled_authwords': {}, }) for source in sorted(glob.glob(os.path.join( os.path.dirname(__file__), From 333581e6fa5435b1336f87971fda689f9798497b Mon Sep 17 00:00:00 2001 From: Louis Date: Sat, 29 Aug 2015 12:42:57 +0200 Subject: [PATCH 18/32] Added initial value for OrderedLifoDict class --- patacrep/songs/chordpro/ast.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/patacrep/songs/chordpro/ast.py b/patacrep/songs/chordpro/ast.py index 0e68f6dc..8dcea1a7 100644 --- a/patacrep/songs/chordpro/ast.py +++ b/patacrep/songs/chordpro/ast.py @@ -16,9 +16,13 @@ class OrderedLifoDict: - LIFO: the last item is reterned first when iterating. """ - def __init__(self): - self._keys = [] - self._values = {} + 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`.""" @@ -36,7 +40,6 @@ class OrderedLifoDict: 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')]) From d00fcad19e2a60d027f904c0854f979c38008745 Mon Sep 17 00:00:00 2001 From: Louis Date: Sat, 29 Aug 2015 12:43:35 +0200 Subject: [PATCH 19/32] [chordpro] Firsts LaTeX tests --- patacrep/content/song.py | 12 ++++++- patacrep/songs/chordpro/data/latex/song | 14 +++----- patacrep/songs/chordpro/test/02.sgc.tex | 10 ++++++ patacrep/songs/chordpro/test/test_parser.py | 36 +++++++++++++-------- 4 files changed, 48 insertions(+), 24 deletions(-) create mode 100644 patacrep/songs/chordpro/test/02.sgc.tex diff --git a/patacrep/content/song.py b/patacrep/content/song.py index 4f8cd8f4..9a1b4635 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.render(output=context['filename'], output_format="latex") + 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/songs/chordpro/data/latex/song b/patacrep/songs/chordpro/data/latex/song index a4f4d9ca..4664d52f 100644 --- a/patacrep/songs/chordpro/data/latex/song +++ b/patacrep/songs/chordpro/data/latex/song @@ -1,12 +1,10 @@ - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% ((path)) - (* if language is defined -*) \selectlanguage{((language))} (* endif *) + +(*- if metadata.columns is defined *) \songcolumns{(( metadata.columns ))} +(* endif *) \beginsong{ (*- for title in titles -*) @@ -33,9 +31,9 @@ (* if (metadata.cov is defined) or (metadata.vcov is defined) *) \cover -(* endif -*) +(* endif *) -(* for chord in metadata['define'] *) +(*- for chord in metadata['define'] *) (( render(chord) )) (* endfor *) @@ -44,5 +42,3 @@ (* endfor *) \endsong -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - diff --git a/patacrep/songs/chordpro/test/02.sgc.tex b/patacrep/songs/chordpro/test/02.sgc.tex new file mode 100644 index 00000000..b3ec6f17 --- /dev/null +++ b/patacrep/songs/chordpro/test/02.sgc.tex @@ -0,0 +1,10 @@ +\selectlanguage{english} + +\beginsong{A directive}[ + by={ + }, +] + + + +\endsong diff --git a/patacrep/songs/chordpro/test/test_parser.py b/patacrep/songs/chordpro/test/test_parser.py index 394e9966..32216d47 100644 --- a/patacrep/songs/chordpro/test/test_parser.py +++ b/patacrep/songs/chordpro/test/test_parser.py @@ -10,6 +10,10 @@ from patacrep.build import DEFAULT_CONFIG from patacrep.songs.chordpro import ChordproSong from patacrep.test import disable_logging +LANGUAGES = { + 'tex': 'latex', + 'sgc': 'chordpro', +} class TestParsingRendering(unittest.TestCase): """Test parsing and rendering""" @@ -26,17 +30,21 @@ class TestParsingRendering(unittest.TestCase): '*.source', ))): base = source[:-len(".source")] - with open("{}.sgc".format(base), 'r', encoding='utf8') as expectfile: - chordproname = "{}.source".format(base) - with disable_logging(): - with self.subTest(base=os.path.basename(base)): - self.assertMultiLineEqual( - ChordproSong(None, chordproname, config).render( - output=chordproname, - output_format="chordpro", - ).strip(), - expectfile.read().replace( - "DIRNAME", - os.path.dirname(base), - ).strip(), - ) + 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) + 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().replace( + "DIRNAME", + os.path.dirname(base), + ).strip(), + ) From 549b546fb2f397392eba88978160a63bf1974ca3 Mon Sep 17 00:00:00 2001 From: Louis Date: Sun, 30 Aug 2015 15:31:57 +0200 Subject: [PATCH 20/32] Pylint --- patacrep/content/song.py | 8 ++++---- patacrep/songs/chordpro/test/test_parser.py | 6 ++++++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/patacrep/content/song.py b/patacrep/content/song.py index 9a1b4635..b44fc7f1 100755 --- a/patacrep/content/song.py +++ b/patacrep/content/song.py @@ -41,10 +41,10 @@ class SongRenderer(Content): {song} """).format( - separator="%"*80, - path=self.song.subpath, - song=self.song.render(output=context['filename'], output_format="latex"), - ) + 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/songs/chordpro/test/test_parser.py b/patacrep/songs/chordpro/test/test_parser.py index 32216d47..26e5181a 100644 --- a/patacrep/songs/chordpro/test/test_parser.py +++ b/patacrep/songs/chordpro/test/test_parser.py @@ -21,6 +21,12 @@ class TestParsingRendering(unittest.TestCase): maxDiff = None 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', From 75d2e5c66fb00e39d71ff68d68213baa7bbc7eb3 Mon Sep 17 00:00:00 2001 From: Louis Date: Sun, 30 Aug 2015 15:33:52 +0200 Subject: [PATCH 21/32] [chordpro][test] Changed naming scheme of test files --- patacrep/songs/chordpro/test/{00.sgc.sgc => 00.sgc} | 0 patacrep/songs/chordpro/test/{00.sgc.source => 00.source} | 0 patacrep/songs/chordpro/test/{01.sgc.sgc => 01.sgc} | 0 patacrep/songs/chordpro/test/{01.sgc.source => 01.source} | 0 patacrep/songs/chordpro/test/{02.sgc.sgc => 02.sgc} | 0 patacrep/songs/chordpro/test/{02.sgc.source => 02.source} | 0 patacrep/songs/chordpro/test/{02.sgc.tex => 02.tex} | 0 patacrep/songs/chordpro/test/{03.sgc.sgc => 03.sgc} | 0 patacrep/songs/chordpro/test/{03.sgc.source => 03.source} | 0 patacrep/songs/chordpro/test/{04.sgc.sgc => 04.sgc} | 0 patacrep/songs/chordpro/test/{04.sgc.source => 04.source} | 0 patacrep/songs/chordpro/test/{05.sgc.sgc => 05.sgc} | 0 patacrep/songs/chordpro/test/{05.sgc.source => 05.source} | 0 patacrep/songs/chordpro/test/{06.sgc.sgc => 06.sgc} | 0 patacrep/songs/chordpro/test/{06.sgc.source => 06.source} | 0 patacrep/songs/chordpro/test/{07.sgc.sgc => 07.sgc} | 0 patacrep/songs/chordpro/test/{07.sgc.source => 07.source} | 0 patacrep/songs/chordpro/test/{08.sgc.sgc => 08.sgc} | 0 patacrep/songs/chordpro/test/{08.sgc.source => 08.source} | 0 patacrep/songs/chordpro/test/{09.sgc.sgc => 09.sgc} | 0 patacrep/songs/chordpro/test/{09.sgc.source => 09.source} | 0 patacrep/songs/chordpro/test/{10.sgc.sgc => 10.sgc} | 0 patacrep/songs/chordpro/test/{10.sgc.source => 10.source} | 0 patacrep/songs/chordpro/test/{11.sgc.sgc => 11.sgc} | 0 patacrep/songs/chordpro/test/{11.sgc.source => 11.source} | 0 patacrep/songs/chordpro/test/{12.sgc.sgc => 12.sgc} | 0 patacrep/songs/chordpro/test/{12.sgc.source => 12.source} | 0 patacrep/songs/chordpro/test/{13.sgc.sgc => 13.sgc} | 0 patacrep/songs/chordpro/test/{13.sgc.source => 13.source} | 0 patacrep/songs/chordpro/test/{21.sgc.sgc => 21.sgc} | 0 patacrep/songs/chordpro/test/{21.sgc.source => 21.source} | 0 patacrep/songs/chordpro/test/{22.sgc.sgc => 22.sgc} | 0 patacrep/songs/chordpro/test/{22.sgc.source => 22.source} | 0 patacrep/songs/chordpro/test/{23.sgc.sgc => 23.sgc} | 0 patacrep/songs/chordpro/test/{23.sgc.source => 23.source} | 0 patacrep/songs/chordpro/test/{24.sgc.sgc => 24.sgc} | 0 patacrep/songs/chordpro/test/{24.sgc.source => 24.source} | 0 patacrep/songs/chordpro/test/{25.sgc.sgc => 25.sgc} | 0 patacrep/songs/chordpro/test/{25.sgc.source => 25.source} | 0 patacrep/songs/chordpro/test/{26.sgc.sgc => 26.sgc} | 0 patacrep/songs/chordpro/test/{26.sgc.source => 26.source} | 0 patacrep/songs/chordpro/test/{27.sgc.sgc => 27.sgc} | 0 patacrep/songs/chordpro/test/{27.sgc.source => 27.source} | 0 patacrep/songs/chordpro/test/{28.sgc.sgc => 28.sgc} | 0 patacrep/songs/chordpro/test/{28.sgc.source => 28.source} | 0 patacrep/songs/chordpro/test/{29.sgc.sgc => 29.sgc} | 0 patacrep/songs/chordpro/test/{29.sgc.source => 29.source} | 0 patacrep/songs/chordpro/test/{chords.sgc.sgc => chords.sgc} | 0 patacrep/songs/chordpro/test/{chords.sgc.source => chords.source} | 0 .../chordpro/test/{customchords.sgc.sgc => customchords.sgc} | 0 .../test/{customchords.sgc.source => customchords.source} | 0 .../chordpro/test/{greensleeves.sgc.sgc => greensleeves.sgc} | 0 .../test/{greensleeves.sgc.source => greensleeves.source} | 0 .../chordpro/test/{invalid_chord.sgc.sgc => invalid_chord.sgc} | 0 .../test/{invalid_chord.sgc.source => invalid_chord.source} | 0 .../test/{invalid_customchord.sgc.sgc => invalid_customchord.sgc} | 0 ...{invalid_customchord.sgc.source => invalid_customchord.source} | 0 patacrep/songs/chordpro/test/{metadata.sgc.sgc => metadata.sgc} | 0 .../songs/chordpro/test/{metadata.sgc.source => metadata.source} | 0 59 files changed, 0 insertions(+), 0 deletions(-) rename patacrep/songs/chordpro/test/{00.sgc.sgc => 00.sgc} (100%) rename patacrep/songs/chordpro/test/{00.sgc.source => 00.source} (100%) rename patacrep/songs/chordpro/test/{01.sgc.sgc => 01.sgc} (100%) rename patacrep/songs/chordpro/test/{01.sgc.source => 01.source} (100%) rename patacrep/songs/chordpro/test/{02.sgc.sgc => 02.sgc} (100%) rename patacrep/songs/chordpro/test/{02.sgc.source => 02.source} (100%) rename patacrep/songs/chordpro/test/{02.sgc.tex => 02.tex} (100%) rename patacrep/songs/chordpro/test/{03.sgc.sgc => 03.sgc} (100%) rename patacrep/songs/chordpro/test/{03.sgc.source => 03.source} (100%) rename patacrep/songs/chordpro/test/{04.sgc.sgc => 04.sgc} (100%) rename patacrep/songs/chordpro/test/{04.sgc.source => 04.source} (100%) rename patacrep/songs/chordpro/test/{05.sgc.sgc => 05.sgc} (100%) rename patacrep/songs/chordpro/test/{05.sgc.source => 05.source} (100%) rename patacrep/songs/chordpro/test/{06.sgc.sgc => 06.sgc} (100%) rename patacrep/songs/chordpro/test/{06.sgc.source => 06.source} (100%) rename patacrep/songs/chordpro/test/{07.sgc.sgc => 07.sgc} (100%) rename patacrep/songs/chordpro/test/{07.sgc.source => 07.source} (100%) rename patacrep/songs/chordpro/test/{08.sgc.sgc => 08.sgc} (100%) rename patacrep/songs/chordpro/test/{08.sgc.source => 08.source} (100%) rename patacrep/songs/chordpro/test/{09.sgc.sgc => 09.sgc} (100%) rename patacrep/songs/chordpro/test/{09.sgc.source => 09.source} (100%) rename patacrep/songs/chordpro/test/{10.sgc.sgc => 10.sgc} (100%) rename patacrep/songs/chordpro/test/{10.sgc.source => 10.source} (100%) rename patacrep/songs/chordpro/test/{11.sgc.sgc => 11.sgc} (100%) rename patacrep/songs/chordpro/test/{11.sgc.source => 11.source} (100%) rename patacrep/songs/chordpro/test/{12.sgc.sgc => 12.sgc} (100%) rename patacrep/songs/chordpro/test/{12.sgc.source => 12.source} (100%) rename patacrep/songs/chordpro/test/{13.sgc.sgc => 13.sgc} (100%) rename patacrep/songs/chordpro/test/{13.sgc.source => 13.source} (100%) rename patacrep/songs/chordpro/test/{21.sgc.sgc => 21.sgc} (100%) rename patacrep/songs/chordpro/test/{21.sgc.source => 21.source} (100%) rename patacrep/songs/chordpro/test/{22.sgc.sgc => 22.sgc} (100%) rename patacrep/songs/chordpro/test/{22.sgc.source => 22.source} (100%) rename patacrep/songs/chordpro/test/{23.sgc.sgc => 23.sgc} (100%) rename patacrep/songs/chordpro/test/{23.sgc.source => 23.source} (100%) rename patacrep/songs/chordpro/test/{24.sgc.sgc => 24.sgc} (100%) rename patacrep/songs/chordpro/test/{24.sgc.source => 24.source} (100%) rename patacrep/songs/chordpro/test/{25.sgc.sgc => 25.sgc} (100%) rename patacrep/songs/chordpro/test/{25.sgc.source => 25.source} (100%) rename patacrep/songs/chordpro/test/{26.sgc.sgc => 26.sgc} (100%) rename patacrep/songs/chordpro/test/{26.sgc.source => 26.source} (100%) rename patacrep/songs/chordpro/test/{27.sgc.sgc => 27.sgc} (100%) rename patacrep/songs/chordpro/test/{27.sgc.source => 27.source} (100%) rename patacrep/songs/chordpro/test/{28.sgc.sgc => 28.sgc} (100%) rename patacrep/songs/chordpro/test/{28.sgc.source => 28.source} (100%) rename patacrep/songs/chordpro/test/{29.sgc.sgc => 29.sgc} (100%) rename patacrep/songs/chordpro/test/{29.sgc.source => 29.source} (100%) rename patacrep/songs/chordpro/test/{chords.sgc.sgc => chords.sgc} (100%) rename patacrep/songs/chordpro/test/{chords.sgc.source => chords.source} (100%) rename patacrep/songs/chordpro/test/{customchords.sgc.sgc => customchords.sgc} (100%) rename patacrep/songs/chordpro/test/{customchords.sgc.source => customchords.source} (100%) rename patacrep/songs/chordpro/test/{greensleeves.sgc.sgc => greensleeves.sgc} (100%) rename patacrep/songs/chordpro/test/{greensleeves.sgc.source => greensleeves.source} (100%) rename patacrep/songs/chordpro/test/{invalid_chord.sgc.sgc => invalid_chord.sgc} (100%) rename patacrep/songs/chordpro/test/{invalid_chord.sgc.source => invalid_chord.source} (100%) rename patacrep/songs/chordpro/test/{invalid_customchord.sgc.sgc => invalid_customchord.sgc} (100%) rename patacrep/songs/chordpro/test/{invalid_customchord.sgc.source => invalid_customchord.source} (100%) rename patacrep/songs/chordpro/test/{metadata.sgc.sgc => metadata.sgc} (100%) rename patacrep/songs/chordpro/test/{metadata.sgc.source => metadata.source} (100%) diff --git a/patacrep/songs/chordpro/test/00.sgc.sgc b/patacrep/songs/chordpro/test/00.sgc similarity index 100% rename from patacrep/songs/chordpro/test/00.sgc.sgc rename to patacrep/songs/chordpro/test/00.sgc diff --git a/patacrep/songs/chordpro/test/00.sgc.source b/patacrep/songs/chordpro/test/00.source similarity index 100% rename from patacrep/songs/chordpro/test/00.sgc.source rename to patacrep/songs/chordpro/test/00.source diff --git a/patacrep/songs/chordpro/test/01.sgc.sgc b/patacrep/songs/chordpro/test/01.sgc similarity index 100% rename from patacrep/songs/chordpro/test/01.sgc.sgc rename to patacrep/songs/chordpro/test/01.sgc diff --git a/patacrep/songs/chordpro/test/01.sgc.source b/patacrep/songs/chordpro/test/01.source similarity index 100% rename from patacrep/songs/chordpro/test/01.sgc.source rename to patacrep/songs/chordpro/test/01.source diff --git a/patacrep/songs/chordpro/test/02.sgc.sgc b/patacrep/songs/chordpro/test/02.sgc similarity index 100% rename from patacrep/songs/chordpro/test/02.sgc.sgc rename to patacrep/songs/chordpro/test/02.sgc diff --git a/patacrep/songs/chordpro/test/02.sgc.source b/patacrep/songs/chordpro/test/02.source similarity index 100% rename from patacrep/songs/chordpro/test/02.sgc.source rename to patacrep/songs/chordpro/test/02.source diff --git a/patacrep/songs/chordpro/test/02.sgc.tex b/patacrep/songs/chordpro/test/02.tex similarity index 100% rename from patacrep/songs/chordpro/test/02.sgc.tex rename to patacrep/songs/chordpro/test/02.tex diff --git a/patacrep/songs/chordpro/test/03.sgc.sgc b/patacrep/songs/chordpro/test/03.sgc similarity index 100% rename from patacrep/songs/chordpro/test/03.sgc.sgc rename to patacrep/songs/chordpro/test/03.sgc diff --git a/patacrep/songs/chordpro/test/03.sgc.source b/patacrep/songs/chordpro/test/03.source similarity index 100% rename from patacrep/songs/chordpro/test/03.sgc.source rename to patacrep/songs/chordpro/test/03.source diff --git a/patacrep/songs/chordpro/test/04.sgc.sgc b/patacrep/songs/chordpro/test/04.sgc similarity index 100% rename from patacrep/songs/chordpro/test/04.sgc.sgc rename to patacrep/songs/chordpro/test/04.sgc diff --git a/patacrep/songs/chordpro/test/04.sgc.source b/patacrep/songs/chordpro/test/04.source similarity index 100% rename from patacrep/songs/chordpro/test/04.sgc.source rename to patacrep/songs/chordpro/test/04.source diff --git a/patacrep/songs/chordpro/test/05.sgc.sgc b/patacrep/songs/chordpro/test/05.sgc similarity index 100% rename from patacrep/songs/chordpro/test/05.sgc.sgc rename to patacrep/songs/chordpro/test/05.sgc diff --git a/patacrep/songs/chordpro/test/05.sgc.source b/patacrep/songs/chordpro/test/05.source similarity index 100% rename from patacrep/songs/chordpro/test/05.sgc.source rename to patacrep/songs/chordpro/test/05.source diff --git a/patacrep/songs/chordpro/test/06.sgc.sgc b/patacrep/songs/chordpro/test/06.sgc similarity index 100% rename from patacrep/songs/chordpro/test/06.sgc.sgc rename to patacrep/songs/chordpro/test/06.sgc diff --git a/patacrep/songs/chordpro/test/06.sgc.source b/patacrep/songs/chordpro/test/06.source similarity index 100% rename from patacrep/songs/chordpro/test/06.sgc.source rename to patacrep/songs/chordpro/test/06.source diff --git a/patacrep/songs/chordpro/test/07.sgc.sgc b/patacrep/songs/chordpro/test/07.sgc similarity index 100% rename from patacrep/songs/chordpro/test/07.sgc.sgc rename to patacrep/songs/chordpro/test/07.sgc diff --git a/patacrep/songs/chordpro/test/07.sgc.source b/patacrep/songs/chordpro/test/07.source similarity index 100% rename from patacrep/songs/chordpro/test/07.sgc.source rename to patacrep/songs/chordpro/test/07.source diff --git a/patacrep/songs/chordpro/test/08.sgc.sgc b/patacrep/songs/chordpro/test/08.sgc similarity index 100% rename from patacrep/songs/chordpro/test/08.sgc.sgc rename to patacrep/songs/chordpro/test/08.sgc diff --git a/patacrep/songs/chordpro/test/08.sgc.source b/patacrep/songs/chordpro/test/08.source similarity index 100% rename from patacrep/songs/chordpro/test/08.sgc.source rename to patacrep/songs/chordpro/test/08.source diff --git a/patacrep/songs/chordpro/test/09.sgc.sgc b/patacrep/songs/chordpro/test/09.sgc similarity index 100% rename from patacrep/songs/chordpro/test/09.sgc.sgc rename to patacrep/songs/chordpro/test/09.sgc diff --git a/patacrep/songs/chordpro/test/09.sgc.source b/patacrep/songs/chordpro/test/09.source similarity index 100% rename from patacrep/songs/chordpro/test/09.sgc.source rename to patacrep/songs/chordpro/test/09.source diff --git a/patacrep/songs/chordpro/test/10.sgc.sgc b/patacrep/songs/chordpro/test/10.sgc similarity index 100% rename from patacrep/songs/chordpro/test/10.sgc.sgc rename to patacrep/songs/chordpro/test/10.sgc diff --git a/patacrep/songs/chordpro/test/10.sgc.source b/patacrep/songs/chordpro/test/10.source similarity index 100% rename from patacrep/songs/chordpro/test/10.sgc.source rename to patacrep/songs/chordpro/test/10.source diff --git a/patacrep/songs/chordpro/test/11.sgc.sgc b/patacrep/songs/chordpro/test/11.sgc similarity index 100% rename from patacrep/songs/chordpro/test/11.sgc.sgc rename to patacrep/songs/chordpro/test/11.sgc diff --git a/patacrep/songs/chordpro/test/11.sgc.source b/patacrep/songs/chordpro/test/11.source similarity index 100% rename from patacrep/songs/chordpro/test/11.sgc.source rename to patacrep/songs/chordpro/test/11.source diff --git a/patacrep/songs/chordpro/test/12.sgc.sgc b/patacrep/songs/chordpro/test/12.sgc similarity index 100% rename from patacrep/songs/chordpro/test/12.sgc.sgc rename to patacrep/songs/chordpro/test/12.sgc diff --git a/patacrep/songs/chordpro/test/12.sgc.source b/patacrep/songs/chordpro/test/12.source similarity index 100% rename from patacrep/songs/chordpro/test/12.sgc.source rename to patacrep/songs/chordpro/test/12.source diff --git a/patacrep/songs/chordpro/test/13.sgc.sgc b/patacrep/songs/chordpro/test/13.sgc similarity index 100% rename from patacrep/songs/chordpro/test/13.sgc.sgc rename to patacrep/songs/chordpro/test/13.sgc diff --git a/patacrep/songs/chordpro/test/13.sgc.source b/patacrep/songs/chordpro/test/13.source similarity index 100% rename from patacrep/songs/chordpro/test/13.sgc.source rename to patacrep/songs/chordpro/test/13.source diff --git a/patacrep/songs/chordpro/test/21.sgc.sgc b/patacrep/songs/chordpro/test/21.sgc similarity index 100% rename from patacrep/songs/chordpro/test/21.sgc.sgc rename to patacrep/songs/chordpro/test/21.sgc diff --git a/patacrep/songs/chordpro/test/21.sgc.source b/patacrep/songs/chordpro/test/21.source similarity index 100% rename from patacrep/songs/chordpro/test/21.sgc.source rename to patacrep/songs/chordpro/test/21.source diff --git a/patacrep/songs/chordpro/test/22.sgc.sgc b/patacrep/songs/chordpro/test/22.sgc similarity index 100% rename from patacrep/songs/chordpro/test/22.sgc.sgc rename to patacrep/songs/chordpro/test/22.sgc diff --git a/patacrep/songs/chordpro/test/22.sgc.source b/patacrep/songs/chordpro/test/22.source similarity index 100% rename from patacrep/songs/chordpro/test/22.sgc.source rename to patacrep/songs/chordpro/test/22.source diff --git a/patacrep/songs/chordpro/test/23.sgc.sgc b/patacrep/songs/chordpro/test/23.sgc similarity index 100% rename from patacrep/songs/chordpro/test/23.sgc.sgc rename to patacrep/songs/chordpro/test/23.sgc diff --git a/patacrep/songs/chordpro/test/23.sgc.source b/patacrep/songs/chordpro/test/23.source similarity index 100% rename from patacrep/songs/chordpro/test/23.sgc.source rename to patacrep/songs/chordpro/test/23.source diff --git a/patacrep/songs/chordpro/test/24.sgc.sgc b/patacrep/songs/chordpro/test/24.sgc similarity index 100% rename from patacrep/songs/chordpro/test/24.sgc.sgc rename to patacrep/songs/chordpro/test/24.sgc diff --git a/patacrep/songs/chordpro/test/24.sgc.source b/patacrep/songs/chordpro/test/24.source similarity index 100% rename from patacrep/songs/chordpro/test/24.sgc.source rename to patacrep/songs/chordpro/test/24.source diff --git a/patacrep/songs/chordpro/test/25.sgc.sgc b/patacrep/songs/chordpro/test/25.sgc similarity index 100% rename from patacrep/songs/chordpro/test/25.sgc.sgc rename to patacrep/songs/chordpro/test/25.sgc diff --git a/patacrep/songs/chordpro/test/25.sgc.source b/patacrep/songs/chordpro/test/25.source similarity index 100% rename from patacrep/songs/chordpro/test/25.sgc.source rename to patacrep/songs/chordpro/test/25.source diff --git a/patacrep/songs/chordpro/test/26.sgc.sgc b/patacrep/songs/chordpro/test/26.sgc similarity index 100% rename from patacrep/songs/chordpro/test/26.sgc.sgc rename to patacrep/songs/chordpro/test/26.sgc diff --git a/patacrep/songs/chordpro/test/26.sgc.source b/patacrep/songs/chordpro/test/26.source similarity index 100% rename from patacrep/songs/chordpro/test/26.sgc.source rename to patacrep/songs/chordpro/test/26.source diff --git a/patacrep/songs/chordpro/test/27.sgc.sgc b/patacrep/songs/chordpro/test/27.sgc similarity index 100% rename from patacrep/songs/chordpro/test/27.sgc.sgc rename to patacrep/songs/chordpro/test/27.sgc diff --git a/patacrep/songs/chordpro/test/27.sgc.source b/patacrep/songs/chordpro/test/27.source similarity index 100% rename from patacrep/songs/chordpro/test/27.sgc.source rename to patacrep/songs/chordpro/test/27.source diff --git a/patacrep/songs/chordpro/test/28.sgc.sgc b/patacrep/songs/chordpro/test/28.sgc similarity index 100% rename from patacrep/songs/chordpro/test/28.sgc.sgc rename to patacrep/songs/chordpro/test/28.sgc diff --git a/patacrep/songs/chordpro/test/28.sgc.source b/patacrep/songs/chordpro/test/28.source similarity index 100% rename from patacrep/songs/chordpro/test/28.sgc.source rename to patacrep/songs/chordpro/test/28.source diff --git a/patacrep/songs/chordpro/test/29.sgc.sgc b/patacrep/songs/chordpro/test/29.sgc similarity index 100% rename from patacrep/songs/chordpro/test/29.sgc.sgc rename to patacrep/songs/chordpro/test/29.sgc diff --git a/patacrep/songs/chordpro/test/29.sgc.source b/patacrep/songs/chordpro/test/29.source similarity index 100% rename from patacrep/songs/chordpro/test/29.sgc.source rename to patacrep/songs/chordpro/test/29.source diff --git a/patacrep/songs/chordpro/test/chords.sgc.sgc b/patacrep/songs/chordpro/test/chords.sgc similarity index 100% rename from patacrep/songs/chordpro/test/chords.sgc.sgc rename to patacrep/songs/chordpro/test/chords.sgc diff --git a/patacrep/songs/chordpro/test/chords.sgc.source b/patacrep/songs/chordpro/test/chords.source similarity index 100% rename from patacrep/songs/chordpro/test/chords.sgc.source rename to patacrep/songs/chordpro/test/chords.source diff --git a/patacrep/songs/chordpro/test/customchords.sgc.sgc b/patacrep/songs/chordpro/test/customchords.sgc similarity index 100% rename from patacrep/songs/chordpro/test/customchords.sgc.sgc rename to patacrep/songs/chordpro/test/customchords.sgc diff --git a/patacrep/songs/chordpro/test/customchords.sgc.source b/patacrep/songs/chordpro/test/customchords.source similarity index 100% rename from patacrep/songs/chordpro/test/customchords.sgc.source rename to patacrep/songs/chordpro/test/customchords.source diff --git a/patacrep/songs/chordpro/test/greensleeves.sgc.sgc b/patacrep/songs/chordpro/test/greensleeves.sgc similarity index 100% rename from patacrep/songs/chordpro/test/greensleeves.sgc.sgc rename to patacrep/songs/chordpro/test/greensleeves.sgc diff --git a/patacrep/songs/chordpro/test/greensleeves.sgc.source b/patacrep/songs/chordpro/test/greensleeves.source similarity index 100% rename from patacrep/songs/chordpro/test/greensleeves.sgc.source rename to patacrep/songs/chordpro/test/greensleeves.source diff --git a/patacrep/songs/chordpro/test/invalid_chord.sgc.sgc b/patacrep/songs/chordpro/test/invalid_chord.sgc similarity index 100% rename from patacrep/songs/chordpro/test/invalid_chord.sgc.sgc rename to patacrep/songs/chordpro/test/invalid_chord.sgc diff --git a/patacrep/songs/chordpro/test/invalid_chord.sgc.source b/patacrep/songs/chordpro/test/invalid_chord.source similarity index 100% rename from patacrep/songs/chordpro/test/invalid_chord.sgc.source rename to patacrep/songs/chordpro/test/invalid_chord.source diff --git a/patacrep/songs/chordpro/test/invalid_customchord.sgc.sgc b/patacrep/songs/chordpro/test/invalid_customchord.sgc similarity index 100% rename from patacrep/songs/chordpro/test/invalid_customchord.sgc.sgc rename to patacrep/songs/chordpro/test/invalid_customchord.sgc diff --git a/patacrep/songs/chordpro/test/invalid_customchord.sgc.source b/patacrep/songs/chordpro/test/invalid_customchord.source similarity index 100% rename from patacrep/songs/chordpro/test/invalid_customchord.sgc.source rename to patacrep/songs/chordpro/test/invalid_customchord.source diff --git a/patacrep/songs/chordpro/test/metadata.sgc.sgc b/patacrep/songs/chordpro/test/metadata.sgc similarity index 100% rename from patacrep/songs/chordpro/test/metadata.sgc.sgc rename to patacrep/songs/chordpro/test/metadata.sgc diff --git a/patacrep/songs/chordpro/test/metadata.sgc.source b/patacrep/songs/chordpro/test/metadata.source similarity index 100% rename from patacrep/songs/chordpro/test/metadata.sgc.source rename to patacrep/songs/chordpro/test/metadata.source From dccb057f2e4280f857095cb8ac8ceb39edb135ce Mon Sep 17 00:00:00 2001 From: Louis Date: Mon, 31 Aug 2015 22:23:24 +0200 Subject: [PATCH 22/32] [chordpro][test] Added a bunch of LaTeX tests --- .../chordpro/data/latex/content_chordlist | 2 + .../chordpro/data/latex/content_tablature | 4 ++ .../songs/chordpro/data/latex/content_verse | 6 +- patacrep/songs/chordpro/data/latex/song | 2 +- patacrep/songs/chordpro/test/00.tex | 10 +++ patacrep/songs/chordpro/test/01.tex | 13 ++++ patacrep/songs/chordpro/test/03.tex | 12 ++++ patacrep/songs/chordpro/test/04.tex | 13 ++++ patacrep/songs/chordpro/test/05.tex | 13 ++++ patacrep/songs/chordpro/test/06.tex | 12 ++++ patacrep/songs/chordpro/test/07.tex | 13 ++++ patacrep/songs/chordpro/test/08.tex | 17 +++++ patacrep/songs/chordpro/test/09.tex | 17 +++++ patacrep/songs/chordpro/test/10.tex | 13 ++++ patacrep/songs/chordpro/test/11.tex | 13 ++++ patacrep/songs/chordpro/test/12.tex | 13 ++++ patacrep/songs/chordpro/test/13.tex | 15 +++++ patacrep/songs/chordpro/test/21.tex | 13 ++++ patacrep/songs/chordpro/test/22.tex | 10 +++ patacrep/songs/chordpro/test/23.tex | 12 ++++ patacrep/songs/chordpro/test/24.tex | 13 ++++ patacrep/songs/chordpro/test/25.tex | 13 ++++ patacrep/songs/chordpro/test/26.tex | 12 ++++ patacrep/songs/chordpro/test/27.tex | 13 ++++ patacrep/songs/chordpro/test/28.tex | 17 +++++ patacrep/songs/chordpro/test/29.tex | 17 +++++ patacrep/songs/chordpro/test/chords.tex | 25 +++++++ patacrep/songs/chordpro/test/customchords.tex | 12 ++++ patacrep/songs/chordpro/test/greensleeves.tex | 67 +++++++++++++++++++ .../songs/chordpro/test/invalid_chord.tex | 15 +++++ .../chordpro/test/invalid_customchord.tex | 10 +++ patacrep/songs/chordpro/test/metadata.tex | 25 +++++++ 32 files changed, 458 insertions(+), 4 deletions(-) create mode 100644 patacrep/songs/chordpro/data/latex/content_tablature create mode 100644 patacrep/songs/chordpro/test/00.tex create mode 100644 patacrep/songs/chordpro/test/01.tex create mode 100644 patacrep/songs/chordpro/test/03.tex create mode 100644 patacrep/songs/chordpro/test/04.tex create mode 100644 patacrep/songs/chordpro/test/05.tex create mode 100644 patacrep/songs/chordpro/test/06.tex create mode 100644 patacrep/songs/chordpro/test/07.tex create mode 100644 patacrep/songs/chordpro/test/08.tex create mode 100644 patacrep/songs/chordpro/test/09.tex create mode 100644 patacrep/songs/chordpro/test/10.tex create mode 100644 patacrep/songs/chordpro/test/11.tex create mode 100644 patacrep/songs/chordpro/test/12.tex create mode 100644 patacrep/songs/chordpro/test/13.tex create mode 100644 patacrep/songs/chordpro/test/21.tex create mode 100644 patacrep/songs/chordpro/test/22.tex create mode 100644 patacrep/songs/chordpro/test/23.tex create mode 100644 patacrep/songs/chordpro/test/24.tex create mode 100644 patacrep/songs/chordpro/test/25.tex create mode 100644 patacrep/songs/chordpro/test/26.tex create mode 100644 patacrep/songs/chordpro/test/27.tex create mode 100644 patacrep/songs/chordpro/test/28.tex create mode 100644 patacrep/songs/chordpro/test/29.tex create mode 100644 patacrep/songs/chordpro/test/chords.tex create mode 100644 patacrep/songs/chordpro/test/customchords.tex create mode 100644 patacrep/songs/chordpro/test/greensleeves.tex create mode 100644 patacrep/songs/chordpro/test/invalid_chord.tex create mode 100644 patacrep/songs/chordpro/test/invalid_customchord.tex create mode 100644 patacrep/songs/chordpro/test/metadata.tex diff --git a/patacrep/songs/chordpro/data/latex/content_chordlist b/patacrep/songs/chordpro/data/latex/content_chordlist index d5ad7c3c..5ff3fa6b 100644 --- a/patacrep/songs/chordpro/data/latex/content_chordlist +++ b/patacrep/songs/chordpro/data/latex/content_chordlist @@ -1,6 +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_tablature b/patacrep/songs/chordpro/data/latex/content_tablature new file mode 100644 index 00000000..e4036783 --- /dev/null +++ b/patacrep/songs/chordpro/data/latex/content_tablature @@ -0,0 +1,4 @@ +% TODO TABLATURE +% (* for foo in content.content *) +% (( foo )) +% (* endfor *) diff --git a/patacrep/songs/chordpro/data/latex/content_verse b/patacrep/songs/chordpro/data/latex/content_verse index ac169e98..b6065a7f 100644 --- a/patacrep/songs/chordpro/data/latex/content_verse +++ b/patacrep/songs/chordpro/data/latex/content_verse @@ -1,5 +1,5 @@ \begin{(( content.type ))} - (* for line in content.lines -*) - (( render(line) )) - (* endfor *) + (* for line in content.lines *) + (( render(line) )) + (* endfor *) \end{(( content.type ))} diff --git a/patacrep/songs/chordpro/data/latex/song b/patacrep/songs/chordpro/data/latex/song index 4664d52f..ccc2742a 100644 --- a/patacrep/songs/chordpro/data/latex/song +++ b/patacrep/songs/chordpro/data/latex/song @@ -33,7 +33,7 @@ \cover (* endif *) -(*- for chord in metadata['define'] *) +(*- for chord in metadata['define'] -*) (( render(chord) )) (* endfor *) 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/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/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/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/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/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/07.tex b/patacrep/songs/chordpro/test/07.tex new file mode 100644 index 00000000..6b8b48c7 --- /dev/null +++ b/patacrep/songs/chordpro/test/07.tex @@ -0,0 +1,13 @@ +\selectlanguage{english} + +\beginsong{}[ + by={ + }, +] + + +% TODO TABLATURE +% % A tab +% + +\endsong 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/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/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/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/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/13.tex b/patacrep/songs/chordpro/test/13.tex new file mode 100644 index 00000000..18ed8f96 --- /dev/null +++ b/patacrep/songs/chordpro/test/13.tex @@ -0,0 +1,15 @@ +\selectlanguage{english} + +\beginsong{}[ + by={ + }, +] + + +% TODO TABLATURE +% % A table +% % wit many # weir [ +% % [ symbols +% + +\endsong 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/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/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/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/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/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/27.tex b/patacrep/songs/chordpro/test/27.tex new file mode 100644 index 00000000..6b8b48c7 --- /dev/null +++ b/patacrep/songs/chordpro/test/27.tex @@ -0,0 +1,13 @@ +\selectlanguage{english} + +\beginsong{}[ + by={ + }, +] + + +% TODO TABLATURE +% % A tab +% + +\endsong 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/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/chords.tex b/patacrep/songs/chordpro/test/chords.tex new file mode 100644 index 00000000..9bb98002 --- /dev/null +++ b/patacrep/songs/chordpro/test/chords.tex @@ -0,0 +1,25 @@ +\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 +\end{verse} + +\endsong diff --git a/patacrep/songs/chordpro/test/customchords.tex b/patacrep/songs/chordpro/test/customchords.tex new file mode 100644 index 00000000..3f2000b2 --- /dev/null +++ b/patacrep/songs/chordpro/test/customchords.tex @@ -0,0 +1,12 @@ +\selectlanguage{english} + +\beginsong{}[ + by={ + }, +] + +\gtab{E4}{7:0133XX} +\gtab{E5}{7:0133XX:012300} + + +\endsong diff --git a/patacrep/songs/chordpro/test/greensleeves.tex b/patacrep/songs/chordpro/test/greensleeves.tex new file mode 100644 index 00000000..4c2aac43 --- /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={DIRNAME/traditionnel}, +] + +\cover + + + +\lilypond{DIRNAME/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/invalid_chord.tex b/patacrep/songs/chordpro/test/invalid_chord.tex new file mode 100644 index 00000000..8e874988 --- /dev/null +++ b/patacrep/songs/chordpro/test/invalid_chord.tex @@ -0,0 +1,15 @@ +\selectlanguage{english} + +\beginsong{}[ + by={ + }, +] + + +\begin{verse} + This is invalid. + This \[A]too. + And as well. +\end{verse} + +\endsong 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.tex b/patacrep/songs/chordpro/test/metadata.tex new file mode 100644 index 00000000..6bb1f6eb --- /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={DIRNAME/Cover}, + vcov={VCover}, +] + +\cover + +\textnote{Comment} +\musicnote{GuitarComment} +\image{DIRNAME/Image} +\lilypond{DIRNAME/Lilypond} + +\endsong From 882967afda9e175c2b107de89eb738930d08eb5a Mon Sep 17 00:00:00 2001 From: Louis Date: Mon, 31 Aug 2015 22:35:21 +0200 Subject: [PATCH 23/32] rdpro] Extra, custom keys are correctly rendered --- patacrep/songs/chordpro/data/latex/song | 3 +++ patacrep/songs/chordpro/test/metadata.tex | 1 + 2 files changed, 4 insertions(+) diff --git a/patacrep/songs/chordpro/data/latex/song b/patacrep/songs/chordpro/data/latex/song index ccc2742a..eaa2a86d 100644 --- a/patacrep/songs/chordpro/data/latex/song +++ b/patacrep/songs/chordpro/data/latex/song @@ -27,6 +27,9 @@ (( key ))={(( metadata[key] ))}, (* endif *) (* endfor *) + (* for key in metadata.keys *) + (( key.keyword ))={(( key.argument ))}, + (* endfor *) ] (* if (metadata.cov is defined) or (metadata.vcov is defined) *) diff --git a/patacrep/songs/chordpro/test/metadata.tex b/patacrep/songs/chordpro/test/metadata.tex index 6bb1f6eb..fbe53fae 100644 --- a/patacrep/songs/chordpro/test/metadata.tex +++ b/patacrep/songs/chordpro/test/metadata.tex @@ -13,6 +13,7 @@ Subtitle5}[ copyright={Copyright}, cov={DIRNAME/Cover}, vcov={VCover}, + foo={Foo}, ] \cover From 6e62c1abfd626a03e157c69ecddcd7568d2ce499 Mon Sep 17 00:00:00 2001 From: Louis Date: Tue, 1 Sep 2015 18:11:46 +0200 Subject: [PATCH 24/32] Got rid of `vcover`: cover (and image and lilypond partition) is looked for in the right place Closes #81 --- patacrep/build.py | 1 + patacrep/data/examples/example-subdir.sb | 17 +++++++++ patacrep/data/examples/img/datadir.ly | 19 +++++++++ patacrep/data/examples/img/datadir.png | Bin 0 -> 645 bytes patacrep/data/examples/root.ly | 19 +++++++++ patacrep/data/examples/root.png | Bin 0 -> 513 bytes .../data/examples/songs/subdir/datadir.sg | 10 +++++ .../data/examples/songs/subdir/datadir.sgc | 6 +++ .../data/examples/songs/subdir/relative.ly | 19 +++++++++ .../data/examples/songs/subdir/relative.png | Bin 0 -> 645 bytes .../data/examples/songs/subdir/relative.sg | 10 +++++ .../data/examples/songs/subdir/relative.sgc | 6 +++ patacrep/data/examples/songs/subdir/root.sg | 10 +++++ patacrep/data/examples/songs/subdir/root.sgc | 6 +++ patacrep/data/latex/patacrep.sty | 10 +---- patacrep/songs/__init__.py | 36 ++++++++++++++++++ patacrep/songs/chordpro/__init__.py | 4 +- patacrep/songs/chordpro/ast.py | 27 ------------- patacrep/songs/chordpro/data/chordpro/song | 2 +- .../songs/chordpro/data/latex/content_image | 2 +- .../chordpro/data/latex/content_partition | 2 +- patacrep/songs/chordpro/data/latex/song | 7 +++- patacrep/songs/chordpro/test/greensleeves.sgc | 4 +- patacrep/songs/chordpro/test/greensleeves.tex | 4 +- patacrep/songs/chordpro/test/metadata.sgc | 7 ++-- patacrep/songs/chordpro/test/metadata.source | 1 - patacrep/songs/chordpro/test/metadata.tex | 7 ++-- patacrep/songs/chordpro/test/test_parser.py | 6 +-- patacrep/songs/latex/__init__.py | 17 +++++---- 29 files changed, 194 insertions(+), 65 deletions(-) create mode 100644 patacrep/data/examples/example-subdir.sb create mode 100644 patacrep/data/examples/img/datadir.ly create mode 100644 patacrep/data/examples/img/datadir.png create mode 100644 patacrep/data/examples/root.ly create mode 100644 patacrep/data/examples/root.png create mode 100644 patacrep/data/examples/songs/subdir/datadir.sg create mode 100644 patacrep/data/examples/songs/subdir/datadir.sgc create mode 100644 patacrep/data/examples/songs/subdir/relative.ly create mode 100644 patacrep/data/examples/songs/subdir/relative.png create mode 100644 patacrep/data/examples/songs/subdir/relative.sg create mode 100644 patacrep/data/examples/songs/subdir/relative.sgc create mode 100644 patacrep/data/examples/songs/subdir/root.sg create mode 100644 patacrep/data/examples/songs/subdir/root.sgc diff --git a/patacrep/build.py b/patacrep/build.py index 679fc82b..5682da1d 100644 --- a/patacrep/build.py +++ b/patacrep/build.py @@ -33,6 +33,7 @@ DEFAULT_CONFIG = { 'content': [], 'titleprefixwords': [], 'encoding': None, + 'datadir': [], } 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 0000000000000000000000000000000000000000..e2efe4090f86b7660f3979865031caf604943e82 GIT binary patch literal 645 zcmV;00($+4P)e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00HeuL_t(o!|j+mO9Md^g+D=! zk6u5d!KDu&}aJEJS>P5BveP`U@;X$PWD82DHh`zW|hgmKs8I)z$j94YA93oOiWN z)l2;=z|RZ6V{n_oEz}UAtFG3+>&9{hbZVRGl=@SE&kH|daDBi}l}F!pJy%_=f0qzn zfU#QMQ4>->H@K|D(ITr@Pot~xZ~Hi>js~*Xf~%R%Hgz^L#gIeKp7p+Jk5SPb#600000NkvXXu0mjfLbVnn literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..70ea3b7c9a4ed2d588df4d3a04ea3cffc8434609 GIT binary patch literal 513 zcmV+c0{;DpP)e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00C)9L_t(o!|j&6N(3w;dZ>1O^`8K$=ir za8kcm0FD*AwQOt#=ok1^pb2Ea3UDK?FKwvLb+bxczar)o`?l!!#64?MCYr#DG`kUe z(UW?!=r6^sd*ZJ|^*gcX-^I;)=ImGwrLHe1DRW#oHZT@H<(ab~%{YQD zT2i0DnnPda#M?FhR6FEPO6FUc%EV@U1yPk!+hBm|()O?HBSFERGZPo8d z<=8|f&Q<-Y`l408hDvV^>{u3m6?d&3lc~2XD`x9Ab$!v2LJQ@e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00HeuL_t(o!|j*7OB_KQhMz6M zX(C#PCI&5SLg2vCO3^C)6(Wj)A4wOB5Rl|gNFjo);1?-^t@e`RFsGzB8@>NP{2;k- z5zX1W2g9+q+4W}DW?op>eShzMJv%cy172QUUS4Ua*0B8s3cy5ya~ij>Y+Pl4bKnAK zOL*UA&(U~%tm9n7bL5mcdf3wy3F94ftwfh7%V4 zVEmnf6u_><0K4W0Y<)~U1b%3L%oW%tz=`oCU4rcZt~GBQh?rAe1J4|Q4S-W4Q*P3j ztbhd=mw%;2L#scpX4`y%RnVLRumB&8%(A7WeB@2PskZA7Y%#&Qz32$+bKnNJ1zy?$ f>*eL; Date: Wed, 2 Sep 2015 10:27:17 +0200 Subject: [PATCH 25/32] [chordpro] Accepting + and * in chords References patacrep/patadata#18 --- patacrep/songs/chordpro/ast.py | 2 ++ patacrep/songs/chordpro/data/chordpro/content_chord | 1 + patacrep/songs/chordpro/data/latex/content_chord | 1 + patacrep/songs/chordpro/lexer.py | 2 +- patacrep/songs/chordpro/syntax.py | 5 +++-- patacrep/songs/chordpro/test/chords.sgc | 2 ++ patacrep/songs/chordpro/test/chords.source | 2 ++ patacrep/songs/chordpro/test/chords.tex | 2 ++ patacrep/songs/chordpro/test/customchords.sgc | 2 ++ patacrep/songs/chordpro/test/customchords.source | 2 ++ patacrep/songs/chordpro/test/customchords.tex | 2 ++ patacrep/songs/chordpro/test/invalid_chord.source | 2 +- 12 files changed, 21 insertions(+), 4 deletions(-) diff --git a/patacrep/songs/chordpro/ast.py b/patacrep/songs/chordpro/ast.py index 1aaae349..178e09ba 100644 --- a/patacrep/songs/chordpro/ast.py +++ b/patacrep/songs/chordpro/ast.py @@ -153,6 +153,7 @@ class Chord(AST): addnote=None, basskey=None, bassalteration=None, + star=None, ): # pylint: disable=too-many-arguments self.key = key @@ -161,6 +162,7 @@ class Chord(AST): self.addnote = addnote self.basskey = basskey self.bassalteration = bassalteration + self.star = star class Verse(AST): """A verse (or bridge, or chorus)""" diff --git a/patacrep/songs/chordpro/data/chordpro/content_chord b/patacrep/songs/chordpro/data/chordpro/content_chord index 6fce5be6..99e0d4c4 100644 --- a/patacrep/songs/chordpro/data/chordpro/content_chord +++ b/patacrep/songs/chordpro/data/chordpro/content_chord @@ -6,4 +6,5 @@ / ((- content.basskey -)) (* if content.bassalteration *)(( content.bassalteration ))(* endif -*) +(* if content.star *)*(* endif -*) (* endif -*) diff --git a/patacrep/songs/chordpro/data/latex/content_chord b/patacrep/songs/chordpro/data/latex/content_chord index 29a1cc30..406b75fe 100644 --- a/patacrep/songs/chordpro/data/latex/content_chord +++ b/patacrep/songs/chordpro/data/latex/content_chord @@ -8,4 +8,5 @@ ((- content.basskey -)) (* if content.bassalteration == '#' *)#(* endif -*) (* if content.bassalteration == 'b' *)&(* endif -*) +(* if content.star *)*(* endif -*) (* endif -*) diff --git a/patacrep/songs/chordpro/lexer.py b/patacrep/songs/chordpro/lexer.py index 813c42b0..6d47bea8 100644 --- a/patacrep/songs/chordpro/lexer.py +++ b/patacrep/songs/chordpro/lexer.py @@ -39,7 +39,7 @@ class ChordProLexer: t_SPACE = r'[ \t]+' - t_chord_CHORD = r'[A-G#bmajdisus2-9/ ]+' + t_chord_CHORD = r'[A-G#bmajdisus+*2-9/ ]+' t_directive_SPACE = r'[ \t]+' t_directive_KEYWORD = r'[a-zA-Z_]+' diff --git a/patacrep/songs/chordpro/syntax.py b/patacrep/songs/chordpro/syntax.py index 1e1420bc..89264f68 100644 --- a/patacrep/songs/chordpro/syntax.py +++ b/patacrep/songs/chordpro/syntax.py @@ -12,13 +12,14 @@ CHORD_RE = re.compile( ^ (?P[A-G]) (?P[b#])? - (?P(maj|sus|dim|m))? + (?P(maj|sus|dim|m|\+))? (?P[2-9])? ( / (?P[A-G]) (?P[b#])? )? + (?P\*)? $ """, re.VERBOSE @@ -223,7 +224,7 @@ class ChordproParser(Parser): def p_chord(self, symbols): """chord : CHORD""" - symbols[0] = ast.ChordList(*self._parse_chords(symbols[1], symbols=symbols)) + symbols[0] = ast.ChordList(*list(self._parse_chords(symbols[1], symbols=symbols))) @staticmethod def p_chorus(symbols): diff --git a/patacrep/songs/chordpro/test/chords.sgc b/patacrep/songs/chordpro/test/chords.sgc index 955f44d6..942a0223 100644 --- a/patacrep/songs/chordpro/test/chords.sgc +++ b/patacrep/songs/chordpro/test/chords.sgc @@ -14,4 +14,6 @@ [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 index 84397df2..a4803589 100644 --- a/patacrep/songs/chordpro/test/chords.source +++ b/patacrep/songs/chordpro/test/chords.source @@ -11,3 +11,5 @@ [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 index 9bb98002..a621a7cd 100644 --- a/patacrep/songs/chordpro/test/chords.tex +++ b/patacrep/songs/chordpro/test/chords.tex @@ -20,6 +20,8 @@ \[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 index 1148a901..3357bb96 100644 --- a/patacrep/songs/chordpro/test/customchords.sgc +++ b/patacrep/songs/chordpro/test/customchords.sgc @@ -1,3 +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 index b7192c87..4c6734cc 100644 --- a/patacrep/songs/chordpro/test/customchords.source +++ b/patacrep/songs/chordpro/test/customchords.source @@ -1,2 +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 index 3f2000b2..80f13c9a 100644 --- a/patacrep/songs/chordpro/test/customchords.tex +++ b/patacrep/songs/chordpro/test/customchords.tex @@ -7,6 +7,8 @@ \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/invalid_chord.source b/patacrep/songs/chordpro/test/invalid_chord.source index 872697b3..7df0d1f9 100644 --- a/patacrep/songs/chordpro/test/invalid_chord.source +++ b/patacrep/songs/chordpro/test/invalid_chord.source @@ -1,3 +1,3 @@ This is [H] invalid. -This [A+]too. +This [A@]too. And [Amm]as well. From bc00b5e44908cdf3ee4867b620c13176aafc2093 Mon Sep 17 00:00:00 2001 From: Louis Date: Wed, 2 Sep 2015 11:08:46 +0200 Subject: [PATCH 26/32] [chordpro] corrected error in example --- patacrep/data/examples/songs/greensleeves.sgc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 From 821030dba5a6eae935f171f79827c3b884dbed07 Mon Sep 17 00:00:00 2001 From: Louis Date: Wed, 2 Sep 2015 13:16:13 +0200 Subject: [PATCH 27/32] [chordpro] Chords parsing is less strict --- patacrep/songs/chordpro/ast.py | 19 +------- .../chordpro/data/chordpro/content_chord | 11 +---- .../songs/chordpro/data/latex/content_chord | 13 +---- patacrep/songs/chordpro/lexer.py | 2 +- patacrep/songs/chordpro/syntax.py | 48 ++++--------------- .../songs/chordpro/test/invalid_chord.sgc | 2 - .../songs/chordpro/test/invalid_chord.source | 4 +- .../songs/chordpro/test/invalid_chord.tex | 2 - .../chordpro/test/invalid_customchord.source | 6 +-- 9 files changed, 17 insertions(+), 90 deletions(-) diff --git a/patacrep/songs/chordpro/ast.py b/patacrep/songs/chordpro/ast.py index 178e09ba..5cffbb86 100644 --- a/patacrep/songs/chordpro/ast.py +++ b/patacrep/songs/chordpro/ast.py @@ -145,24 +145,9 @@ class Chord(AST): _template = "chord" - def __init__( - self, - key, - alteration=None, - modifier=None, - addnote=None, - basskey=None, - bassalteration=None, - star=None, - ): + def __init__(self, chord): # pylint: disable=too-many-arguments - self.key = key - self.alteration = alteration - self.modifier = modifier - self.addnote = addnote - self.basskey = basskey - self.bassalteration = bassalteration - self.star = star + self.chord = chord class Verse(AST): """A verse (or bridge, or chorus)""" diff --git a/patacrep/songs/chordpro/data/chordpro/content_chord b/patacrep/songs/chordpro/data/chordpro/content_chord index 99e0d4c4..7d5ec6ca 100644 --- a/patacrep/songs/chordpro/data/chordpro/content_chord +++ b/patacrep/songs/chordpro/data/chordpro/content_chord @@ -1,10 +1 @@ -((- content.key -)) -(* if content.alteration *)(( content.alteration ))(* endif -*) -(* if content.modifier *)((content.modifier))(* endif -*) -(* if content.addnote *)((content.addnote))(* endif -*) -(* if content.basskey -*) - / - ((- content.basskey -)) - (* if content.bassalteration *)(( content.bassalteration ))(* endif -*) -(* if content.star *)*(* endif -*) -(* endif -*) +((- content.chord -)) diff --git a/patacrep/songs/chordpro/data/latex/content_chord b/patacrep/songs/chordpro/data/latex/content_chord index 406b75fe..61b51c8a 100644 --- a/patacrep/songs/chordpro/data/latex/content_chord +++ b/patacrep/songs/chordpro/data/latex/content_chord @@ -1,12 +1 @@ -((- content.key -)) -(* if content.alteration == '#' *)#(* endif -*) -(* if content.alteration == 'b' *)&(* endif -*) -(* if content.modifier *)((content.modifier))(* endif -*) -(* if content.addnote *)((content.addnote))(* endif -*) -(* if content.basskey -*) - / - ((- content.basskey -)) - (* if content.bassalteration == '#' *)#(* endif -*) - (* if content.bassalteration == 'b' *)&(* endif -*) -(* if content.star *)*(* endif -*) -(* endif -*) +((- content.chord|replace("b", "&") -)) diff --git a/patacrep/songs/chordpro/lexer.py b/patacrep/songs/chordpro/lexer.py index 6d47bea8..aba37a1c 100644 --- a/patacrep/songs/chordpro/lexer.py +++ b/patacrep/songs/chordpro/lexer.py @@ -39,7 +39,7 @@ class ChordProLexer: t_SPACE = r'[ \t]+' - t_chord_CHORD = r'[A-G#bmajdisus+*2-9/ ]+' + t_chord_CHORD = r'[^\]]+' t_directive_SPACE = r'[ \t]+' t_directive_KEYWORD = r'[a-zA-Z_]+' diff --git a/patacrep/songs/chordpro/syntax.py b/patacrep/songs/chordpro/syntax.py index 89264f68..80baf66f 100644 --- a/patacrep/songs/chordpro/syntax.py +++ b/patacrep/songs/chordpro/syntax.py @@ -7,24 +7,6 @@ from patacrep.songs.syntax import Parser from patacrep.songs.chordpro import ast from patacrep.songs.chordpro.lexer import tokens, ChordProLexer -CHORD_RE = re.compile( - r""" - ^ - (?P[A-G]) - (?P[b#])? - (?P(maj|sus|dim|m|\+))? - (?P[2-9])? - ( - / - (?P[A-G]) - (?P[b#])? - )? - (?P\*)? - $ - """, - re.VERBOSE - ) - class ChordproParser(Parser): """ChordPro parser class""" # pylint: disable=too-many-public-methods @@ -69,17 +51,17 @@ class ChordproParser(Parser): """ symbols[0] = None - def _parse_define(self, groups, *, symbols): + @staticmethod + 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 - key = list(self._parse_chords(groups['key'], symbols=symbols)) - if len(key) != 1: + if not groups['key'].strip(): return None else: - key = key[0] + key = ast.Chord(groups['key'].strip()) if groups['basefret'] is None: basefret = None @@ -151,7 +133,7 @@ class ChordproParser(Parser): symbols[0] = ast.Error() return - symbols[0] = self._parse_define(match.groupdict(), symbols=symbols) + symbols[0] = self._parse_define(match.groupdict()) if symbols[0] is None: self.error( line=symbols.lexer.lineno, @@ -207,24 +189,10 @@ class ChordproParser(Parser): """space : SPACE""" symbols[0] = ast.Space() - def _parse_chords(self, string, *, symbols): - """Parse a list of chords. - - Iterate over :class:`ast.Chord` objects. - """ - for chord in string.split(): - match = CHORD_RE.match(chord) - if match is None: - self.error( - line=symbols.lexer.lineno, - message="Invalid chord '{}'.".format(chord), - ) - continue - yield ast.Chord(**match.groupdict()) - - def p_chord(self, symbols): + @staticmethod + def p_chord(symbols): """chord : CHORD""" - symbols[0] = ast.ChordList(*list(self._parse_chords(symbols[1], symbols=symbols))) + 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/invalid_chord.sgc b/patacrep/songs/chordpro/test/invalid_chord.sgc index 2a17e6e7..7ec4fd65 100644 --- a/patacrep/songs/chordpro/test/invalid_chord.sgc +++ b/patacrep/songs/chordpro/test/invalid_chord.sgc @@ -2,6 +2,4 @@ {start_of_verse} This is invalid. - This [A]too. - And []as well. {end_of_verse} diff --git a/patacrep/songs/chordpro/test/invalid_chord.source b/patacrep/songs/chordpro/test/invalid_chord.source index 7df0d1f9..0e63a90b 100644 --- a/patacrep/songs/chordpro/test/invalid_chord.source +++ b/patacrep/songs/chordpro/test/invalid_chord.source @@ -1,3 +1 @@ -This is [H] invalid. -This [A@]too. -And [Amm]as well. +This is [] invalid. diff --git a/patacrep/songs/chordpro/test/invalid_chord.tex b/patacrep/songs/chordpro/test/invalid_chord.tex index 8e874988..476d776a 100644 --- a/patacrep/songs/chordpro/test/invalid_chord.tex +++ b/patacrep/songs/chordpro/test/invalid_chord.tex @@ -8,8 +8,6 @@ \begin{verse} This is invalid. - This \[A]too. - And as well. \end{verse} \endsong diff --git a/patacrep/songs/chordpro/test/invalid_customchord.source b/patacrep/songs/chordpro/test/invalid_customchord.source index 9754318f..d0baf679 100644 --- a/patacrep/songs/chordpro/test/invalid_customchord.source +++ b/patacrep/songs/chordpro/test/invalid_customchord.source @@ -1,5 +1,5 @@ {define : } -{define: H base-fret 7 frets 0 1 3 3 x x} -{define: E4 base-fret H frets 0 1 3 3 x x} -{define: E4 base-fret 7 frets 0 1 3 3 x A} +{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} From 4b7f98a9a68b494a8a68250d5fe40e78e79f2e09 Mon Sep 17 00:00:00 2001 From: Oliverpool Date: Tue, 8 Sep 2015 21:17:56 +0200 Subject: [PATCH 28/32] Allow capital 'X' when string is not played --- patacrep/songs/chordpro/syntax.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/patacrep/songs/chordpro/syntax.py b/patacrep/songs/chordpro/syntax.py index 80baf66f..582bae41 100644 --- a/patacrep/songs/chordpro/syntax.py +++ b/patacrep/songs/chordpro/syntax.py @@ -73,7 +73,7 @@ class ChordproParser(Parser): else: frets = [] for fret in groups['frets'].split(): - if fret == "x": + if fret in "xX": frets.append(None) else: frets.append(int(fret)) @@ -112,7 +112,7 @@ class ChordproParser(Parser): ^ (?P[^\ ]*)\ * (base-fret\ *(?P[2-9]))?\ * - frets\ *(?P((\d+|x)\ *)+)\ * + frets\ *(?P((\d+|x|X)\ *)+)\ * (fingers\ *(?P(([0-4-])\ *)*))? $ """, From 429442ad6f2b471a6fd24e41a5323a16dc4b7706 Mon Sep 17 00:00:00 2001 From: Oliverpool Date: Tue, 8 Sep 2015 21:22:44 +0200 Subject: [PATCH 29/32] base-fret can be any number greater than 1 (included) --- patacrep/songs/chordpro/syntax.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patacrep/songs/chordpro/syntax.py b/patacrep/songs/chordpro/syntax.py index 582bae41..ee0300b2 100644 --- a/patacrep/songs/chordpro/syntax.py +++ b/patacrep/songs/chordpro/syntax.py @@ -111,7 +111,7 @@ class ChordproParser(Parser): r""" ^ (?P[^\ ]*)\ * - (base-fret\ *(?P[2-9]))?\ * + (base-fret\ *(?P[1-9]\d*))?\ * frets\ *(?P((\d+|x|X)\ *)+)\ * (fingers\ *(?P(([0-4-])\ *)*))? $ From 3d34985671654958686e0cf767ea88bd17af4af8 Mon Sep 17 00:00:00 2001 From: Louis Date: Fri, 11 Sep 2015 19:00:48 +0200 Subject: [PATCH 30/32] Support of tablature They are rendered using verbatim in LaTeX right now. May be rendered in a nicer way later. --- .../songs/chordpro/data/chordpro/content_tablature | 4 ++-- patacrep/songs/chordpro/data/latex/content_tablature | 9 +++++---- patacrep/songs/chordpro/test/07.sgc | 2 +- patacrep/songs/chordpro/test/07.tex | 6 +++--- patacrep/songs/chordpro/test/13.sgc | 6 +++--- patacrep/songs/chordpro/test/13.tex | 10 +++++----- patacrep/songs/chordpro/test/27.sgc | 2 +- patacrep/songs/chordpro/test/27.tex | 6 +++--- 8 files changed, 23 insertions(+), 22 deletions(-) diff --git a/patacrep/songs/chordpro/data/chordpro/content_tablature b/patacrep/songs/chordpro/data/chordpro/content_tablature index d8924b00..1036924b 100644 --- a/patacrep/songs/chordpro/data/chordpro/content_tablature +++ b/patacrep/songs/chordpro/data/chordpro/content_tablature @@ -1,5 +1,5 @@ {start_of_tab} - (* for foo in content.content *) - (( foo )) + (* for content in content.content *) + ((- content )) (* endfor *) {end_of_tab} diff --git a/patacrep/songs/chordpro/data/latex/content_tablature b/patacrep/songs/chordpro/data/latex/content_tablature index e4036783..85f74e6d 100644 --- a/patacrep/songs/chordpro/data/latex/content_tablature +++ b/patacrep/songs/chordpro/data/latex/content_tablature @@ -1,4 +1,5 @@ -% TODO TABLATURE -% (* for foo in content.content *) -% (( foo )) -% (* endfor *) +\begin{verbatim} +(* for content in content.content *) + ((- content )) +(* endfor *) +\end{verbatim} diff --git a/patacrep/songs/chordpro/test/07.sgc b/patacrep/songs/chordpro/test/07.sgc index 741fee4a..b05a536f 100644 --- a/patacrep/songs/chordpro/test/07.sgc +++ b/patacrep/songs/chordpro/test/07.sgc @@ -1,5 +1,5 @@ {language: english} {start_of_tab} - A tab +A tab {end_of_tab} diff --git a/patacrep/songs/chordpro/test/07.tex b/patacrep/songs/chordpro/test/07.tex index 6b8b48c7..01c0198e 100644 --- a/patacrep/songs/chordpro/test/07.tex +++ b/patacrep/songs/chordpro/test/07.tex @@ -6,8 +6,8 @@ ] -% TODO TABLATURE -% % A tab -% +\begin{verbatim} +A tab +\end{verbatim} \endsong diff --git a/patacrep/songs/chordpro/test/13.sgc b/patacrep/songs/chordpro/test/13.sgc index a2b60a5e..aa6f6603 100644 --- a/patacrep/songs/chordpro/test/13.sgc +++ b/patacrep/songs/chordpro/test/13.sgc @@ -1,7 +1,7 @@ {language: english} {start_of_tab} - A table - wit many # weir [ - [ symbols +A table +wit many # weir [ +[ symbols {end_of_tab} diff --git a/patacrep/songs/chordpro/test/13.tex b/patacrep/songs/chordpro/test/13.tex index 18ed8f96..0bce3b58 100644 --- a/patacrep/songs/chordpro/test/13.tex +++ b/patacrep/songs/chordpro/test/13.tex @@ -6,10 +6,10 @@ ] -% TODO TABLATURE -% % A table -% % wit many # weir [ -% % [ symbols -% +\begin{verbatim} +A table +wit many # weir [ +[ symbols +\end{verbatim} \endsong diff --git a/patacrep/songs/chordpro/test/27.sgc b/patacrep/songs/chordpro/test/27.sgc index 741fee4a..b05a536f 100644 --- a/patacrep/songs/chordpro/test/27.sgc +++ b/patacrep/songs/chordpro/test/27.sgc @@ -1,5 +1,5 @@ {language: english} {start_of_tab} - A tab +A tab {end_of_tab} diff --git a/patacrep/songs/chordpro/test/27.tex b/patacrep/songs/chordpro/test/27.tex index 6b8b48c7..01c0198e 100644 --- a/patacrep/songs/chordpro/test/27.tex +++ b/patacrep/songs/chordpro/test/27.tex @@ -6,8 +6,8 @@ ] -% TODO TABLATURE -% % A tab -% +\begin{verbatim} +A tab +\end{verbatim} \endsong From ae50c7bc283d106bbdee3db7bc36f4fc576a5886 Mon Sep 17 00:00:00 2001 From: Oliverpool Date: Fri, 11 Sep 2015 15:46:12 +0200 Subject: [PATCH 31/32] base-fret can be anything between 1 and 99 --- patacrep/songs/chordpro/syntax.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patacrep/songs/chordpro/syntax.py b/patacrep/songs/chordpro/syntax.py index ee0300b2..4e66b4af 100644 --- a/patacrep/songs/chordpro/syntax.py +++ b/patacrep/songs/chordpro/syntax.py @@ -111,7 +111,7 @@ class ChordproParser(Parser): r""" ^ (?P[^\ ]*)\ * - (base-fret\ *(?P[1-9]\d*))?\ * + (base-fret\ *(?P\d{2}))?\ * frets\ *(?P((\d+|x|X)\ *)+)\ * (fingers\ *(?P(([0-4-])\ *)*))? $ From cf36fbbd9c4e212b1c5d5d06e92b50ca3ea43a22 Mon Sep 17 00:00:00 2001 From: Louis Date: Fri, 11 Sep 2015 22:05:07 +0200 Subject: [PATCH 32/32] Corrected regular expression: can be 1 or 2 repetitions (not *exactly* 2) --- patacrep/songs/chordpro/syntax.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patacrep/songs/chordpro/syntax.py b/patacrep/songs/chordpro/syntax.py index 4e66b4af..a5d1b102 100644 --- a/patacrep/songs/chordpro/syntax.py +++ b/patacrep/songs/chordpro/syntax.py @@ -111,7 +111,7 @@ class ChordproParser(Parser): r""" ^ (?P[^\ ]*)\ * - (base-fret\ *(?P\d{2}))?\ * + (base-fret\ *(?P\d{1,2}))?\ * frets\ *(?P((\d+|x|X)\ *)+)\ * (fingers\ *(?P(([0-4-])\ *)*))? $