Browse Source

Merge branch 'master' into version5

pull/210/head
Louis 8 years ago
parent
commit
2e815f8d5a
  1. 8
      patacrep/authors.py
  2. 15
      patacrep/build.py
  3. 2
      patacrep/content/sort.py
  4. BIN
      patacrep/data/img/internet.png
  5. 21
      patacrep/data/templates/songbook/default.tex
  6. 6
      patacrep/data/templates/songbook/patacrep.tex
  7. 33
      patacrep/data/templates/songbook_model.yml
  8. 2
      patacrep/data/templates/songs/chordpro/chordpro/content_image
  9. 2
      patacrep/data/templates/songs/chordpro/chordpro/content_word
  10. 12
      patacrep/data/templates/songs/chordpro/chordpro/song_header
  11. 4
      patacrep/data/templates/songs/chordpro/latex/content_image
  12. 2
      patacrep/data/templates/songs/chordpro/latex/content_word
  13. 11
      patacrep/data/templates/songs/chordpro/latex/song
  14. 13
      patacrep/data/templates/styles/chords.sty
  15. 4
      patacrep/data/templates/styles/crepbook.sty
  16. 17
      patacrep/data/templates/styles/patacrep.sty
  17. 7
      patacrep/index.py
  18. 4
      patacrep/latex/__init__.py
  19. 2
      patacrep/songs/__init__.py
  20. 77
      patacrep/songs/chordpro/__init__.py
  21. 16
      patacrep/songs/chordpro/ast.py
  22. 18
      patacrep/songs/chordpro/lexer.py
  23. 89
      patacrep/songs/chordpro/syntax.py
  24. 59
      patacrep/templates.py
  25. 77
      patacrep/tools/__main__.py
  26. 5
      patacrep/tools/cache/__main__.py
  27. 3
      patacrep/tools/convert/__main__.py
  28. 2
      setup.py
  29. 0
      test/test_book/.gitignore
  30. 0
      test/test_book/__init__.py
  31. 12
      test/test_book/content.tex.control
  32. 0
      test/test_book/content.yaml
  33. 0
      test/test_book/content_datadir/content/foo.tex
  34. 0
      test/test_book/content_datadir/content/inter.isg
  35. 0
      test/test_book/content_datadir/content/song.csg
  36. 0
      test/test_book/content_datadir/content/song.tsg
  37. 0
      test/test_book/content_datadir/songs/include.sbc
  38. 0
      test/test_book/content_datadir/songs/inter.isg
  39. 0
      test/test_book/content_datadir/songs/song.csg
  40. 0
      test/test_book/content_datadir/songs/song.tsg
  41. 20
      test/test_book/datadir.tex.control
  42. 0
      test/test_book/datadir.yaml
  43. 0
      test/test_book/datadir_datadir/img/datadir.png
  44. 0
      test/test_book/datadir_datadir/scores/datadir.ly
  45. 0
      test/test_book/datadir_datadir/songs/datadir.csg
  46. 0
      test/test_book/datadir_datadir/songs/datadir.tsg
  47. 0
      test/test_book/datadir_datadir/songs/datadir2.csg
  48. 0
      test/test_book/datadir_datadir/songs/datadir2.sg
  49. 0
      test/test_book/datadir_datadir/songs/relative.csg
  50. 0
      test/test_book/datadir_datadir/songs/relative.ly
  51. 0
      test/test_book/datadir_datadir/songs/relative.png
  52. 0
      test/test_book/datadir_datadir/songs/relative.tsg
  53. 0
      test/test_book/datadir_datadir/songs/subdir/subdir.csg
  54. 0
      test/test_book/datadir_datadir/songs/subdir/subdir.ly
  55. 0
      test/test_book/datadir_datadir/songs/subdir/subdir.png
  56. 0
      test/test_book/datadir_datadir/songs/subdir/subdir.tsg
  57. 0
      test/test_book/datadir_datadir2/img/datadir2.png
  58. 0
      test/test_book/datadir_datadir2/scores/datadir2.ly
  59. 131
      test/test_book/lang_de.tex.control
  60. 5
      test/test_book/lang_de.yaml
  61. 12
      test/test_book/lang_default.tex.control
  62. 0
      test/test_book/lang_default.yaml
  63. 12
      test/test_book/lang_en.tex.control
  64. 0
      test/test_book/lang_en.yaml
  65. 12
      test/test_book/lang_fr.tex.control
  66. 0
      test/test_book/lang_fr.yaml
  67. 12
      test/test_book/languages.tex.control
  68. 0
      test/test_book/languages.yaml
  69. 0
      test/test_book/languages_datadir/songs/language.csg
  70. 0
      test/test_book/languages_datadir/songs/language_location.csg
  71. 0
      test/test_book/languages_datadir/songs/no_language.csg
  72. 0
      test/test_book/languages_datadir/songs/wrong_language.csg
  73. 0
      test/test_book/languages_datadir/songs/wrong_location.csg
  74. 12
      test/test_book/onthefly/content.onthefly.tex.control
  75. 0
      test/test_book/onthefly/content.onthefly.yaml
  76. 162
      test/test_book/special.tex.control
  77. 14
      test/test_book/special.yaml
  78. 10
      test/test_book/special_datadir/songs/special.csg
  79. 79
      test/test_book/syntax.tex.control
  80. 0
      test/test_book/syntax.yaml
  81. BIN
      test/test_book/syntax_datadir/img/image with spaces.png
  82. BIN
      test/test_book/syntax_datadir/img/image.png
  83. 35
      test/test_book/syntax_datadir/songs/images.csg
  84. 0
      test/test_book/syntax_datadir/songs/musicnote.csg
  85. 0
      test/test_book/test_compilation.py
  86. 12
      test/test_book/unicode.tex.control
  87. 0
      test/test_book/unicode.yaml
  88. 0
      test/test_book/unicode_datadir/songs/nonbreak.csg
  89. 0
      test/test_song/image with spaces.png
  90. 44
      test/test_song/image.csg
  91. 35
      test/test_song/image.csg.source
  92. 0
      test/test_song/image.png
  93. 59
      test/test_song/image.tsg
  94. 2
      test/test_song/metadata.csg
  95. 2
      test/test_song/metadata.tsg
  96. 13
      test/test_song/special.csg
  97. 10
      test/test_song/special.csg.source
  98. 22
      test/test_song/special.tsg

8
patacrep/authors.py

@ -16,12 +16,12 @@ def compile_authwords(authwords):
return {
'ignore': authwords.get('ignore', []),
'after': [
re.compile(RE_AFTER.format(word), re.LOCALE)
for word in authwords.get('after')
re.compile(RE_AFTER.format(word))
for word in authwords.get('after', [])
],
'separators': [
re.compile(RE_SEPARATOR.format(word), re.LOCALE)
for word in ([" %s" % word for word in authwords['separators']] + [',', ';'])
re.compile(RE_SEPARATOR.format(word))
for word in ([" %s" % word for word in authwords.get('separators', [])] + [',', ';'])
],
}

15
patacrep/build.py

@ -29,8 +29,6 @@ GENERATED_EXTENSIONS = [
"_title.sxd",
]
# pylint: disable=too-few-public-methods
class Songbook:
"""Represent a songbook (.yaml) file.
@ -101,7 +99,11 @@ class Songbook:
)
self._config['filename'] = output.name[:-4]
# Processing special options
self._config['_bookoptions'] = iter_bookoptions(self._config)
self._config['chords']['_notenames'] = self._get_chord_names(
self._config['chords']['notation']
)
renderer.render_tex(output, self._config)
@ -111,6 +113,15 @@ class Songbook:
if self.has_errors():
raise errors.SongbookError("Some songs contain errors. Stopping as requested.")
@staticmethod
def _get_chord_names(notation):
"""Return a list of chord names, given the user option."""
if notation == "alphascale":
return ["A", "B", "C", "D", "E", "F", "G"]
if notation == "solfedge":
return ["La", "Si", "Do", r"R\'e", "Mi", "Fa", "Sol"]
return notation
def has_errors(self):
"""Return `True` iff errors have been encountered in the book.

2
patacrep/content/sort.py

