Browse Source

Merge master

pull/122/head
Louis 9 years ago
parent
commit
1876b5b5b4
  1. 1
      examples/.gitignore
  2. 3
      examples/example-all.sb
  3. 2
      examples/songs/greensleeves.sgc
  4. 2
      examples/songs/tests/chords.sgc
  5. 2
      examples/songs/tests/errors.sgc
  6. 2
      patacrep/build.py
  7. 6
      patacrep/content/song.py
  8. 10
      patacrep/data/templates/songs.tex
  9. 23
      patacrep/latex/__init__.py
  10. 6
      patacrep/latex/ast.py
  11. 2
      patacrep/songbook.py
  12. 6
      patacrep/songs/__init__.py
  13. 6
      patacrep/songs/chordpro/__init__.py
  14. 4
      patacrep/songs/chordpro/ast.py
  15. 4
      patacrep/songs/chordpro/data/chordpro/song_header
  16. 4
      patacrep/songs/chordpro/data/html/song_header
  17. 4
      patacrep/songs/chordpro/data/latex/song
  18. 20
      patacrep/songs/latex/__init__.py
  19. 4
      patacrep/templates.py
  20. 2
      test/test_chordpro/00.sgc
  21. 2
      test/test_chordpro/01.sgc
  22. 2
      test/test_chordpro/02.sgc
  23. 2
      test/test_chordpro/03.sgc
  24. 2
      test/test_chordpro/04.sgc
  25. 2
      test/test_chordpro/05.sgc
  26. 2
      test/test_chordpro/06.sgc
  27. 2
      test/test_chordpro/07.sgc
  28. 2
      test/test_chordpro/08.sgc
  29. 2
      test/test_chordpro/09.sgc
  30. 2
      test/test_chordpro/10.sgc
  31. 2
      test/test_chordpro/11.sgc
  32. 2
      test/test_chordpro/12.sgc
  33. 2
      test/test_chordpro/13.sgc
  34. 2
      test/test_chordpro/21.sgc
  35. 2
      test/test_chordpro/22.sgc
  36. 2
      test/test_chordpro/23.sgc
  37. 2
      test/test_chordpro/24.sgc
  38. 2
      test/test_chordpro/25.sgc
  39. 2
      test/test_chordpro/26.sgc
  40. 2
      test/test_chordpro/27.sgc
  41. 2
      test/test_chordpro/28.sgc
  42. 2
      test/test_chordpro/29.sgc
  43. 2
      test/test_chordpro/author_names.sgc
  44. 2
      test/test_chordpro/chords.sgc
  45. 2
      test/test_chordpro/customchords.sgc
  46. 2
      test/test_chordpro/greensleeves.sgc
  47. 2
      test/test_chordpro/greensleeves.source
  48. 2
      test/test_chordpro/invalid_chord.sgc
  49. 2
      test/test_chordpro/invalid_customchord.sgc
  50. 1
      test/test_chordpro/lang.sgc
  51. 1
      test/test_chordpro/lang.source
  52. 2
      test/test_chordpro/metadata.sgc
  53. 4
      test/test_chordpro/metadata.source
  54. 2
      test/test_chordpro/newline.html
  55. 2
      test/test_chordpro/newline.sgc
  56. 2
      test/test_chordpro/nolyrics.sgc
  57. 2
      test/test_chordpro/ukulelechords.sgc

1
examples/.gitignore

