Browse Source

[chordpro] Songs can now be rendered in any format (given that it has been implemented)

pull/79/head
Louis 9 years ago
parent
commit
3c89a70f73
  1. 5
      patacrep/songs/chordpro/__init__.py
  2. 13
      patacrep/songs/chordpro/ast.py
  3. 9
      patacrep/songs/chordpro/data/chordpro/content_chord
  4. 6
      patacrep/songs/chordpro/data/chordpro/content_chordlist
  5. 1
      patacrep/songs/chordpro/data/chordpro/content_comment
  6. 25
      patacrep/songs/chordpro/data/chordpro/content_define
  7. 3
      patacrep/songs/chordpro/data/chordpro/content_error
  8. 1
      patacrep/songs/chordpro/data/chordpro/content_guitar_comment
  9. 1
      patacrep/songs/chordpro/data/chordpro/content_image
  10. 3
      patacrep/songs/chordpro/data/chordpro/content_line
  11. 2
      patacrep/songs/chordpro/data/chordpro/content_newline
  12. 1
      patacrep/songs/chordpro/data/chordpro/content_partition
  13. 1
      patacrep/songs/chordpro/data/chordpro/content_space
  14. 5
      patacrep/songs/chordpro/data/chordpro/content_tablature
  15. 5
      patacrep/songs/chordpro/data/chordpro/content_verse
  16. 1
      patacrep/songs/chordpro/data/chordpro/content_word
  17. 34
      patacrep/songs/chordpro/data/chordpro/song
  18. 2
      patacrep/songs/chordpro/data/latex/content_error
  19. 2
      patacrep/songs/chordpro/test/00.txt
  20. 3
      patacrep/songs/chordpro/test/01.txt
  21. 1
      patacrep/songs/chordpro/test/02.txt
  22. 1
      patacrep/songs/chordpro/test/03.txt
  23. 3
      patacrep/songs/chordpro/test/04.txt
  24. 3
      patacrep/songs/chordpro/test/05.txt
  25. 1
      patacrep/songs/chordpro/test/06.txt
  26. 3
      patacrep/songs/chordpro/test/07.txt
  27. 5
      patacrep/songs/chordpro/test/08.txt
  28. 5
      patacrep/songs/chordpro/test/09.txt
  29. 3
      patacrep/songs/chordpro/test/10.txt
  30. 3
      patacrep/songs/chordpro/test/11.txt
  31. 3
      patacrep/songs/chordpro/test/12.txt
  32. 7
      patacrep/songs/chordpro/test/13.txt
  33. 3
      patacrep/songs/chordpro/test/21.txt
  34. 1
      patacrep/songs/chordpro/test/22.txt
  35. 2
      patacrep/songs/chordpro/test/23.txt
  36. 3
      patacrep/songs/chordpro/test/24.txt
  37. 3
      patacrep/songs/chordpro/test/25.txt
  38. 1
      patacrep/songs/chordpro/test/26.txt
  39. 3
      patacrep/songs/chordpro/test/27.txt
  40. 5
      patacrep/songs/chordpro/test/28.txt
  41. 5
      patacrep/songs/chordpro/test/29.txt
  42. 27
      patacrep/songs/chordpro/test/chords.txt
  43. 2
      patacrep/songs/chordpro/test/customchords.txt
  44. 64
      patacrep/songs/chordpro/test/greensleeves.txt
  45. 7
      patacrep/songs/chordpro/test/invalid_chord.txt
  46. 2
      patacrep/songs/chordpro/test/invalid_customchord.txt
  47. 2
      patacrep/songs/chordpro/test/metadata.sgc
  48. 13
      patacrep/songs/chordpro/test/metadata.txt
  49. 23
      patacrep/songs/chordpro/test/test_parser.py
  50. 14
      patacrep/songs/syntax.py

5
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,

13
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__()

9
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 -*)

6
patacrep/songs/chordpro/data/chordpro/content_chordlist

@ -0,0 +1,6 @@
[
(*- for chord in content.chords -*)
(* if not loop.first *) (* endif -*)
(( render(chord) -))
(* endfor -*)
]

1
patacrep/songs/chordpro/data/chordpro/content_comment

@ -0,0 +1 @@
{comment: (( content.argument ))}

25
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 -*)
}

3
patacrep/songs/chordpro/data/chordpro/content_error

@ -0,0 +1,3 @@
ERROR : Template not found for "(( content.__class__.__name__ ))". See the logs for details.

1
patacrep/songs/chordpro/data/chordpro/content_guitar_comment

@ -0,0 +1 @@
{guitar_comment: (( content.argument ))}

1
patacrep/songs/chordpro/data/chordpro/content_image

@ -0,0 +1 @@
{image: (( content.argument ))}

3
patacrep/songs/chordpro/data/chordpro/content_line

@ -0,0 +1,3 @@
(* for item in content.line -*)
(( render(item) ))
(*- endfor *)

2
patacrep/songs/chordpro/data/chordpro/content_newline

@ -0,0 +1,2 @@

1
patacrep/songs/chordpro/data/chordpro/content_partition

@ -0,0 +1 @@
{partition: ((content.argument))}

1
patacrep/songs/chordpro/data/chordpro/content_space

@ -0,0 +1 @@

5
patacrep/songs/chordpro/data/chordpro/content_tablature

@ -0,0 +1,5 @@
{start_of_tab}
(* for foo in content.content *)
(( foo ))
(* endfor *)
{end_of_tab}

5
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 ))}

1
patacrep/songs/chordpro/data/chordpro/content_word

@ -0,0 +1 @@
(( content.value ))

34
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 *)

2
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.

2
patacrep/songs/chordpro/test/00.txt

@ -1 +1 @@
{language: english}

3
patacrep/songs/chordpro/test/01.txt

@ -1,4 +1,5 @@
{language: english}
{start_of_verse}
A verse line
A verse line
{end_of_verse}

1
patacrep/songs/chordpro/test/02.txt

@ -1,2 +1,3 @@
{language: english}
{title: A directive}

1
patacrep/songs/chordpro/test/03.txt

@ -1 +1,2 @@
{language: english}

3
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}

3
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}

1
patacrep/songs/chordpro/test/06.txt

@ -1 +1,2 @@
{language: english}

3
patacrep/songs/chordpro/test/07.txt

@ -1,4 +1,5 @@
{language: english}
{start_of_tab}
A tab
A tab
{end_of_tab}

5
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}

5
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}

3
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}

3
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}

3
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}

7
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}

3
patacrep/songs/chordpro/test/21.txt

@ -1,4 +1,5 @@
{language: english}
{start_of_verse}
A verse line
A verse line
{end_of_verse}

1
patacrep/songs/chordpro/test/22.txt

@ -1,2 +1,3 @@
{language: english}
{title: A directive}

2
patacrep/songs/chordpro/test/23.txt

@ -1 +1 @@
{language: english}

3
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}

3
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}

1
patacrep/songs/chordpro/test/26.txt

@ -1 +1,2 @@
{language: english}

3
patacrep/songs/chordpro/test/27.txt

@ -1,4 +1,5 @@
{language: english}
{start_of_tab}
A tab
A tab
{end_of_tab}

5
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}

5
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}

27
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}

2
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 - -}

64
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}

7
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}

2
patacrep/songs/chordpro/test/invalid_customchord.txt

@ -0,0 +1,2 @@
{language: english}

2
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}

13
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}

23
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."""

14
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:

Loading…
Cancel
Save