@ -56,7 +56,7 @@ def key_generator(sort):
field = song.data[key]
except KeyError:
LOGGER.debug(
"Ignoring unknown key '{}' for song {}.".format(
"Ignoring missing key '{}' for song {}.".format(
key,
files.relpath(song.fullpath),
)

BIN
patacrep/data/img/internet.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

21
patacrep/data/templates/songbook/default.tex

@ -66,8 +66,8 @@ description:
\usepackage{chords}
\title{(( template_var.title ))}
\author{(( template_var.author ))}
\title{(( template_var.title|escape_specials() ))}
\author{(( template_var.author|escape_specials() ))}
\newindex{titleidx}{((filename))_title}
\newauthorindex{authidx}{((filename))_auth}
@ -85,11 +85,7 @@ description:
\authsepword{((word))}
(* endfor *)
(* if chords.notation=="alphascale" -*)
\notenamesout{A}{B}{C}{D}{E}{F}{G}
(* else -*)
\notenamesout{La}{Si}{Do}{R\'e}{Mi}{Fa}{Sol}
(* endif *)
\notenamesout{(( chords._notenames[0] ))}{(( chords._notenames[1] ))}{(( chords._notenames[2] ))}{(( chords._notenames[3] ))}{(( chords._notenames[4] ))}{(( chords._notenames[5] ))}{(( chords._notenames[6] ))}
(* endblock *)
(* block title *)
@ -103,12 +99,11 @@ description:
(* block chords *)
% list of chords
\ifchorded
\ifdiagram
\phantomsection
\addcontentsline{toc}{section}{\chordlistname}
\chords
\fi
\ifdiagrampage
\phantomsection
\addcontentsline{toc}{section}{\chordlistname}
\chords
\fi
\setcounter{songnum}{1}%
(* endblock *)

6
patacrep/data/templates/songbook/patacrep.tex

@ -138,12 +138,12 @@ description:
]{hyperref}
\subtitle{(( template_var.subtitle ))}
\subtitle{(( template_var.subtitle|escape_specials ))}
(* if template_var.version -*)
\version{(( template_var.version ))}
(* endif *)
\mail{(( template_var.email ))}
\web{(( template_var.url ))}
\mail{(( template_var.email|escape_url ))}
\web{(( template_var.url|escape_url ))}
\picture{(( template_var.picture ))}
\picturecopyright{(( template_var.picturecopyright ))}
\footer{(( template_var.footer ))}

33
patacrep/data/templates/songbook_model.yml

@ -27,7 +27,15 @@ schema:
type: //rec
required:
show: //bool
diagrampage: //bool
diagrampage:
type: //any
of:
- type: //str
value: "none"
- type: //str
value: "important"
- type: //str
value: "all"
repeatchords: //bool
lilypond: //bool
tablatures: //bool
@ -48,12 +56,17 @@ schema:
- type: //str
value: "ukulele"
notation:
type: //any
of:
- type: //str
value: "alphascale"
- type: //str
value: "solfedge"
type: //any
of:
- type: //str
value: "alphascale"
- type: //str
value: "solfedge"
- type: //arr
contents: //str
length:
min: 7
max: 7
authors:
type: //rec
required:
@ -97,7 +110,7 @@ default:
chords:
show: yes
diagramreminder: important
diagrampage: yes
diagrampage: all
repeatchords: yes
lilypond: no
tablatures: no
@ -149,7 +162,7 @@ description:
lilypond: "Display lilypond scores"
tablatures: "Display tablatures"
instrument: "Instrument for the diagrams"
notation: "Chord notation"
notation: "List of chord names, with special values `solfedge` being an alias for `['La', 'Si', 'Do', 'Ré', 'Mi', 'Fa', 'Sol']`, and `alphascale` for `['A', 'B', 'C', 'D', 'E', 'F', 'G']`."
authors:
separators: "Separator words between artists"
@ -175,7 +188,7 @@ description:
lilypond: "Inclure les partitions lilypond"
tablatures: "Inclure les tablatures"
instrument: "Instrument pour les diagrammes d'accords"
notation: "Notation des accords"
notation: "Liste des noms de notes, en commençant par LA, sachant que `solfedge` est un alias pour `['La', 'Si', 'Do', 'Ré', 'Mi', 'Fa', 'Sol']`, et `alphascale` pour `['A', 'B', 'C', 'D', 'E', 'F', 'G']`."
authors:
separators: "Mots de séparation entre les artistes"

2
patacrep/data/templates/songs/chordpro/chordpro/content_image

@ -1 +1 @@
{image: (( content.argument|search_image ))}
{image: "(( content.filename|search_image ))" ((content.size|render_size))}

2
patacrep/data/templates/songs/chordpro/chordpro/content_word

@ -1 +1 @@
(( content.value ))
(( content.value|escape_specials('{}\\#') ))

12
patacrep/data/templates/songs/chordpro/chordpro/song_header

@ -9,16 +9,16 @@
(* endif *)
(*- for title in titles -*)
{title: (( title ))}
{title: (( title|escape_specials('{}\\') ))}
(* endfor -*)
(*- for author in authors -*)
{artist: (( author[1] )) (( author[0] ))}
{artist: (( author[1]|escape_specials('{}\\') )) (( author[0]|escape_specials('{}\\') ))}
(* endfor -*)
(*- for key in ['album', 'copyright'] *)
(* if key in metadata -*)
{(( key )): (( metadata[key] ))}
{(( key )): (( metadata[key]|escape_specials('{}\\') ))}
(* endif *)
(* endfor *)
(* if 'cover' in metadata -*)
@ -30,9 +30,13 @@
(* endfor -*)
(*- for key in metadata.morekeys -*)
{key: (( key.keyword )): (( key.argument ))}
{key: (( key.keyword )): (( key.argument|escape_specials('{}\\') ))}
(* endfor *)
(*- if 'url' in metadata -*)
{url: (( metadata.url|escape_url ))}
(* endif -*)
(*- for chord in metadata['define'] *)
((- render(chord) ))
(* endfor *)

4
patacrep/data/templates/songs/chordpro/latex/content_image

@ -1,6 +1,6 @@
(* block image *)
(* set image = content.argument|search_image|path2posix *)
(* set image = content.filename|search_image|path2posix *)
(* if image *)
\image{(( image ))}
\image[(( content.size|render_size ))]{(( image ))}
(*- endif *)
(*- endblock *)

2
patacrep/data/templates/songs/chordpro/latex/content_word

@ -1 +1 @@
(( content.value ))
(( content.value|escape_specials('{}&#_^%~$\\') ))

11
patacrep/data/templates/songs/chordpro/latex/song

@ -8,7 +8,7 @@
\beginsong{
(*- for title in titles -*)
(( title ))
(( title|escape_specials('{}&#_^%~$\\') ))
(*- if not loop.last -*)
\\
(* endif *)
@ -16,7 +16,7 @@
}[
by={
(* for author in authors *)
(( author[1] )) (( author[0] ))
(( author[1]|escape_specials('{}&#_^%~$\\') )) (( author[0]|escape_specials('{}&#_^%~$\\') ))
(*- if not loop.last -*)
,
(* endif *)
@ -24,9 +24,12 @@
},
(* for key in ['album', 'copyright'] *)
(* if key in metadata *)
(( key ))={(( metadata[key] ))},
(( key ))={(( metadata[key]|escape_specials('{}&#_^%~$\\') ))},
(* endif *)
(* endfor *)
(* if 'url' in metadata *)
url={(( metadata.url|escape_url ))},
(* endif *)
(* if 'cover' in metadata *)
(* block cover *)
(* set cover = metadata["cover"].argument|search_image|path2posix *)
@ -36,7 +39,7 @@
(* endblock *)
(* endif *)
(* for key in metadata.morekeys *)
(( key.keyword ))={(( key.argument ))},
(( key.keyword ))={(( key.argument|escape_specials('{}&#_^%~$\\') ))},
(* endfor *)
]

13
patacrep/data/templates/styles/chords.sty

@ -24,7 +24,7 @@
\raisebox{2em}{\chordname{##1}} %
} %
% Placing boxes
\ifimportantdiagramonly%
\ifdiagrampagereduced%
\pl@cechord{#1}%
\hspace{\stretch{1}}%
\usebox{\@chordgroupbox@ii}%
@ -75,7 +75,17 @@
\newcommand{\chords}{
\ifdiagrampage
\begin{songs}{}
%important diagrams are hidden by \chordtabs
\renewcommand{\gtab}{\@ifstar
\gtab@Original%
\gtab@Original%
}
\renewcommand{\utab}{\@ifstar
\utab@Original%
\utab@Original%
}
%hide song number
\definecolor{SongNumberBgColor}{HTML}{FFFFFF}
\renewcommand{\snumbgcolor}{SongNumberBgColor}
@ -391,5 +401,6 @@
\fi
\end{songs}
\fi
}
\endinput

4
patacrep/data/templates/styles/crepbook.sty

@ -79,8 +79,8 @@
% Title page
\long\def\subtitle#1{\long\def\@subtitle{#1}}
\def\version#1{\def\@version{#1}}
\def\web#1{\def\@web{#1}}
\def\mail#1{\def\@mail{#1}}
\def\web#1{\def\@web{\url{#1}}}
\def\mail#1{\def\@mail{\href{mailto:#1}{\nolinkurl{#1}}}}
\def\email#1{\def\@email{#1}}
\def\picture#1{\def\@picture{#1}}
\def\picturecopyright#1{\def\@picturecopyright{#1}}

17
patacrep/data/templates/styles/patacrep.sty

@ -6,6 +6,7 @@
\NeedsTeXFormat{LaTeX2e}[1994/06/01]
\ProvidesPackage{patacrep}[2014/06/17 Patacrep Package, version 1]
\RequirePackage[space]{grffile}
\RequirePackage{graphicx,xcolor} %
\RequirePackage{epstopdf} %
\RequirePackage{fancybox}
@ -26,6 +27,14 @@
\newif{\iflilypondauto}
\DeclareOption{lilypond}{\lilypondautotrue\lilypondtrue}
% diagram: insert a page of diagrams before the songs
\newif{\ifdiagrampage}
\DeclareOption{diagrampage}{\diagrampagetrue}
% diagram: insert a page of the "important diagrams" before the songs
\newif{\ifdiagrampagereduced}
\DeclareOption{diagrampagereduced}{\diagrampagereducedtrue\diagrampagetrue}
% diagram: display chord diagrams at the beginning
\newif{\ifdiagram}
\DeclareOption{diagram}{\diagramtrue}
@ -392,7 +401,9 @@
\renewcommand{\textnote}[2][]{%
\vspace{.1cm}
\IfStrEq{}{#1}{\@textnoteold{#2}}{
\iflanguage{#1}{\@textnoteold{#2}}{}
\IfStrEq{\mainlanguage}{#1}{
\@textnoteold{#2}
}{}
}
}
@ -400,7 +411,9 @@
\renewcommand{\musicnote}[2][]{%
\vspace{.1cm}
\IfStrEq{}{#1}{\@musicnoteold{#2}}{
\iflanguage{#1}{\@musicnoteold{#2}}{}
\IfStrEq{\mainlanguage}{#1}{
\@musicnoteold{#2}
}{}
}
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

7
patacrep/index.py

@ -16,8 +16,8 @@ from patacrep.latex import tex2plain
EOL = "\n"
# Pattern set to ignore latex command in title prefix
KEYWORD_PATTERN = re.compile(r"^%(\w+)\s?(.*)$", re.LOCALE)
FIRST_LETTER_PATTERN = re.compile(r"^(?:\{?\\\w+\}?)*[^\w]*(\w)", re.LOCALE)
KEYWORD_PATTERN = re.compile(r"^%(\w+)\s?(.*)$")
FIRST_LETTER_PATTERN = re.compile(r"^(?:\{?\\\w+\}?)*[^\w]*(\w)")
def process_sxd(filename):
"""Parse sxd file.
@ -90,8 +90,7 @@ class Index:
if 'prefix' in self.keywords:
for prefix in self.keywords['prefix']:
self.prefix_patterns.append(re.compile(
r"^({prefix})(\b|\\)(\s*.*)$".format(prefix=prefix),
re.LOCALE
r"^({prefix})(\b|\\)(\s*.*)$".format(prefix=prefix)
))
if self.indextype == "AUTHOR":

4
patacrep/latex/__init__.py

@ -16,7 +16,7 @@ LOGGER = logging.getLogger(__name__)
DEFAULT_LANGUAGE = "en_us"
BABEL_LANGUAGES = OrderedDict((
('de_de', 'german'),
('de_de', 'ngerman'), # german (old), germanb (like german)
('de_at', 'austrian'),
('eo_uy', 'esperanto'),
('en_us', 'english'), # USenglish, american
@ -53,8 +53,6 @@ BABEL_LANGUAGES = OrderedDict((
# ('??_??', 'finnish'),
# ('??_??', 'acadian'),
# ('??_??', 'galician'),
# ('??_??', 'germanb'),
# ('??_??', 'ngerman'),
# ('??_??', 'naustrian'),
# ('??_??', 'greek'),
# ('??_??', 'polutonikogreek'),

2
patacrep/songs/__init__.py

@ -294,7 +294,7 @@ def unprefixed_title(title, prefixes):
"""Remove the first prefix of the list in the beginning of title (if any).
"""
for prefix in prefixes:
match = re.compile(r"^(%s)\b\s*(.*)$" % prefix, re.LOCALE).match(title)
match = re.compile(r"^(%s)\b\s*(.*)$" % prefix).match(title)
if match:
return match.group(2)
return title

77
patacrep/songs/chordpro/__init__.py

@ -3,6 +3,7 @@
import logging
import operator
import os
import urllib
from jinja2 import Environment, FileSystemLoader, ChoiceLoader
from jinja2 import contextfunction
@ -30,6 +31,13 @@ class ChordproSong(Song):
# pylint: disable=abstract-method
output_language = None
_translation_map = {}
_translation_map_url = None
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if self._translation_map_url is None:
self._translation_map_url = self._translation_map
def _parse(self):
"""Parse content, and return the dictionary of song data."""
@ -50,6 +58,8 @@ class ChordproSong(Song):
filters.update({
'search_image': self.search_image,
'search_partition': self.search_partition,
'escape_specials': self._escape_specials,
'escape_url': self._escape_url,
})
return filters
@ -84,6 +94,20 @@ class ChordproSong(Song):
context.vars['content'] = content
return context.environment.get_template(content.template()).render(context)
def _escape_specials(self, content, chars=None, *, translation_map=None):
if translation_map is None:
translation_map = self._translation_map
if chars is None:
chars = translation_map.keys()
return str(content).translate(str.maketrans({
key: value
for key, value in translation_map.items()
if key in chars
}))
def _escape_url(self, content):
return self._escape_specials(content, translation_map=self._translation_map_url)
class Chordpro2HtmlSong(ChordproSong):
"""Render chordpro song to html code"""
@ -104,6 +128,25 @@ class Chordpro2LatexSong(ChordproSong):
"""Render chordpro song to latex code"""
output_language = "latex"
_translation_map = {
'{': r'\{',
'}': r'\}',
'\\': r'\textbackslash{}',
'^': r'\textasciicircum{}',
'~': r'\textasciitilde{}',
'#': r'\#',
'&': r'\&',
'$': r'\$',
'%': r'\%',
'_': r'\_',
}
_translation_map_url = {
" ": urllib.parse.quote(" "),
"{": urllib.parse.quote("{"),
"}": urllib.parse.quote("}"),
'%': r'\%',
'#': r'\#',
}
def search_file(self, filename, extensions=None, *, datadirs=None):
_datadir, filename, _extension = self.search_datadir_file(
@ -139,6 +182,7 @@ class Chordpro2LatexSong(ChordproSong):
parent = super()._filters()
parent.update({
'lang2babel': self.lang2babel,
'render_size': self._render_size,
})
return parent
@ -160,15 +204,48 @@ class Chordpro2LatexSong(ChordproSong):
self.errors.append(new_error)
return error.babel
@staticmethod
def _render_size(size):
items = []
for name, value, unit in size:
items.append(name + "=" + value + unit)
return ", ".join(items)
class Chordpro2ChordproSong(ChordproSong):
"""Render chordpro song to chordpro code"""
output_language = "chordpro"
_translation_map = {
'{': r'\{',
'}': r'\}',
'\\': '\\\\',
'#': r'\#',
}
_translation_map_url = {
'{': r'\{',
'}': r'\}',
'\\': '\\\\',
}
def _filters(self):
parent = super()._filters()
parent.update({
'render_size': self._render_size,
})
return parent
def search_file(self, filename, extensions=None, *, datadirs=None):
# pylint: disable=unused-variable
return filename
@staticmethod
def _render_size(size):
items = []
for name, value, unit in size:
items.append(name + "=" + value + unit)
return " ".join(items)
SONG_RENDERERS = {
"tsg": {
'csg': Chordpro2LatexSong,

16
patacrep/songs/chordpro/ast.py

@ -405,6 +405,22 @@ class Define(Directive):
def __str__(self):
return None
class Image(Directive):
"""An image
.. attribute:: filename
The filename of the image.
.. attribute:: size
An iterable of tuples ``(type, float, unit)``.
"""
def __init__(self, filename, size=None):
self.filename = filename
if size is None:
size = []
self.size = size
super().__init__("image", None)
class Tab(AST):
"""Tablature"""

18
patacrep/songs/chordpro/lexer.py

@ -49,7 +49,7 @@ class ChordProLexer:
t_directive_SPACE = r'[ \t]+'
t_directive_KEYWORD = r'[a-zA-Z_]+'
t_directiveargument_TEXT = r'[^}]+'
t_directiveargument_TEXT = r'[^\\}]+'
@staticmethod
def t_SOC(token):
@ -118,7 +118,7 @@ class ChordProLexer:
@staticmethod
def t_WORD(token):
r'[^{}\r\n\]\[\t ]+'
r'[^{}\\\r\n\]\[\t ]+'
return token
def t_LBRACKET(self, __token):
@ -150,6 +150,20 @@ class ChordProLexer:
self.lexer.push_state('directiveargument')
return token
@staticmethod
def t_ESCAPED(token):
r'\\[{} #\\]'
token.value = token.value[1]
token.type = "WORD"
return token
@staticmethod
def t_directiveargument_ESCAPED(token):
r'\\[{} #\\]'
token.value = token.value[1]
token.type = "TEXT"
return token
def error(self, token, more=""):
"""Display error message, and skip illegal token."""
message = "Illegal character '{char}'{more}.".format(

89
patacrep/songs/chordpro/syntax.py

@ -2,6 +2,7 @@
import logging
import re
import shlex
import ply.yacc as yacc
@ -124,10 +125,67 @@ class ChordproParser(Parser):
fingers=fingers,
)
def _iter_raw_image_size_arguments(self, arguments, *, lineno):
for item in arguments:
prefix, _, suffix = item.partition("=")
if prefix in ['width', 'height']:
match = re.compile(
r"^(?P<value>(\d*\.\d+|\d+))(?P<unit>cm|em|pt)$",
re.VERBOSE,
).match(suffix)
if match is not None:
yield (prefix, match.groupdict()['value'], match.groupdict()['unit'])
continue
elif prefix in ['scale']:
match = re.compile(
r"^(?P<value>(\d*\.\d+|\d+))$",
re.VERBOSE,
).match(suffix)
if match is not None:
yield (prefix, match.groupdict()['value'], "")
continue
else:
self.error(
line=lineno,
message="Image: Unknown argument name '{}'.".format(prefix),
)
continue
self.error(
line=lineno,
message="Image: Unsupported {} value: '{}'.".format(prefix, suffix),
)
def _iter_image_size_arguments(self, argument, *, lineno):
arguments = set()
length_names = frozenset(["width", "height"])
for name, value, unit in self._iter_raw_image_size_arguments(argument, lineno=lineno):
if name in arguments:
self.error(
line=lineno,
message="Image: Ignoring repeated argument: {}.".format(name),
)
continue
if (
name == "scale" and not length_names.isdisjoint(arguments)
) or (
name in length_names and "scale" in arguments
):
self.error(
line=lineno,
message=(
"Image: Ignoring '{}' argument: Cannot mix scale and "
"width or height argument."
).format(name),
)
continue
arguments.add(name)
yield name, value, unit
def p_directive(self, symbols):
"""directive : LBRACE KEYWORD directive_next RBRACE
| LBRACE SPACE KEYWORD directive_next RBRACE
"""
# pylint: disable=too-many-branches
if len(symbols) == 5:
keyword = symbols[2]
argument = symbols[3]
@ -171,7 +229,21 @@ class ChordproParser(Parser):
symbols[0] = ast.Error()
return
self._directives.append(define)
elif keyword == "image":
splitted = shlex.split(argument)
if len(splitted) < 1:
self.error(
line=symbols.lexer.lineno,
message="Missing filename for image directive",
)
symbols[0] = ast.Error()
else:
symbols[0] = ast.Image(
splitted[0],
list(
self._iter_image_size_arguments(splitted[1:], lineno=symbols.lexer.lineno)
),
)
else:
directive = ast.Directive(keyword, argument)
if directive.inline:
@ -182,9 +254,8 @@ class ChordproParser(Parser):
@staticmethod
def p_directive_next(symbols):
"""directive_next : SPACE COLON TEXT
| COLON TEXT
| COLON
"""directive_next : SPACE COLON directive_argument
| COLON directive_argument
| empty
"""
if len(symbols) == 3:
@ -196,6 +267,16 @@ class ChordproParser(Parser):
else:
symbols[0] = None
@staticmethod
def p_directive_argument(symbols):
"""directive_argument : TEXT directive_argument
| empty
"""
if len(symbols) == 3:
symbols[0] = symbols[1] + symbols[2]
else:
symbols[0] = ""
def p_line_error(self, symbols):
"""line_error : error directive"""
self.error(

59
patacrep/templates.py

@ -2,6 +2,7 @@
import logging
import re
import urllib
import yaml
@ -16,15 +17,6 @@ import patacrep.encoding
LOGGER = logging.getLogger(__name__)
_LATEX_SUBS = (
(re.compile(r'\\'), r'\\textbackslash'),
(re.compile(r'([{}_#%&$])'), r'\\\1'),
(re.compile(r'~'), r'\~{}'),
(re.compile(r'\^'), r'\^{}'),
(re.compile(r'"'), r"''"),
(re.compile(r'\.\.\.+'), r'\\ldots'),
)
_VARIABLE_REGEXP = re.compile(
r"""
\(\*-?\ *variables\ *\*\) # Match (* variables *) or (*- variables *)
@ -46,15 +38,47 @@ _VARIABLE_REGEXP = re.compile(
""",
re.VERBOSE|re.DOTALL)
def _escape_tex(value):
TRANSLATION_MAP = {
'{': r'\{',
'}': r'\}',
'\\': r'\textbackslash{}',
'^': r'\textasciicircum{}',
'~': r'\textasciitilde{}',
'#': r'\#',
'&': r'\&',
'$': r'\$',
'%': r'\%',
'_': r'\_',
}
TRANSLATION_MAP_URL = {
' ': '\\' + urllib.parse.quote(" "),
'{': '\\' + urllib.parse.quote("{"),
'}': '\\' + urllib.parse.quote("}"),
'%': '\\%',
'\\': '\\\\',
'#': '\\#',
'&': '\\&',
}
def _escape_specials(text, *, chars=None, translation_map=None):
'''Escape TeX special characters'''
newval = value
for pattern, replacement in _LATEX_SUBS:
newval = pattern.sub(replacement, newval)
return newval
if translation_map is None:
translation_map = TRANSLATION_MAP
if chars is None:
chars = translation_map.keys()
return str(text).translate(str.maketrans({
key: value
for key, value in translation_map.items()
if key in chars
}))
def _escape_url(text):
"""Escape TeX special characters, in url."""
return _escape_specials(text, translation_map=TRANSLATION_MAP_URL)
DEFAULT_FILTERS = {
"escape_tex": _escape_tex,
"escape_specials": _escape_specials,
"escape_url": _escape_url,
"iter_datadirs": files.iter_datadirs,
"path2posix": files.path2posix,
}
@ -296,4 +320,9 @@ def iter_bookoptions(config):
elif config['chords']['diagramreminder'] == "all":
yield 'diagram'
if config['chords']['diagrampage'] == "important":
yield 'diagrampagereduced'
elif config['chords']['diagrampage'] == "all":
yield 'diagrampage'
yield config['chords']['instrument']

77
patacrep/tools/__main__.py

@ -2,85 +2,26 @@
"""Command line client to :mod:`tools`"""
import argparse
import logging
import operator
import os
import pkgutil
import re
import sys
import argdispatch
import patacrep
# Logging configuration
logging.basicConfig(level=logging.INFO)
LOGGER = logging.getLogger("patatools")
def _execlp(program, args):
"""Call :func:`os.execlp`, adding `program` as the first argument to itself."""
return os.execlp(program, program, *args)
def _iter_subcommands():
"""Iterate over subcommands.
The objects returned are tuples of:
- the name of the command;
- its description;
- the function to call to execute the subcommand.
"""
subcommands = []
# Get python subcommands
path = [os.path.join(item, "patacrep", "tools") for item in sys.path]
prefix = "patacrep.tools."
module_re = re.compile(r'{}(?P<subcommand>[^\.]*)\.__main__'.format(prefix))
for module_loader, name, _ in pkgutil.walk_packages(path, prefix):
match = module_re.match(name)
if match:
module = module_loader.find_module(match.string).load_module()
if hasattr(module, "SUBCOMMAND_DESCRIPTION"):
subcommands.append(match.groupdict()['subcommand'])
yield (
match.groupdict()['subcommand'],
getattr(module, "SUBCOMMAND_DESCRIPTION"),
module.main,
)
class ArgumentParser(argparse.ArgumentParser):
"""Proxy class to circumvent an :mod:`argparse` bug.
Contrarily to what documented, the `argparse.REMAINDER
<https://docs.python.org/3/library/argparse.html#nargs>`_ `nargs` setting
does not include the remainder arguments if the first one begins with `-`.
This bug is reperted as `17050 <https://bugs.python.org/issue17050>`_. This
class can be deleted once this bug has been fixed.
"""
def parse_args(self, args=None, namespace=None):
if args is None:
args = sys.argv[1:]
subcommands = [command[0] for command in set(_iter_subcommands())]
if len(args) > 0:
if args[0] in subcommands:
args = [args[0], "--"] + args[1:]
value = super().parse_args(args, namespace)
if hasattr(value, 'remainder'):
value.remainder = value.remainder[1:]
return value
def commandline_parser():
"""Return a command line parser."""
parser = ArgumentParser(
parser = argdispatch.ArgumentParser(
prog="patatools",
description=(
"Miscellaneous tools for patacrep."
),
formatter_class=argparse.RawTextHelpFormatter,
formatter_class=argdispatch.RawTextHelpFormatter,
)
parser.add_argument(
@ -96,11 +37,7 @@ def commandline_parser():
)
subparsers.required = True
subparsers.dest = "subcommand"
for command, message, function in sorted(_iter_subcommands(), key=operator.itemgetter(0)):
sub1 = subparsers.add_parser(command, help=message, add_help=False)
sub1.add_argument('remainder', nargs=argparse.REMAINDER)
sub1.set_defaults(function=function)
subparsers.add_submodules("patacrep.tools")
return parser
@ -108,9 +45,7 @@ def main(args=None):
"""Main function"""
if args is None:
args = sys.argv
parser = commandline_parser()
args = parser.parse_args(args[1:])
args.function(["patatools-{}".format(args.subcommand)] + args.remainder)
commandline_parser().parse_args(args[1:])
if __name__ == "__main__":
main()

5
patacrep/tools/cache/__main__.py

@ -1,4 +1,4 @@
"""`patatools cache` command: cache manipulation."""
"""Perform operations on cache."""
import argparse
import logging
@ -11,7 +11,6 @@ from patacrep import errors
from patacrep.songbook import open_songbook
LOGGER = logging.getLogger("patatools.cache")
SUBCOMMAND_DESCRIPTION = "Perform operations on cache."
def filename(name):
"""Check that argument is an existing, readable file name.
@ -27,7 +26,7 @@ def commandline_parser():
parser = argparse.ArgumentParser(
prog="patatools cache",
description=SUBCOMMAND_DESCRIPTION,
description="Convert between song formats.",
formatter_class=argparse.RawTextHelpFormatter,
)

3
patacrep/tools/convert/__main__.py

@ -1,4 +1,4 @@
"""`patatools.convert` command: convert between song formats"""
"""Convert between song formats."""
import os
import logging
@ -10,7 +10,6 @@ from patacrep.utils import yesno
from patacrep.build import config_model
LOGGER = logging.getLogger("patatools.convert")
SUBCOMMAND_DESCRIPTION = "Convert between song formats"
def _usage():
return "patatools convert INPUTFORMAT OUTPUTFORMAT FILES"

2
setup.py

@ -34,7 +34,7 @@ setup(
packages=find_packages(exclude=["test*"]),
license="GPLv2 or any later version",
install_requires=[
"unidecode", "jinja2", "ply", "pyyaml",
"argdispatch", "unidecode", "jinja2", "ply", "pyyaml",
],
entry_points={
'console_scripts': [

0
test/test_songbook/.gitignore → test/test_book/.gitignore

0
test/test_songbook/__init__.py → test/test_book/__init__.py

12
test/test_songbook/content.tex.control → test/test_book/content.tex.control

@ -26,6 +26,7 @@
chorded,
pictures,
diagram,
diagrampage,
guitar,
]{patacrep}
@ -79,13 +80,12 @@ guitar,
\showindex{\authorindexname}{authidx}
% list of chords
\ifchorded
\ifdiagram
\phantomsection
\addcontentsline{toc}{section}{\chordlistname}
\chords
\fi
\ifdiagrampage
\phantomsection
\addcontentsline{toc}{section}{\chordlistname}
\chords
\fi
\setcounter{songnum}{1}%
\phantomsection
\addcontentsline{toc}{section}{\songlistname}

0
test/test_songbook/content.yaml → test/test_book/content.yaml

0
test/test_songbook/content_datadir/content/foo.tex → test/test_book/content_datadir/content/foo.tex

0
test/test_songbook/content_datadir/content/inter.isg → test/test_book/content_datadir/content/inter.isg

0
test/test_songbook/content_datadir/content/song.csg → test/test_book/content_datadir/content/song.csg

0
test/test_songbook/content_datadir/content/song.tsg → test/test_book/content_datadir/content/song.tsg

0
test/test_songbook/content_datadir/songs/include.sbc → test/test_book/content_datadir/songs/include.sbc

0
test/test_songbook/content_datadir/songs/inter.isg → test/test_book/content_datadir/songs/inter.isg

0
test/test_songbook/content_datadir/songs/song.csg → test/test_book/content_datadir/songs/song.csg

0
test/test_songbook/content_datadir/songs/song.tsg → test/test_book/content_datadir/songs/song.tsg

20
test/test_songbook/datadir.tex.control → test/test_book/datadir.tex.control

@ -28,6 +28,7 @@ chorded,
pictures,
repeatchords,
importantdiagramonly,
diagrampage,
guitar,
]{patacrep}
@ -82,13 +83,12 @@ guitar,
\showindex{\authorindexname}{authidx}
% list of chords
\ifchorded
\ifdiagram
\phantomsection
\addcontentsline{toc}{section}{\chordlistname}
\chords
\fi
\ifdiagrampage
\phantomsection
\addcontentsline{toc}{section}{\chordlistname}
\chords
\fi
\setcounter{songnum}{1}%
\phantomsection
\addcontentsline{toc}{section}{\songlistname}
@ -111,7 +111,7 @@ Chordpro}[
\lilypond{scores/datadir.ly}
\image{img/datadir.png}
\image[]{img/datadir.png}
\endsong
@ -138,7 +138,7 @@ Chordpro}[
\lilypond{scores/datadir2.ly}
\image{img/datadir2.png}
\image[]{img/datadir2.png}
\endsong
@ -165,7 +165,7 @@ Chordpro}[
\lilypond{@TEST_FOLDER@/datadir_datadir/songs/./relative.ly}
\image{@TEST_FOLDER@/datadir_datadir/songs/./relative.png}
\image[]{@TEST_FOLDER@/datadir_datadir/songs/./relative.png}
\endsong
@ -192,7 +192,7 @@ Chordpro}[
\lilypond{@TEST_FOLDER@/datadir_datadir/songs/./subdir/subdir.ly}
\image{@TEST_FOLDER@/datadir_datadir/songs/./subdir/subdir.png}
\image[]{@TEST_FOLDER@/datadir_datadir/songs/./subdir/subdir.png}
\endsong

0
test/test_songbook/datadir.yaml → test/test_book/datadir.yaml

0
test/test_songbook/datadir_datadir/img/datadir.png → test/test_book/datadir_datadir/img/datadir.png

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

0
test/test_songbook/datadir_datadir/scores/datadir.ly → test/test_book/datadir_datadir/scores/datadir.ly

0
test/test_songbook/datadir_datadir/songs/datadir.csg → test/test_book/datadir_datadir/songs/datadir.csg

0
test/test_songbook/datadir_datadir/songs/datadir.tsg → test/test_book/datadir_datadir/songs/datadir.tsg

0
test/test_songbook/datadir_datadir/songs/datadir2.csg → test/test_book/datadir_datadir/songs/datadir2.csg

0
test/test_songbook/datadir_datadir/songs/datadir2.sg → test/test_book/datadir_datadir/songs/datadir2.sg

0
test/test_songbook/datadir_datadir/songs/relative.csg → test/test_book/datadir_datadir/songs/relative.csg

0
test/test_songbook/datadir_datadir/songs/relative.ly → test/test_book/datadir_datadir/songs/relative.ly

0
test/test_songbook/datadir_datadir/songs/relative.png → test/test_book/datadir_datadir/songs/relative.png

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

0
test/test_songbook/datadir_datadir/songs/relative.tsg → test/test_book/datadir_datadir/songs/relative.tsg

0
test/test_songbook/datadir_datadir/songs/subdir/subdir.csg → test/test_book/datadir_datadir/songs/subdir/subdir.csg

0
test/test_songbook/datadir_datadir/songs/subdir/subdir.ly → test/test_book/datadir_datadir/songs/subdir/subdir.ly

0
test/test_songbook/datadir_datadir/songs/subdir/subdir.png → test/test_book/datadir_datadir/songs/subdir/subdir.png

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

0
test/test_songbook/datadir_datadir/songs/subdir/subdir.tsg → test/test_book/datadir_datadir/songs/subdir/subdir.tsg

0
test/test_songbook/datadir_datadir2/img/datadir2.png → test/test_book/datadir_datadir2/img/datadir2.png

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

0
test/test_songbook/datadir_datadir2/scores/datadir2.ly → test/test_book/datadir_datadir2/scores/datadir2.ly

131
test/test_book/lang_de.tex.control

@ -0,0 +1,131 @@
%% Automatically generated document.
%% You may edit this file but all changes will be overwritten.
%% If you want to change this document, have a look at
%% the templating system.
%%
%% Generated using Songbook <http://www.patacrep.com>
\makeatletter
\def\input@path{ %
{@TEST_FOLDER@/templates/styles/} %
{@DATA_FOLDER@/templates/styles/} %
}
\makeatother
\documentclass[
]{article}
\usepackage[
chorded,
pictures,
repeatchords,
importantdiagramonly,
diagrampage,
guitar,
]{crepbook}
\usepackage[
a4paper % paper size
,includeheadfoot % include header and footer into text size
,hmarginratio=1:1 % ratio between inner and outer margin (default)
,outer=1.8cm % outer margin (right)
,vmarginratio=1:1 % ratio between top and bottom margin
,bmargin=1.3cm % bottom margin
]{geometry}
\usepackage{lmodern}
\usepackage[ngerman]{babel}
\lang{ngerman}
\usepackage{graphicx}
\graphicspath{ %
{@TEST_FOLDER@/} %
{@DATA_FOLDER@/} %
}
\makeatletter
\@ifpackageloaded{hyperref}{}{
\usepackage{url}
\newcommand{\phantomsection}{}
\newcommand{\hyperlink}[2]{#2}
\newcommand{\href}[2]{\expandafter\url\expandafter{#1}}
}
\makeatother
\usepackage{chords}
\title{Guitar songbook}
\author{The Patacrep Team}
\newindex{titleidx}{lang_de_title}
\newauthorindex{authidx}{lang_de_auth}
\authignoreword{unknown}
\authbyword{by}
\authsepword{and}
\notenamesout{A}{B}{C}{D}{E}{F}{G}
\pagestyle{empty}\definecolor{SongNumberBgColor}{HTML}{D1E4AE}
\definecolor{NoteBgColor}{HTML}{D1E4AE}
\definecolor{IndexBgColor}{HTML}{D1E4AE}
\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}
\subtitle{}
\mail{crep@team-on-fire.com}
\web{http://www.patacrep.com}
\picture{img/treble_a}
\picturecopyright{Dbolton \url{http://commons.wikimedia.org/wiki/User:Dbolton}}
\footer{Generated using Songbook (\url{http://www.patacrep.com})}
\begin{document}
\maketitle
\showindex{\songindexname}{titleidx}
\showindex{\authorindexname}{authidx}
% list of chords
\ifdiagrampage
\phantomsection
\addcontentsline{toc}{section}{\chordlistname}
\chords
\fi
\setcounter{songnum}{1}%
\phantomsection
\addcontentsline{toc}{section}{\songlistname}
\end{document}

5
test/test_book/lang_de.yaml

@ -0,0 +1,5 @@
book:
lang: de
content:
- sort:

12
test/test_songbook/lang_default.tex.control → test/test_book/lang_default.tex.control

@ -26,6 +26,7 @@ chorded,
pictures,
repeatchords,
importantdiagramonly,
diagrampage,
guitar,
]{crepbook}
@ -113,13 +114,12 @@ guitar,
\showindex{\authorindexname}{authidx}
% list of chords
\ifchorded
\ifdiagram
\phantomsection
\addcontentsline{toc}{section}{\chordlistname}
\chords
\fi
\ifdiagrampage
\phantomsection
\addcontentsline{toc}{section}{\chordlistname}
\chords
\fi
\setcounter{songnum}{1}%
\phantomsection
\addcontentsline{toc}{section}{\songlistname}

0
test/test_songbook/lang_default.yaml → test/test_book/lang_default.yaml

12
test/test_songbook/lang_en.tex.control → test/test_book/lang_en.tex.control

@ -26,6 +26,7 @@ chorded,
pictures,
repeatchords,
importantdiagramonly,
diagrampage,
guitar,
]{crepbook}
@ -113,13 +114,12 @@ guitar,
\showindex{\authorindexname}{authidx}
% list of chords
\ifchorded
\ifdiagram
\phantomsection
\addcontentsline{toc}{section}{\chordlistname}
\chords
\fi
\ifdiagrampage
\phantomsection
\addcontentsline{toc}{section}{\chordlistname}
\chords
\fi
\setcounter{songnum}{1}%
\phantomsection
\addcontentsline{toc}{section}{\songlistname}

0
test/test_songbook/lang_en.yaml → test/test_book/lang_en.yaml

12
test/test_songbook/lang_fr.tex.control → test/test_book/lang_fr.tex.control

@ -26,6 +26,7 @@ chorded,
pictures,
repeatchords,
importantdiagramonly,
diagrampage,
guitar,
]{crepbook}
@ -113,13 +114,12 @@ guitar,
\showindex{\authorindexname}{authidx}
% list of chords
\ifchorded
\ifdiagram
\phantomsection
\addcontentsline{toc}{section}{\chordlistname}
\chords
\fi
\ifdiagrampage
\phantomsection
\addcontentsline{toc}{section}{\chordlistname}
\chords
\fi
\setcounter{songnum}{1}%
\phantomsection
\addcontentsline{toc}{section}{\songlistname}

0
test/test_songbook/lang_fr.yaml → test/test_book/lang_fr.yaml

12
test/test_songbook/languages.tex.control → test/test_book/languages.tex.control

@ -27,6 +27,7 @@ chorded,
pictures,
repeatchords,
importantdiagramonly,
diagrampage,
guitar,
]{patacrep}
@ -82,13 +83,12 @@ guitar,
\showindex{\authorindexname}{authidx}
% list of chords
\ifchorded
\ifdiagram
\phantomsection
\addcontentsline{toc}{section}{\chordlistname}
\chords
\fi
\ifdiagrampage
\phantomsection
\addcontentsline{toc}{section}{\chordlistname}
\chords
\fi
\setcounter{songnum}{1}%
\phantomsection
\addcontentsline{toc}{section}{\songlistname}

0
test/test_songbook/languages.yaml → test/test_book/languages.yaml

0
test/test_songbook/languages_datadir/songs/language.csg → test/test_book/languages_datadir/songs/language.csg

0
test/test_songbook/languages_datadir/songs/language_location.csg → test/test_book/languages_datadir/songs/language_location.csg

0
test/test_songbook/languages_datadir/songs/no_language.csg → test/test_book/languages_datadir/songs/no_language.csg

0
test/test_songbook/languages_datadir/songs/wrong_language.csg → test/test_book/languages_datadir/songs/wrong_language.csg

0
test/test_songbook/languages_datadir/songs/wrong_location.csg → test/test_book/languages_datadir/songs/wrong_location.csg

12
test/test_songbook/onthefly/content.onthefly.tex.control → test/test_book/onthefly/content.onthefly.tex.control

@ -25,6 +25,7 @@
chorded,
pictures,
diagram,
diagrampage,
guitar,
]{patacrep}
@ -77,13 +78,12 @@ guitar,
\showindex{\authorindexname}{authidx}
% list of chords
\ifchorded
\ifdiagram
\phantomsection
\addcontentsline{toc}{section}{\chordlistname}
\chords
\fi
\ifdiagrampage
\phantomsection
\addcontentsline{toc}{section}{\chordlistname}
\chords
\fi
\setcounter{songnum}{1}%
\phantomsection
\addcontentsline{toc}{section}{\songlistname}

0
test/test_songbook/onthefly/content.onthefly.yaml → test/test_book/onthefly/content.onthefly.yaml

162
test/test_book/special.tex.control

@ -0,0 +1,162 @@
%% Automatically generated document.
%% You may edit this file but all changes will be overwritten.
%% If you want to change this document, have a look at
%% the templating system.
%%
%% Generated using Songbook <http://www.patacrep.com>
\makeatletter
\def\input@path{ %
{@TEST_FOLDER@/special_datadir/templates/styles/} %
{@TEST_FOLDER@/templates/styles/} %
{@DATA_FOLDER@/templates/styles/} %
}
\makeatother
\documentclass[
]{article}
\usepackage[
chorded,
pictures,
repeatchords,
importantdiagramonly,
diagrampage,
guitar,
]{crepbook}
\usepackage[
a4paper % paper size
,includeheadfoot % include header and footer into text size
,hmarginratio=1:1 % ratio between inner and outer margin (default)
,outer=1.8cm % outer margin (right)
,vmarginratio=1:1 % ratio between top and bottom margin
,bmargin=1.3cm % bottom margin
]{geometry}
\usepackage{lmodern}
\PassOptionsToPackage{english}{babel}
\usepackage[english]{babel}
\lang{english}
\usepackage{graphicx}
\graphicspath{ %
{@TEST_FOLDER@/special_datadir/} %
{@TEST_FOLDER@/} %
{@DATA_FOLDER@/} %
}
\makeatletter
\@ifpackageloaded{hyperref}{}{
\usepackage{url}
\newcommand{\phantomsection}{}
\newcommand{\hyperlink}[2]{#2}
\newcommand{\href}[2]{\expandafter\url\expandafter{#1}}
}
\makeatother
\usepackage{chords}
\title{\& \% \$ \# \_ \} \{ \textasciitilde{} \textasciicircum{} \textbackslash{}}
\author{\& \% \$ \# \_ \} \{ \textasciitilde{} \textasciicircum{} \textbackslash{}}
\newindex{titleidx}{special_title}
\newauthorindex{authidx}{special_auth}
\authignoreword{unknown}
\authbyword{by}
\authsepword{and}
\notenamesout{A}{B}{C}{D}{E}{F}{G}
\pagestyle{empty}\definecolor{SongNumberBgColor}{HTML}{D1E4AE}
\definecolor{NoteBgColor}{HTML}{D1E4AE}
\definecolor{IndexBgColor}{HTML}{D1E4AE}
\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}
\subtitle{\& \% \$ \# \_ \} \{ \textasciitilde{} \textasciicircum{} \textbackslash{}}
\mail{foo@\\\%\&$\#_~^\%20\%7B\%7D}
\web{http://\\\%\&$\#_~^\%20\%7B\%7D}
\picture{img/treble_a}
\picturecopyright{Dbolton \url{http://commons.wikimedia.org/wiki/User:Dbolton}}
\footer{Generated using Songbook (\url{http://www.patacrep.com})}
\begin{document}
\maketitle
\showindex{\songindexname}{titleidx}
\showindex{\authorindexname}{authidx}
% list of chords
\ifdiagrampage
\phantomsection
\addcontentsline{toc}{section}{\chordlistname}
\chords
\fi
\setcounter{songnum}{1}%
\phantomsection
\addcontentsline{toc}{section}{\songlistname}
\begin{songs}{titleidx,authidx}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% songs/./special.csg
\selectlanguage{english}
\beginsong{\& \$ \% \# \_ \} \{ \textasciitilde{} \textasciicircum{} \textbackslash{}}[
by={
\& \$ \% \# \_ \} \{ \textasciitilde{} \textasciicircum{} \textbackslash{} },
album={\& \$ \% \# \_ \} \{ \textasciitilde{} \textasciicircum{} \textbackslash{}},
url={http://&$\%\#_~^},
]
\begin{verse}
\& \$ \% \# \_ \} \{ \textasciitilde{} \textasciicircum{} \textbackslash{}
\end{verse}
\begin{chorus}
\& \$ \% \# \_ \} \{ \textasciitilde{} \textasciicircum{} \textbackslash{}
\end{chorus}
\endsong
\end{songs}
\end{document}

14
test/test_book/special.yaml

@ -0,0 +1,14 @@
book:
datadir:
- special_datadir
template:
default.tex:
title: "& % $ # _ } { ~ ^ \\"
author: "& % $ # _ } { ~ ^ \\"
patacrep.tex:
subtitle: "& % $ # _ } { ~ ^ \\"
url: "http://\\%&$#_~^ {}"
email: "foo@\\%&$#_~^ {}"
picture: "img/treble_a"

10
test/test_book/special_datadir/songs/special.csg

@ -0,0 +1,10 @@
{title: & $ % # _ \} \{ ~ ^ \\}
{artist: & $ % # _ \} \{ ~ ^ \\}
{album: & $ % # _ \} \{ ~ ^ \\}
{url: http://&$%#_~^}
& $ % \# _ \} \{ ~ ^ \\
{start_of_chorus}
& $ % \# _ \} \{ ~ ^ \\
{end_of_chorus}

79
test/test_songbook/syntax.tex.control → test/test_book/syntax.tex.control

@ -2,8 +2,6 @@
%% Automatically generated document.
%% You may edit this file but all changes will be overwritten.
%% If you want to change this document, have a look at
@ -27,6 +25,7 @@ chorded,
pictures,
repeatchords,
importantdiagramonly,
diagrampage,
guitar,
]{patacrep}
@ -79,18 +78,80 @@ guitar,
\showindex{\authorindexname}{authidx}
% list of chords
\ifchorded
\ifdiagram
\phantomsection
\addcontentsline{toc}{section}{\chordlistname}
\chords
\fi
\ifdiagrampage
\phantomsection
\addcontentsline{toc}{section}{\chordlistname}
\chords
\fi
\setcounter{songnum}{1}%
\phantomsection
\addcontentsline{toc}{section}{\songlistname}
\begin{songs}{titleidx,authidx}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% songs/./images.csg
\selectlanguage{english}
\beginsong{}[
by={
},
]
\image[]{img/image.png}
\image[]{img/image with spaces.png}
\image[scale=2]{img/image.png}
\image[scale=.20]{img/image with spaces.png}
\image[scale=1.2]{img/image.png}
\image[width=2cm]{img/image.png}
\image[height=2cm]{img/image with spaces.png}
\image[width=2cm, height=1cm]{img/image.png}
\image[width=2em]{img/image.png}
\image[height=2em]{img/image with spaces.png}
\image[width=2em, height=1em]{img/image.png}
\image[width=50pt]{img/image.png}
\image[height=50pt]{img/image with spaces.png}
\image[width=50pt, height=100pt]{img/image.png}
\image[width=2.5cm]{img/image.png}
\image[height=2.5cm]{img/image with spaces.png}
\image[width=2.5cm, height=1.5cm]{img/image.png}
\image[width=3cm, height=10pt]{img/image.png}
\image[width=10pt, height=3cm]{img/image with spaces.png}
\image[]{img/image.png}
\image[]{img/image.png}
\image[]{img/image with spaces.png}
\image[]{img/image with spaces.png}
\image[]{img/image.png}
\image[width=2cm]{img/image.png}
\image[width=2cm]{img/image.png}
\image[width=2cm]{img/image.png}
\endsong
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% songs/./musicnote.csg
@ -117,4 +178,4 @@ guitar,
\end{document}
\end{document}

0
test/test_songbook/syntax.yaml → test/test_book/syntax.yaml

BIN
test/test_book/syntax_datadir/img/image with spaces.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

BIN
test/test_book/syntax_datadir/img/image.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

35
test/test_book/syntax_datadir/songs/images.csg

@ -0,0 +1,35 @@
{image: image.png}
{image: "image with spaces.png"}
{image: image.png scale=2 }
{image: "image with spaces.png" scale=.20}
{image: image.png scale=1.2}
{image: image.png width=2cm}
{image: "image with spaces.png" height=2cm}
{image: image.png width=2cm height=1cm}
{image: image.png width=2em}
{image: "image with spaces.png" height=2em}
{image: image.png width=2em height=1em}
{image: image.png width=50pt}
{image: "image with spaces.png" height=50pt}
{image: image.png width=50pt height=100pt}
{image: image.png width=2.5cm}
{image: "image with spaces.png" height=2.5cm}
{image: image.png width=2.5cm height=1.5cm}
{image: image.png width=3cm height=10pt}
{image: "image with spaces.png" width=10pt height=3cm}
{image: image.png width= height=}
{image: image.png error=foo}
{image: "image with spaces.png" not_a_size}
{image: "image with spaces.png" too many arguments}
{image: image.png width=2ex height=3km}
{image: image.png width=2cm width=3cm}
{image: image.png width=2cm scale=3cm}
{image: image.png width=2cm scale=3}
{image: }

0
test/test_songbook/syntax_datadir/songs/musicnote.csg → test/test_book/syntax_datadir/songs/musicnote.csg

0
test/test_songbook/test_compilation.py → test/test_book/test_compilation.py

12
test/test_songbook/unicode.tex.control → test/test_book/unicode.tex.control

@ -27,6 +27,7 @@ chorded,
pictures,
repeatchords,
importantdiagramonly,
diagrampage,
guitar,
]{patacrep}
@ -79,13 +80,12 @@ guitar,
\showindex{\authorindexname}{authidx}
% list of chords
\ifchorded
\ifdiagram
\phantomsection
\addcontentsline{toc}{section}{\chordlistname}
\chords
\fi
\ifdiagrampage
\phantomsection
\addcontentsline{toc}{section}{\chordlistname}
\chords
\fi
\setcounter{songnum}{1}%
\phantomsection
\addcontentsline{toc}{section}{\songlistname}

0
test/test_songbook/unicode.yaml → test/test_book/unicode.yaml

0
test/test_songbook/unicode_datadir/songs/nonbreak.csg → test/test_book/unicode_datadir/songs/nonbreak.csg

0
test/test_song/image with spaces.png

44
test/test_song/image.csg

@ -0,0 +1,44 @@
{lang: en}
{image: "image.png" }
{image: "image with spaces.png" }
{image: "image.png" scale=2}
{image: "image with spaces.png" scale=.20}
{image: "image.png" scale=1.2}
{image: "image.png" width=2cm}
{image: "image with spaces.png" height=2cm}
{image: "image.png" width=2cm height=1cm}
{image: "image.png" width=2em}
{image: "image with spaces.png" height=2em}
{image: "image.png" width=2em height=1em}
{image: "image.png" width=50pt}
{image: "image with spaces.png" height=50pt}
{image: "image.png" width=50pt height=100pt}
{image: "image.png" width=2.5cm}
{image: "image with spaces.png" height=2.5cm}
{image: "image.png" width=2.5cm height=1.5cm}
{image: "image.png" width=3cm height=10pt}
{image: "image with spaces.png" width=10pt height=3cm}
{image: "image.png" }
{image: "image.png" }
{image: "image with spaces.png" }
{image: "image with spaces.png" }
{image: "image.png" }
{image: "image.png" width=2cm}
{image: "image.png" width=2cm}
{image: "image.png" width=2cm}

35
test/test_song/image.csg.source

@ -0,0 +1,35 @@
{image: image.png}
{image: "image with spaces.png"}
{image: image.png scale=2 }
{image: "image with spaces.png" scale=.20}
{image: image.png scale=1.2}
{image: image.png width=2cm}
{image: "image with spaces.png" height=2cm}
{image: image.png width=2cm height=1cm}
{image: image.png width=2em}
{image: "image with spaces.png" height=2em}
{image: image.png width=2em height=1em}
{image: image.png width=50pt}
{image: "image with spaces.png" height=50pt}
{image: image.png width=50pt height=100pt}
{image: image.png width=2.5cm}
{image: "image with spaces.png" height=2.5cm}
{image: image.png width=2.5cm height=1.5cm}
{image: image.png width=3cm height=10pt}
{image: "image with spaces.png" width=10pt height=3cm}
{image: image.png width= height=}
{image: image.png error=foo}
{image: "image with spaces.png" not_a_size}
{image: "image with spaces.png" too many arguments}
{image: image.png width=2ex height=3km}
{image: image.png width=2cm width=3cm}
{image: image.png width=2cm scale=3cm}
{image: image.png width=2cm scale=3}
{image: }

0
test/test_song/image.png

59
test/test_song/image.tsg

@ -0,0 +1,59 @@
\selectlanguage{english}
\beginsong{}[
by={
},
]
\image[]{img/image.png}
\image[]{img/image with spaces.png}
\image[scale=2]{img/image.png}
\image[scale=.20]{img/image with spaces.png}
\image[scale=1.2]{img/image.png}
\image[width=2cm]{img/image.png}
\image[height=2cm]{img/image with spaces.png}
\image[width=2cm, height=1cm]{img/image.png}
\image[width=2em]{img/image.png}
\image[height=2em]{img/image with spaces.png}
\image[width=2em, height=1em]{img/image.png}
\image[width=50pt]{img/image.png}
\image[height=50pt]{img/image with spaces.png}
\image[width=50pt, height=100pt]{img/image.png}
\image[width=2.5cm]{img/image.png}
\image[height=2.5cm]{img/image with spaces.png}
\image[width=2.5cm, height=1.5cm]{img/image.png}
\image[width=3cm, height=10pt]{img/image.png}
\image[width=10pt, height=3cm]{img/image with spaces.png}
\image[]{img/image.png}
\image[]{img/image.png}
\image[]{img/image with spaces.png}
\image[]{img/image with spaces.png}
\image[]{img/image.png}
\image[width=2cm]{img/image.png}
\image[width=2cm]{img/image.png}
\image[width=2cm]{img/image.png}
\endsong

2
test/test_song/metadata.csg

@ -16,7 +16,7 @@
{comment: Comment}
{guitar_comment: GuitarComment}
{partition: metadata_lilypond}
{image: metadata_image}
{image: "metadata_image" }
Foo

2
test/test_song/metadata.tsg

@ -20,7 +20,7 @@ Subtitle5}[
\textnote{Comment}
\musicnote{GuitarComment}
\lilypond{scores/metadata_lilypond}
\image{img/metadata_image}
\image[]{img/metadata_image}

13
test/test_song/special.csg

@ -0,0 +1,13 @@
{lang: en}
{title: & $ % # _ \} \{ ~ ^ \\}
{artist: & $ % # _ \} \{ ~ ^ \\}
{album: & $ % # _ \} \{ ~ ^ \\}
{url: http://&$%#_~^}
& $ % \# _ \} \{ ~ ^ \\
{start_of_chorus}
& $ % \# _ \} \{ ~ ^ \\
{end_of_chorus}

10
test/test_song/special.csg.source

@ -0,0 +1,10 @@
{title: & $ % # _ \} \{ ~ ^ \\}
{artist: & $ % # _ \} \{ ~ ^ \\}
{album: & $ % # _ \} \{ ~ ^ \\}
{url: http://&$%#_~^}
& $ % \# _ \} \{ ~ ^ \\
{start_of_chorus}
& $ % \# _ \} \{ ~ ^ \\
{end_of_chorus}

22
test/test_song/special.tsg

@ -0,0 +1,22 @@
\selectlanguage{english}
\beginsong{\& \$ \% \# \_ \} \{ \textasciitilde{} \textasciicircum{} \textbackslash{}}[
by={
\& \$ \% \# \_ \} \{ \textasciitilde{} \textasciicircum{} \textbackslash{} },
album={\& \$ \% \# \_ \} \{ \textasciitilde{} \textasciicircum{} \textbackslash{}},
url={http://&$\%\#_~^},
]
\begin{verse}
\& \$ \% \# \_ \} \{ \textasciitilde{} \textasciicircum{} \textbackslash{}
\end{verse}
\begin{chorus}
\& \$ \% \# \_ \} \{ \textasciitilde{} \textasciicircum{} \textbackslash{}
\end{chorus}
\endsong
Loading…
Cancel
Save