@ -1 +1,2 @@
/.cache
/*tex

3
examples/example-all.sb

@ -6,8 +6,9 @@
"pictures"
],
"booktype" : "chorded",
"datadir": ["datadir2"],
"template" : "patacrep.tex",
"lang" : "french",
"lang" : "fr",
"encoding": "utf8",
"authwords" : {
"sep" : ["and", "et"]

2
examples/songs/greensleeves.sgc

@ -1,4 +1,4 @@
{language : english}
{lang : en}
{columns : 2}
{ title : Greensleeves}
{subtitle: Test of the chordpro format}

2
examples/songs/tests/chords.sgc

@ -1,4 +1,4 @@
{language: english}
{lang: en}
{columns: 1}
{title: Chords testing}
{subtitle: Test of the chords specification and LaTeX translation}

2
examples/songs/tests/errors.sgc

@ -1,4 +1,4 @@
{language : english}
{lang : en}
{columns : 2}
{ title : Error}
{subtitle: A chordpro file with many errors}

2
patacrep/build.py

@ -29,7 +29,7 @@ GENERATED_EXTENSIONS = [
]
DEFAULT_CONFIG = {
'template': "default.tex",
'lang': 'english',
'lang': 'en',
'content': [],
'titleprefixwords': [],
'encoding': None,

6
patacrep/content/song.py

@ -60,8 +60,8 @@ def parse(keyword, argument, contentlist, config):
Return a list of Song() instances.
"""
plugins = config['_song_plugins']
if '_languages' not in config:
config['_languages'] = set()
if '_langs' not in config:
config['_langs'] = set()
songlist = []
for songdir in config['_songdir']:
if contentlist:
@ -92,7 +92,7 @@ def parse(keyword, argument, contentlist, config):
datadir=songdir.datadir,
))
songlist.append(renderer)
config["_languages"].update(renderer.song.languages)
config["_langs"].add(renderer.song.lang)
if len(songlist) > before:
break
if len(songlist) == before:

10
patacrep/data/templates/songs.tex

@ -52,7 +52,7 @@
"mandatory": true
},
"lang": {"description": {"english": "Language", "french": "Langue"},
"default": {"english": "english", "french": "french"}
"default": {"english": "en", "french": "fr"}
},
"titleprefixwords": {"description": {"english": "Ignore some words in the beginning of song titles",
"french": "Ignore des mots dans le classement des chansons"},
@ -80,11 +80,11 @@
(* block songbookpreambule *)
(( super() ))
(* for lang in _languages -*)
\PassOptionsToPackage{((lang))}{babel}
(* for lang in _langs -*)
\PassOptionsToPackage{(( lang2babel(lang) ))}{babel}
(* endfor *)
\usepackage[((lang))]{babel}
\lang{((lang))}
\usepackage[(( lang2babel(lang) ))]{babel}
\lang{(( lang2babel(lang) ))}
\usepackage{graphicx}
\graphicspath{ %

23
patacrep/latex/__init__.py

@ -5,4 +5,27 @@ This module uses an LALR parser to try to parse LaTeX code. LaTeX language
will work on simple cases, but not on complex ones.
"""
import logging
from collections import OrderedDict
from patacrep.latex.syntax import tex2plain, parse_song
LOGGER = logging.getLogger(__name__)
BABEL_LANGUAGES = OrderedDict((
('fr', 'french'),
('en', 'english'),
('de', 'german'),
('es', 'spanish'),
('it', 'italian'),
('pt', 'portuguese'),
))
def lang2babel(lang):
"""Return the language used by babel, corresponding to the language code"""
try:
return BABEL_LANGUAGES[lang]
except KeyError:
available = ", ".join(BABEL_LANGUAGES.keys())
LOGGER.error('Unknown lang code: ' + lang + '. Supported: ' + available)
return 'english'

6
patacrep/latex/ast.py

@ -2,6 +2,8 @@
# pylint: disable=too-few-public-methods
DEFAULT_LANGUAGE = "english"
class AST:
"""Base class for the tree."""
# pylint: disable=no-init
@ -16,7 +18,7 @@ class AST:
parsing.
"""
cls.metadata = {
'@languages': set(),
'@language': DEFAULT_LANGUAGE,
}
class Expression(AST):
@ -44,7 +46,7 @@ class Command(AST):
self.optional = optional
if name == r'\selectlanguage':
self.metadata['@languages'] |= set(self.mandatory)
self.metadata['@language'] = self.mandatory[0]
def __str__(self):
if self.name in [r'\emph']:

2
patacrep/songbook.py

@ -105,6 +105,8 @@ def main():
options = argument_parser(sys.argv[1:])
songbook_path = options.book[0]
if os.path.exists(songbook_path + ".sb") and not os.path.exists(songbook_path):
songbook_path += ".sb"
basename = os.path.basename(songbook_path)[:-3]

6
patacrep/songs/__init__.py

@ -89,7 +89,7 @@ class Song:
"cached",
"data",
"subpath",
"languages",
"lang",
"authors",
"_filehash",
"_version",
@ -131,6 +131,7 @@ class Song:
self.titles = []
self.data = {}
self.cached = None
self.lang = None
self._parse(config)
# Post processing of data
@ -182,8 +183,7 @@ class Song:
- titles: the list of (raw) titles. This list will be processed to
remove prefixes.
- languages: the list of languages used in the song, as languages
recognized by the LaTeX babel package.
- lang: the main language of the song, as language code..
- authors: the list of (raw) authors. This list will be processed to
'clean' it (see function :func:`patacrep.authors.processauthors`).
- data: song metadata. Used (among others) to sort the songs.

6
patacrep/songs/chordpro/__init__.py

@ -10,6 +10,7 @@ from patacrep import encoding, files
from patacrep.songs import Song
from patacrep.songs.chordpro.syntax import parse_song
from patacrep.templates import Renderer
from patacrep.latex import lang2babel
LOGGER = logging.getLogger(__name__)
@ -25,7 +26,7 @@ class ChordproSong(Song):
song = parse_song(song.read(), self.fullpath)
self.authors = song.authors
self.titles = song.titles
self.languages = song.get_data_argument('language', [self.config['lang']])
self.lang = song.get_data_argument('lang', self.config['lang'])
self.data = song.meta
self.cached = {
'song': song,
@ -33,7 +34,7 @@ class ChordproSong(Song):
def render(self, output=None, template="song"): # pylint: disable=arguments-differ
context = {
'language': self.languages[0],
'lang': self.lang,
"titles": self.titles,
"authors": self.authors,
"metadata": self.data,
@ -52,6 +53,7 @@ class ChordproSong(Song):
]))
jinjaenv.filters['search_image'] = self.search_image
jinjaenv.filters['search_partition'] = self.search_partition
jinjaenv.filters['lang2babel'] = lang2babel
try:
return Renderer(

4
patacrep/songs/chordpro/ast.py

@ -31,6 +31,7 @@ DIRECTIVE_SHORTCUTS = {
"c": "comment",
"gc": "guitar_comment",
"cover": "cov",
"language": "lang",
}
def directive_name(text):
@ -181,7 +182,7 @@ class Song(AST):
- content: the song content, as a list of objects `foo` such that
`foo.inline` is True.
- titles: The list of titles
- language: The language (if set), None otherwise
- lang: The language code (if set), None otherwise
- authors: The list of authors
- meta: Every other metadata.
"""
@ -193,7 +194,6 @@ class Song(AST):
"artist": "add_author",
"key": "add_key",
"define": "add_cumulative",
"language": "add_cumulative",
}
def __init__(self, filename):

4
patacrep/songs/chordpro/data/chordpro/song_header

@ -1,5 +1,5 @@
(* if language is defined -*)
{language: (( language ))}
(* if lang is defined -*)
{lang: (( lang ))}
(* endif *)
(* if metadata.columns is defined -*)
{columns: (( metadata.columns ))}

4
patacrep/songs/chordpro/data/html/song_header

@ -17,8 +17,8 @@
(* endif *)
(* endfor *)
(* if language is defined -*)
<span class="song-language">Language: (( language ))</span><br>
(* if lang is defined -*)
<span class="song-language">Lang: (( lang ))</span><br>
(* endif *)
(* include 'content_metadata_cover' *)

4
patacrep/songs/chordpro/data/latex/song

@ -1,5 +1,5 @@
(* if language is defined -*)
\selectlanguage{((language))}
(* if lang is defined -*)
\selectlanguage{(( lang2babel(lang) ))}
(* endif *)
(*- if metadata.columns is defined *)

20
patacrep/songs/latex/__init__.py

@ -8,7 +8,7 @@ will work on simple cases, but not on complex ones.
import os
from patacrep import files, encoding
from patacrep.latex import parse_song
from patacrep.latex import parse_song, BABEL_LANGUAGES
from patacrep.songs import Song
class Latex2LatexSong(Song):
@ -16,13 +16,13 @@ class Latex2LatexSong(Song):
# pylint: disable=abstract-method
def _parse(self, __config):
"""Parse content, and return the dictinory of song data."""
"""Parse content, and return the dictionary of song data."""
with encoding.open_read(self.fullpath, encoding=self.encoding) as song:
self.data = parse_song(song.read(), self.fullpath)
self.titles = self.data['@titles']
del self.data['@titles']
self.languages = self.data['@languages']
del self.data['@languages']
self.set_lang(self.data['@language'])
del self.data['@language']
if "by" in self.data:
self.authors = [self.data['by']]
del self.data['by']
@ -40,6 +40,18 @@ class Latex2LatexSong(Song):
))
return r'\import{{{}/}}{{{}}}'.format(os.path.dirname(path), os.path.basename(path))
def set_lang(self, language):
"""Set the language code"""
for lang, babel_language in BABEL_LANGUAGES.items():
if language == babel_language:
self.lang = lang
return
# Add a custom language to the babel dictionary (language is not officially supported)
custom_lang = '_' + language
BABEL_LANGUAGES[custom_lang] = language
self.lang = custom_lang
SONG_RENDERERS = {
"latex": {
'is': Latex2LatexSong,

4
patacrep/templates.py

@ -9,6 +9,7 @@ import re
import json
from patacrep import errors, files
from patacrep.latex import lang2babel
import patacrep.encoding
_LATEX_SUBS = (
@ -84,6 +85,7 @@ class Renderer:
self.jinjaenv.trim_blocks = True
self.jinjaenv.lstrip_blocks = True
self.jinjaenv.globals["path2posix"] = files.path2posix
self.jinjaenv.globals["lang2babel"] = lang2babel
self.template = self.jinjaenv.get_template(template)
@ -153,7 +155,7 @@ class TexBookRenderer(Renderer):
variable = default["default"]
elif "en" in default:
variable = default["en"]
elif len(default > 0):
elif len(default):
variable = default.popitem()[1]
else:
variable = None

2
test/test_chordpro/00.sgc

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

2
test/test_chordpro/01.sgc

@ -1,3 +1,3 @@
{language: english}
{lang: en}
A verse line

2
test/test_chordpro/02.sgc

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

2
test/test_chordpro/03.sgc

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

2
test/test_chordpro/04.sgc

@ -1,4 +1,4 @@
{language: english}
{lang: en}
{start_of_chorus}
A one line chorus

2
test/test_chordpro/05.sgc

@ -1,4 +1,4 @@
{language: english}
{lang: en}
{start_of_bridge}
A one line bridge

2
test/test_chordpro/06.sgc

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

2
test/test_chordpro/07.sgc

@ -1,4 +1,4 @@
{language: english}
{lang: en}
{start_of_tab}
A tab

2
test/test_chordpro/08.sgc

@ -1,4 +1,4 @@
{language: english}
{lang: en}
A lot of new lines

2
test/test_chordpro/09.sgc

@ -1,4 +1,4 @@
{language: english}
{lang: en}
{title: and a directive}

2
test/test_chordpro/10.sgc

@ -1,3 +1,3 @@
{language: english}
{lang: en}
A line[A] with a chord

2
test/test_chordpro/11.sgc

@ -1,3 +1,3 @@
{language: english}
{lang: en}
A line ending with a chord[A]

2
test/test_chordpro/12.sgc

@ -1,3 +1,3 @@
{language: english}
{lang: en}
[A]A line starting with a chord

2
test/test_chordpro/13.sgc

@ -1,4 +1,4 @@
{language: english}
{lang: en}
{start_of_tab}
A table

2
test/test_chordpro/21.sgc

@ -1,3 +1,3 @@
{language: english}
{lang: en}
A verse line

2
test/test_chordpro/22.sgc

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

2
test/test_chordpro/23.sgc

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

2
test/test_chordpro/24.sgc

@ -1,4 +1,4 @@
{language: english}
{lang: en}
{start_of_chorus}
A one line chorus

2
test/test_chordpro/25.sgc

@ -1,4 +1,4 @@
{language: english}
{lang: en}
{start_of_bridge}
A one line bridge

2
test/test_chordpro/26.sgc

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

2
test/test_chordpro/27.sgc

@ -1,4 +1,4 @@
{language: english}
{lang: en}
{start_of_tab}
A tab

2
test/test_chordpro/28.sgc

@ -1,4 +1,4 @@
{language: english}
{lang: en}
A lot of new lines

2
test/test_chordpro/29.sgc

@ -1,4 +1,4 @@
{language: english}
{lang: en}
{title: and a directive}

2
test/test_chordpro/author_names.sgc

@ -1,4 +1,4 @@
{language: english}
{lang: en}
{title: Title}
{artist: The Beatles}
{artist: Oasis}

2
test/test_chordpro/chords.sgc

@ -1,4 +1,4 @@
{language: english}
{lang: en}
[A]Simple
[Bb]Bémol

2
test/test_chordpro/customchords.sgc

@ -1,4 +1,4 @@
{language: english}
{lang: en}
{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 - -}

2
test/test_chordpro/greensleeves.sgc

@ -1,4 +1,4 @@
{language: english}
{lang: en}
{columns: 2}
{title: Greensleeves}
{title: Un autre sous-titre}

2
test/test_chordpro/greensleeves.source

@ -1,4 +1,4 @@
{language : english}
{lang : en}
{columns : 2}
{subtitle : Un sous titre}
{ title : Greensleeves}

2
test/test_chordpro/invalid_chord.sgc

@ -1,3 +1,3 @@
{language: english}
{lang: en}
This is invalid.

2
test/test_chordpro/invalid_customchord.sgc

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

1
test/test_chordpro/lang.sgc

@ -0,0 +1 @@
{lang: fr}

1
test/test_chordpro/lang.source

@ -0,0 +1 @@
{language: fr}

2
test/test_chordpro/metadata.sgc

@ -1,4 +1,4 @@
{language: french}
{lang: fr}
{capo: Capo}
{title: Title}
{title: Subtitle1}

4
test/test_chordpro/metadata.source

@ -4,8 +4,8 @@
{subtitle: Subtitle4}
{t: Subtitle2}
{st: Subtitle5}
{language: french}
{language: english}
{lang: en}
{lang: fr}
{by: Author1}
{artist: Author2}
{album: Album}

2
test/test_chordpro/newline.html

@ -1,4 +1,4 @@
<span class="song-language">Language: english</span><br>
<span class="song-language">Lang: en</span><br>

2
test/test_chordpro/newline.sgc

@ -1,4 +1,4 @@
{language: english}
{lang: en}
This is a verse
With a new line

2
test/test_chordpro/nolyrics.sgc

@ -1,4 +1,4 @@
{language: english}
{lang: en}
A chorus [A]with lyrics
[Emaj3]maj et nombre

2
test/test_chordpro/ukulelechords.sgc

@ -1,4 +1,4 @@
{language: english}
{lang: en}
{define: G frets 0 2 3 2}
{define: D7 frets 2 2 2 3 fingers 1 1 1 2}
{define: G frets 3 2 0 0 0 3}

Loading…
Cancel
Save