lydown 0.9.0 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +159 -2
- data/lib/lydown.rb +8 -2
- data/lib/lydown/cache.rb +54 -0
- data/lib/lydown/cli.rb +1 -0
- data/lib/lydown/cli/commands.rb +27 -9
- data/lib/lydown/cli/compiler.rb +218 -54
- data/lib/lydown/cli/diff.rb +1 -1
- data/lib/lydown/cli/proofing.rb +3 -3
- data/lib/lydown/cli/signals.rb +23 -0
- data/lib/lydown/cli/support.rb +23 -1
- data/lib/lydown/core_ext.rb +41 -5
- data/lib/lydown/{rendering/defaults.yml → defaults.yml} +3 -3
- data/lib/lydown/errors.rb +3 -0
- data/lib/lydown/lilypond.rb +73 -31
- data/lib/lydown/ly_lib/lib.ly +297 -0
- data/lib/lydown/parsing.rb +1 -2
- data/lib/lydown/parsing/lydown.treetop +16 -10
- data/lib/lydown/parsing/nodes.rb +29 -5
- data/lib/lydown/rendering.rb +32 -6
- data/lib/lydown/rendering/command.rb +79 -2
- data/lib/lydown/rendering/figures.rb +29 -8
- data/lib/lydown/rendering/literal.rb +7 -0
- data/lib/lydown/rendering/movement.rb +61 -0
- data/lib/lydown/rendering/music.rb +37 -5
- data/lib/lydown/rendering/notes.rb +26 -8
- data/lib/lydown/rendering/settings.rb +41 -13
- data/lib/lydown/rendering/skipping.rb +43 -10
- data/lib/lydown/rendering/staff.rb +72 -16
- data/lib/lydown/templates.rb +8 -2
- data/lib/lydown/templates/lilypond_doc.erb +10 -1
- data/lib/lydown/templates/movement.erb +87 -34
- data/lib/lydown/templates/multi_voice.erb +1 -1
- data/lib/lydown/templates/part.erb +83 -55
- data/lib/lydown/templates/variables.erb +38 -0
- data/lib/lydown/version.rb +1 -1
- data/lib/lydown/work.rb +39 -26
- data/lib/lydown/work_context.rb +252 -14
- metadata +138 -8
- data/lib/lydown/rendering/lib.ly +0 -88
data/lib/lydown/cli/diff.rb
CHANGED
data/lib/lydown/cli/proofing.rb
CHANGED
@@ -77,7 +77,7 @@ module Lydown::CLI::Proofing
|
|
77
77
|
opts[:mode] = :score
|
78
78
|
else
|
79
79
|
opts[:parts] = [part]
|
80
|
-
opts[:mode] =
|
80
|
+
opts[:mode] = :proof
|
81
81
|
opts[:line_range] = Lydown::CLI::Diff.diff_line_range(path)
|
82
82
|
end
|
83
83
|
|
@@ -85,9 +85,9 @@ module Lydown::CLI::Proofing
|
|
85
85
|
end
|
86
86
|
|
87
87
|
def process(opts)
|
88
|
-
if opts[:line_range] !=
|
88
|
+
if opts[:line_range] != [nil, nil]
|
89
89
|
t = Time.now.strftime("%H:%M:%S")
|
90
|
-
$stderr.puts "[#{t}] Changed: #{opts[:base_path]} (lines #{opts[:line_range]
|
90
|
+
$stderr.puts "[#{t}] Changed: #{opts[:base_path]} (lines #{opts[:line_range][0]}..#{opts[:line_range][1]})"
|
91
91
|
Lydown::CLI::Compiler.process(opts)
|
92
92
|
end
|
93
93
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Lydown::CLI
|
2
|
+
@@abortable_child_processes = []
|
3
|
+
|
4
|
+
def self.abort
|
5
|
+
$stderr.puts
|
6
|
+
if pid = @@abortable_child_processes.last
|
7
|
+
Process.kill("INT", pid)
|
8
|
+
else
|
9
|
+
exit
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.register_abortable_process(pid)
|
14
|
+
@@abortable_child_processes << pid
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.unregister_abortable_process(pid)
|
18
|
+
@@abortable_child_processes.delete pid
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
Signal.trap("INT") {Lydown::CLI.abort}
|
23
|
+
Signal.trap("TERM") {exit}
|
data/lib/lydown/cli/support.rb
CHANGED
@@ -14,7 +14,7 @@ module Lydown::CLI::Support
|
|
14
14
|
|
15
15
|
# the output defaults to a file named lydown expect if the format is ly.
|
16
16
|
# In that case the output will be sent to STDOUT.
|
17
|
-
options[:output_filename] ||= 'lydown' unless options[:format] ==
|
17
|
+
options[:output_filename] ||= 'lydown' unless options[:format] == :ly
|
18
18
|
else
|
19
19
|
options[:source_filename] = options[:path]
|
20
20
|
if (options[:path] !~ /\.ld$/) and File.file?(options[:path] + ".ld")
|
@@ -31,4 +31,26 @@ module Lydown::CLI::Support
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
end
|
34
|
+
|
35
|
+
# determine if the specified path is actually a path to a single movement of
|
36
|
+
# a multi-movement work. If so, return the path of the work directory, and
|
37
|
+
# add a movement parameter. This should also take care of running proof
|
38
|
+
# mode inside of a movement directory.
|
39
|
+
def self.detect_work_directory(opts)
|
40
|
+
return if opts[:movements]
|
41
|
+
|
42
|
+
parent_dir = File.expand_path(File.join(opts[:path], '..'))
|
43
|
+
|
44
|
+
if !File.exists?(File.join(opts[:path], 'work.ld')) &&
|
45
|
+
File.exists?(File.expand_path(File.join(parent_dir, 'work.ld')))
|
46
|
+
|
47
|
+
movement = File.basename(File.expand_path(opts[:path]))
|
48
|
+
opts[:movements] = [movement] unless opts[:mode] == :proof
|
49
|
+
opts[:path] = parent_dir
|
50
|
+
end
|
51
|
+
end
|
34
52
|
end
|
53
|
+
|
54
|
+
|
55
|
+
|
56
|
+
|
data/lib/lydown/core_ext.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'escape_utils'
|
2
|
+
require 'pathname'
|
2
3
|
|
3
4
|
class Hash
|
4
5
|
# Merges self with another hash, recursively.
|
@@ -62,7 +63,7 @@ class Hash
|
|
62
63
|
if @deep && k.is_a?(String) && k =~ /\//
|
63
64
|
lookup(k)
|
64
65
|
elsif @deep && k.is_a?(Symbol)
|
65
|
-
old_get(k) || old_get(k.to_s)
|
66
|
+
old_get(k) || old_get(k.to_s)
|
66
67
|
else
|
67
68
|
old_get(k)
|
68
69
|
end
|
@@ -105,6 +106,12 @@ class Hash
|
|
105
106
|
def is_deep?
|
106
107
|
!!@deep
|
107
108
|
end
|
109
|
+
|
110
|
+
def stringify_keys
|
111
|
+
h = {}
|
112
|
+
each {|k, v| h[k.to_s] = v}
|
113
|
+
h
|
114
|
+
end
|
108
115
|
end
|
109
116
|
|
110
117
|
class String
|
@@ -169,11 +176,40 @@ class String
|
|
169
176
|
end
|
170
177
|
|
171
178
|
class Fixnum
|
172
|
-
|
173
|
-
|
174
|
-
|
179
|
+
# Taken from https://github.com/AndrewVos/roman-numerals
|
180
|
+
# Copyright (c) 2011 Andrew Vos
|
181
|
+
@@roman_digits = {
|
182
|
+
1000 => 'M',
|
183
|
+
900 => 'CM',
|
184
|
+
500 => 'D',
|
185
|
+
400 => 'CD',
|
186
|
+
100 => 'C',
|
187
|
+
90 => 'XC',
|
188
|
+
50 => 'L',
|
189
|
+
40 => 'XL',
|
190
|
+
10 => 'X',
|
191
|
+
9 => 'IX',
|
192
|
+
5 => 'V',
|
193
|
+
4 => 'IV',
|
194
|
+
1 => 'I'
|
195
|
+
}
|
196
|
+
|
175
197
|
def to_roman
|
176
|
-
|
198
|
+
result = ''
|
199
|
+
value = self
|
200
|
+
@@roman_digits.keys.each do |decimal|
|
201
|
+
while value >= decimal
|
202
|
+
value -= decimal
|
203
|
+
result += @@roman_digits[decimal]
|
204
|
+
end
|
205
|
+
end
|
206
|
+
result
|
177
207
|
end
|
178
208
|
end
|
179
209
|
|
210
|
+
class Pathname
|
211
|
+
# Returns path relative to working directory
|
212
|
+
def self.relative_pwd(path)
|
213
|
+
self.new(path).relative_path_from(pwd).to_s
|
214
|
+
end
|
215
|
+
end
|
@@ -148,6 +148,7 @@ parts:
|
|
148
148
|
clef: bass
|
149
149
|
midi_instrument: cello
|
150
150
|
embed_figures: true
|
151
|
+
remove_empty: false
|
151
152
|
organo:
|
152
153
|
clef: bass
|
153
154
|
midi_instrument: church organ
|
@@ -182,7 +183,6 @@ score:
|
|
182
183
|
- [violino, violino1, violino2, violino3, violin1, violin2, violin3]
|
183
184
|
- viola
|
184
185
|
- [gamba, gamba1, gamba2]
|
185
|
-
- [soprano, alto, tenore, basso]
|
186
|
-
- [soprano1, alto1, tenore1, basso1]
|
187
|
-
- [soprano2, alto2, tenore2, basso2]
|
186
|
+
- [soprano1, soprano2, soprano, alto1, alto2, alto, tenore1, tenore2, tenore, basso1, basso2, basso]
|
188
187
|
- continuo
|
188
|
+
end_barline: "|."
|
data/lib/lydown/errors.rb
CHANGED
data/lib/lydown/lilypond.rb
CHANGED
@@ -13,10 +13,31 @@ module Lydown
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def compile(source, opts = {})
|
16
|
-
opts[:
|
16
|
+
opts[:output_target] ||= 'lydown'
|
17
|
+
|
18
|
+
if opts[:temp]
|
19
|
+
opts[:output_filename] = opts[:output_target]
|
20
|
+
invoke(source, opts)
|
21
|
+
else
|
22
|
+
invoke_with_tempfile(source, opts)
|
23
|
+
end
|
17
24
|
|
18
|
-
|
19
|
-
|
25
|
+
rescue CompilationAbortError => e
|
26
|
+
raise e
|
27
|
+
rescue => e
|
28
|
+
$stderr.puts e.message
|
29
|
+
$stderr.puts e.backtrace.join("\n") unless e.is_a?(LydownError)
|
30
|
+
raise e
|
31
|
+
end
|
32
|
+
|
33
|
+
# Compile into a tempfile. We do this because lilypond's behavior when
|
34
|
+
# supplied with target filenames is broken. If it is given a target
|
35
|
+
# path which corresponds to an existing directory name, it does not use
|
36
|
+
# the specified path plus extension, but instead creates a file inside
|
37
|
+
# the directory.
|
38
|
+
def invoke_with_tempfile(source, opts)
|
39
|
+
target = opts[:output_target].dup
|
40
|
+
ext = ".#{opts[:format] || :pdf}"
|
20
41
|
if target !~ /#{ext}$/
|
21
42
|
target << ext
|
22
43
|
end
|
@@ -25,15 +46,12 @@ module Lydown
|
|
25
46
|
opts[:output_filename] = tmp_target
|
26
47
|
invoke(source, opts)
|
27
48
|
|
49
|
+
# Copy tempfile to target
|
28
50
|
if File.file?(tmp_target + ext)
|
29
51
|
FileUtils.cp(tmp_target + ext, target)
|
30
52
|
else
|
31
53
|
copy_pages(tmp_target, target, ext)
|
32
54
|
end
|
33
|
-
rescue => e
|
34
|
-
$stderr.puts e.message
|
35
|
-
$stderr.puts e.backtrace.join("\n")
|
36
|
-
raise e
|
37
55
|
end
|
38
56
|
|
39
57
|
def copy_pages(source, target, ext)
|
@@ -49,30 +67,49 @@ module Lydown
|
|
49
67
|
end
|
50
68
|
end
|
51
69
|
|
70
|
+
# Run lilypond, pipe source into its STDIN, and capture its STDERR
|
52
71
|
def invoke(source, opts = {})
|
53
|
-
|
54
|
-
format = nil if format == 'midi'
|
72
|
+
cmd = format_cmd(opts)
|
55
73
|
|
56
|
-
|
74
|
+
err_info = ''
|
75
|
+
exit_value = nil
|
76
|
+
Open3.popen2e(cmd) do |input, output, wait_thr|
|
77
|
+
err_info = exec(wait_thr, input, output, source, opts)
|
78
|
+
exit_value = wait_thr.value
|
79
|
+
end
|
80
|
+
if exit_value != 0
|
81
|
+
if exit_value.termsig
|
82
|
+
raise CompilationAbortError
|
83
|
+
else
|
84
|
+
# err_info = err_info.lines[0, 3].join
|
85
|
+
raise LydownError, "Lilypond compilation failed:\n#{err_info}"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def format_cmd(opts)
|
91
|
+
format = opts[:format]
|
92
|
+
format = nil if (format == :midi) || (format == :mp3)
|
93
|
+
|
57
94
|
cmd = 'lilypond '
|
95
|
+
cmd << "-dbackend=eps " if opts[:mode] == :proof
|
58
96
|
cmd << "-o #{opts[:output_filename]} "
|
59
97
|
cmd << "-dno-point-and-click "
|
60
98
|
cmd << "--#{opts[:format]} " if format
|
61
99
|
cmd << ' - '
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
end
|
100
|
+
|
101
|
+
cmd
|
102
|
+
end
|
103
|
+
|
104
|
+
def exec(wait_thr, input, output, source, opts)
|
105
|
+
Lydown::CLI.register_abortable_process(wait_thr.pid)
|
106
|
+
input.puts source
|
107
|
+
input.close_write
|
108
|
+
err_info = read_lilypond_progress(output, opts)
|
109
|
+
output.close
|
110
|
+
err_info
|
111
|
+
ensure
|
112
|
+
Lydown::CLI.unregister_abortable_process(wait_thr.pid)
|
76
113
|
end
|
77
114
|
|
78
115
|
LILYPOND_STATUS_LINES = %w{
|
@@ -91,18 +128,23 @@ module Lydown
|
|
91
128
|
|
92
129
|
def read_lilypond_progress(f, opts)
|
93
130
|
info = ''
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
131
|
+
unless opts[:no_progress_bar]
|
132
|
+
Lydown::CLI::show_progress('Compile', STATUS_TOTAL) do |bar|
|
133
|
+
while !f.eof?
|
134
|
+
line = f.gets
|
135
|
+
info += line
|
136
|
+
if line =~ /^([^\s]+)/
|
137
|
+
idx = LILYPOND_STATUS_LINES.index($1)
|
138
|
+
bar.progress = idx + 1 if idx
|
139
|
+
end
|
101
140
|
end
|
102
141
|
end
|
142
|
+
else
|
143
|
+
info = f.read
|
103
144
|
end
|
104
145
|
info
|
105
146
|
end
|
147
|
+
|
106
148
|
end
|
107
149
|
end
|
108
150
|
end
|
@@ -0,0 +1,297 @@
|
|
1
|
+
\header {
|
2
|
+
tagline = ##f
|
3
|
+
}
|
4
|
+
|
5
|
+
segno = {
|
6
|
+
\once \override Score.RehearsalMark #'font-size = #-2
|
7
|
+
\mark \markup { \musicglyph #"scripts.segno" }
|
8
|
+
}
|
9
|
+
|
10
|
+
segnobottom = {
|
11
|
+
\once \override Score.RehearsalMark #'direction = #DOWN
|
12
|
+
\once \override Score.RehearsalMark #'font-size = #-2
|
13
|
+
\mark \markup { \musicglyph #"scripts.segno" }
|
14
|
+
}
|
15
|
+
|
16
|
+
dalsegno = {
|
17
|
+
\once \override Score.RehearsalMark #'break-visibility = #begin-of-line-invisible
|
18
|
+
\once \override Score.RehearsalMark #'direction = #DOWN
|
19
|
+
\once \override Score.RehearsalMark #'self-alignment-X = #RIGHT
|
20
|
+
\once \override Score.RehearsalMark #'font-size = #-2
|
21
|
+
\mark \markup { \fontsize #2 {"dal segno "} \musicglyph #"scripts.segno" }
|
22
|
+
}
|
23
|
+
|
24
|
+
dacapo = {
|
25
|
+
\once \override Score.RehearsalMark #'break-visibility = #begin-of-line-invisible
|
26
|
+
\once \override Score.RehearsalMark #'direction = #DOWN
|
27
|
+
\once \override Score.RehearsalMark #'self-alignment-X = #RIGHT
|
28
|
+
\mark \markup {\bold {\italic {"Da capo"}}}
|
29
|
+
}
|
30
|
+
|
31
|
+
dalsegnoadlib = {
|
32
|
+
\once \override Score.RehearsalMark #'direction = #DOWN
|
33
|
+
\once \override Score.RehearsalMark #'self-alignment-X = #LEFT
|
34
|
+
\once \override Score.RehearsalMark #'font-size = #-2
|
35
|
+
\mark \markup { \musicglyph #"scripts.segno" ad lib }
|
36
|
+
}
|
37
|
+
|
38
|
+
finedellaparteprima = {
|
39
|
+
\once \override Score.RehearsalMark #'break-visibility = #begin-of-line-invisible
|
40
|
+
\once \override Score.RehearsalMark #'direction = #DOWN
|
41
|
+
\once \override Score.RehearsalMark #'self-alignment-X = #RIGHT
|
42
|
+
\mark \markup {\bold {\italic {"Fine della parte prima"}}}
|
43
|
+
}
|
44
|
+
|
45
|
+
padbarlinebefore = {
|
46
|
+
\once \override Staff.BarLine #'extra-spacing-width = #'(-2 . 0)
|
47
|
+
}
|
48
|
+
|
49
|
+
padbarlineafter = {
|
50
|
+
\once \override Staff.BarLine #'extra-spacing-width = #'(0 . 2)
|
51
|
+
}
|
52
|
+
|
53
|
+
editF = \markup { \center-align \concat { \bold { \italic ( }
|
54
|
+
\dynamic f \bold { \italic ) } } }
|
55
|
+
editP = \markup { \center-align \concat { \bold { \italic ( }
|
56
|
+
\dynamic p \bold { \italic ) } } }
|
57
|
+
editPP = \markup { \center-align \concat { \bold { \italic ( }
|
58
|
+
\dynamic pp \bold { \italic ) } } }
|
59
|
+
|
60
|
+
doux = \markup { \center-align \bold { \italic doux }}
|
61
|
+
fort = \markup { \center-align \bold { \italic fort }}
|
62
|
+
|
63
|
+
ten = \markup { \italic ten. }
|
64
|
+
|
65
|
+
ficta = {
|
66
|
+
\once \override AccidentalSuggestion #'avoid-slur = #'outside
|
67
|
+
\once \set suggestAccidentals = ##t
|
68
|
+
}
|
69
|
+
|
70
|
+
%{
|
71
|
+
http://www.lilypond.org/doc/v2.18/Documentation/snippets/editorial-annotations#editorial-annotations-adding-links-to-objects
|
72
|
+
%}
|
73
|
+
#(define (add-link url-strg)
|
74
|
+
(lambda (grob)
|
75
|
+
(let* ((stil (ly:grob-property grob 'stencil)))
|
76
|
+
(if (ly:stencil? stil)
|
77
|
+
(begin
|
78
|
+
(let* (
|
79
|
+
(x-ext (ly:stencil-extent stil X))
|
80
|
+
(y-ext (ly:stencil-extent stil Y))
|
81
|
+
(url-expr (list 'url-link url-strg `(quote ,x-ext) `(quote ,y-ext)))
|
82
|
+
(new-stil (ly:stencil-add (ly:make-stencil url-expr x-ext y-ext) stil)))
|
83
|
+
(ly:grob-set-property! grob 'stencil new-stil)))
|
84
|
+
#f))))
|
85
|
+
|
86
|
+
|
87
|
+
\layout {
|
88
|
+
#(layout-set-staff-size 14)
|
89
|
+
indent = 0\cm
|
90
|
+
|
91
|
+
\context {
|
92
|
+
\Score
|
93
|
+
\override InstrumentName #'self-alignment-X = #right
|
94
|
+
\override InstrumentName #'padding = 0.6
|
95
|
+
|
96
|
+
\override BarNumber #'padding = 1.5
|
97
|
+
|
98
|
+
%make note stems a bit thicker
|
99
|
+
\override Stem.thickness = #2
|
100
|
+
|
101
|
+
% slurs and ties are a bit curvier and thicker
|
102
|
+
% ties are also a bit more distant from note heads
|
103
|
+
% all that with a bit of randomness
|
104
|
+
\override Slur.eccentricity = #(lambda (grob) (* 0.05 (random:normal)))
|
105
|
+
\override Slur.height-limit = #(lambda (grob) (+ 2.8 (* 0.2 (random:normal))))
|
106
|
+
\override Slur.thickness = #(lambda (grob) (+ 2.9 (* 0.1 (random:normal))))
|
107
|
+
\override Slur.ratio = #(lambda (grob) (+ 0.3 (* 0.05 (random:normal))))
|
108
|
+
|
109
|
+
\override Tie.thickness = #(lambda (grob) (+ 2.9 (* 0.1 (random:normal))))
|
110
|
+
\override Tie.ratio = #(lambda (grob) (+ 0.3 (* 0.05 (random:normal))))
|
111
|
+
\override Tie #'details #'note-head-gap = #(lambda (grob) (+ 0.5 (* 0.1 (random:normal))))
|
112
|
+
|
113
|
+
\override Beam.beam-thickness = #(lambda (grob) (+ 0.55 (* 0.02 (random:normal))))
|
114
|
+
\override Beam.length-fraction = #1.15
|
115
|
+
|
116
|
+
% \remove "Bar_number_engraver"
|
117
|
+
}
|
118
|
+
|
119
|
+
\context {
|
120
|
+
\Staff
|
121
|
+
\override StaffSymbol.color = #(rgb-color 0.25 0.2 0.2)
|
122
|
+
|
123
|
+
}
|
124
|
+
|
125
|
+
\context {
|
126
|
+
\Lyrics
|
127
|
+
% candidates: Georgia, Hoefler Text, Hoefler Text Italic,
|
128
|
+
%
|
129
|
+
\override LyricText #'font-name = #"Hoefler Text"
|
130
|
+
% \override LyricText #'font-size = #3
|
131
|
+
}
|
132
|
+
|
133
|
+
\context {
|
134
|
+
\override MarkupText #'font-name = #"Hoefler Text"
|
135
|
+
}
|
136
|
+
}
|
137
|
+
|
138
|
+
\paper {
|
139
|
+
% #(set-default-paper-size "A5")
|
140
|
+
|
141
|
+
% system-system-spacing #'basic-distance = #17
|
142
|
+
|
143
|
+
top-margin = 1.4\cm
|
144
|
+
bottom-margin = 1.4\cm
|
145
|
+
two-sided = ##t
|
146
|
+
inner-margin = 1.4\cm
|
147
|
+
outer-margin = 2\cm
|
148
|
+
|
149
|
+
markup-system-spacing #'padding = #3
|
150
|
+
markup-system-spacing #'stretchability = #10
|
151
|
+
score-markup-spacing #'padding = #7
|
152
|
+
top-system-spacing #'padding = #3
|
153
|
+
top-markup-spacing #'padding = #3
|
154
|
+
system-system-spacing #'minimum-distance = #9
|
155
|
+
system-system-spacing #'stretchability = #15
|
156
|
+
|
157
|
+
|
158
|
+
% ragged-last-bottom = ##t
|
159
|
+
ragged-bottom = ##t
|
160
|
+
|
161
|
+
print-first-page-number = ##f
|
162
|
+
|
163
|
+
oddHeaderMarkup = \markup
|
164
|
+
\fill-line {
|
165
|
+
%% force the header to take some space, otherwise the
|
166
|
+
%% page layout becomes a complete mess.
|
167
|
+
" "
|
168
|
+
% \on-the-fly #not-first-page {
|
169
|
+
\on-the-fly #print-page-number-check-first \fromproperty #'page:page-number-string
|
170
|
+
% }
|
171
|
+
}
|
172
|
+
|
173
|
+
evenHeaderMarkup = \markup
|
174
|
+
\fill-line {
|
175
|
+
\on-the-fly #print-page-number-check-first \fromproperty #'page:page-number-string
|
176
|
+
" "
|
177
|
+
}
|
178
|
+
|
179
|
+
}
|
180
|
+
|
181
|
+
% trill = #(make-articulation "stopped")
|
182
|
+
trillSharp = #(make-articulation "trillSharp")
|
183
|
+
trillNatural = #(make-articulation "trillNatural")
|
184
|
+
tr = #(make-articulation "t")
|
185
|
+
trillSug = #(make-articulation "trillSug")
|
186
|
+
prallSug = #(make-articulation "prallSug")
|
187
|
+
arcTrill = #(make-articulation "arcTrill")
|
188
|
+
arcDot = #(make-articulation "arcDot")
|
189
|
+
arcArc = #(make-articulation "arcArc")
|
190
|
+
arcArcDot = #(make-articulation "arcArcDot")
|
191
|
+
dotDot = #(make-articulation "dotDot")
|
192
|
+
dotPrall = #(make-articulation "dotPrall")
|
193
|
+
dotDoublePrallDoublePrall = #(make-articulation "dotDoublePrallDoublePrall")
|
194
|
+
doublePrall = #(make-articulation "doublePrall")
|
195
|
+
|
196
|
+
prallupbefore = {
|
197
|
+
\mark\markup {
|
198
|
+
\musicglyph #"scripts.prallup"
|
199
|
+
\hspace #1
|
200
|
+
}
|
201
|
+
}
|
202
|
+
|
203
|
+
% override the figured bass formatter in order to fix size of figure accidentals
|
204
|
+
#(define-public (better-format-bass-figure figure event context)
|
205
|
+
(let* ((fig (ly:event-property event 'figure))
|
206
|
+
(fig-markup (if (number? figure)
|
207
|
+
|
208
|
+
;; this is not very elegant, but center-aligning
|
209
|
+
;; all digits is problematic with other markups,
|
210
|
+
;; and shows problems in the (lack of) overshoot
|
211
|
+
;; of feta-alphabet glyphs.
|
212
|
+
((if (<= 10 figure)
|
213
|
+
(lambda (y) (make-translate-scaled-markup
|
214
|
+
(cons -0.7 0) y))
|
215
|
+
identity)
|
216
|
+
|
217
|
+
(cond
|
218
|
+
((eq? #t (ly:event-property event 'diminished))
|
219
|
+
(markup #:slashed-digit figure))
|
220
|
+
((eq? #t (ly:event-property event 'augmented-slash))
|
221
|
+
(markup #:backslashed-digit figure))
|
222
|
+
(else (markup #:number (number->string figure 10)))))
|
223
|
+
#f))
|
224
|
+
|
225
|
+
(alt (ly:event-property event 'alteration))
|
226
|
+
(alt-markup
|
227
|
+
(if (number? alt)
|
228
|
+
(markup
|
229
|
+
#:general-align Y DOWN #:fontsize
|
230
|
+
(if (not (= alt DOUBLE-SHARP))
|
231
|
+
0 2)
|
232
|
+
(alteration->text-accidental-markup alt))
|
233
|
+
#f))
|
234
|
+
|
235
|
+
(plus-markup (if (eq? #t (ly:event-property event 'augmented))
|
236
|
+
(markup #:number "+")
|
237
|
+
#f))
|
238
|
+
|
239
|
+
(alt-dir (ly:context-property context 'figuredBassAlterationDirection))
|
240
|
+
(plus-dir (ly:context-property context 'figuredBassPlusDirection)))
|
241
|
+
|
242
|
+
(if (and (not fig-markup) alt-markup)
|
243
|
+
(begin
|
244
|
+
(set! fig-markup (markup #:left-align #:pad-around 0.2 alt-markup))
|
245
|
+
(set! alt-markup #f)))
|
246
|
+
|
247
|
+
|
248
|
+
;; hmm, how to get figures centered between note, and
|
249
|
+
;; lone accidentals too?
|
250
|
+
|
251
|
+
;; (if (markup? fig-markup)
|
252
|
+
;; (set!
|
253
|
+
;; fig-markup (markup #:translate (cons 1.0 0)
|
254
|
+
;; #:center-align fig-markup)))
|
255
|
+
|
256
|
+
(if alt-markup
|
257
|
+
(set! fig-markup
|
258
|
+
(markup #:put-adjacent
|
259
|
+
X (if (number? alt-dir)
|
260
|
+
alt-dir
|
261
|
+
LEFT)
|
262
|
+
fig-markup
|
263
|
+
#:pad-x 0.2 #:lower 0.1 alt-markup)))
|
264
|
+
|
265
|
+
(if plus-markup
|
266
|
+
(set! fig-markup
|
267
|
+
(if fig-markup
|
268
|
+
(markup #:put-adjacent
|
269
|
+
X (if (number? plus-dir)
|
270
|
+
plus-dir
|
271
|
+
LEFT)
|
272
|
+
fig-markup
|
273
|
+
#:pad-x 0.2 plus-markup)
|
274
|
+
plus-markup)))
|
275
|
+
|
276
|
+
(if (markup? fig-markup)
|
277
|
+
(markup #:fontsize 0 fig-markup)
|
278
|
+
empty-markup)))
|
279
|
+
|
280
|
+
\layout {
|
281
|
+
\context {
|
282
|
+
\FiguredBass
|
283
|
+
figuredBassFormatter = #better-format-bass-figure
|
284
|
+
% \override BassFigure #'font-size = #-1
|
285
|
+
% \override BassFigure #'font-name = #"Georgia"
|
286
|
+
}
|
287
|
+
|
288
|
+
% \context {
|
289
|
+
% \StaffGroup
|
290
|
+
% \override StaffGrouper.staff-staff-spacing =
|
291
|
+
% #'((basic-distance . 10)
|
292
|
+
% (minimum-distance . 7)
|
293
|
+
% (padding . 0)
|
294
|
+
% (stretchability . 7))
|
295
|
+
%
|
296
|
+
% }
|
297
|
+
}
|