lydown 0.12.4 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +41 -1
- data/bin/lydown +2 -0
- data/lib/lydown.rb +6 -2
- data/lib/lydown/cache.rb +5 -1
- data/lib/lydown/cli.rb +1 -1
- data/lib/lydown/cli/commands.rb +7 -11
- data/lib/lydown/cli/compiler.rb +5 -0
- data/lib/lydown/cli/proofing.rb +2 -2
- data/lib/lydown/cli/repl.rb +1 -1
- data/lib/lydown/cli/support.rb +0 -33
- data/lib/lydown/defaults.yml +50 -8
- data/lib/lydown/inverso.rb +84 -0
- data/lib/lydown/lilypond.rb +76 -10
- data/lib/lydown/ly_lib/lib.ly +140 -127
- data/lib/lydown/parsing/lydown.treetop +25 -12
- data/lib/lydown/parsing/nodes.rb +55 -19
- data/lib/lydown/rendering.rb +72 -1
- data/lib/lydown/rendering/base.rb +21 -0
- data/lib/lydown/rendering/command.rb +53 -0
- data/lib/lydown/rendering/layout.rb +83 -0
- data/lib/lydown/rendering/lyrics.rb +1 -1
- data/lib/lydown/rendering/markup.rb +23 -0
- data/lib/lydown/rendering/movement.rb +7 -4
- data/lib/lydown/rendering/music.rb +35 -29
- data/lib/lydown/rendering/notes.rb +75 -41
- data/lib/lydown/rendering/repeats.rb +27 -0
- data/lib/lydown/rendering/settings.rb +36 -9
- data/lib/lydown/rendering/skipping.rb +10 -2
- data/lib/lydown/rendering/staff.rb +38 -31
- data/lib/lydown/rendering/voices.rb +1 -1
- data/lib/lydown/templates.rb +8 -8
- data/lib/lydown/templates/layout.rb +40 -0
- data/lib/lydown/templates/lilypond_doc.rb +95 -0
- data/lib/lydown/templates/movement.rb +188 -0
- data/lib/lydown/templates/multi_voice.rb +25 -0
- data/lib/lydown/templates/part.rb +146 -0
- data/lib/lydown/templates/variables.rb +43 -0
- data/lib/lydown/translation/ripple.rb +1 -1
- data/lib/lydown/translation/ripple/nodes.rb +51 -2
- data/lib/lydown/translation/ripple/ripple.treetop +87 -10
- data/lib/lydown/version.rb +1 -1
- data/lib/lydown/work.rb +19 -2
- data/lib/lydown/work_context.rb +10 -2
- metadata +12 -8
- data/lib/lydown/cli/installer.rb +0 -175
- data/lib/lydown/templates/lilypond_doc.erb +0 -34
- data/lib/lydown/templates/movement.erb +0 -118
- data/lib/lydown/templates/multi_voice.erb +0 -16
- data/lib/lydown/templates/part.erb +0 -118
- data/lib/lydown/templates/variables.erb +0 -43
data/lib/lydown/lilypond.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'lydown/errors'
|
2
2
|
require 'lydown/cli/output'
|
3
|
+
require 'lydown/cli/signals'
|
3
4
|
|
4
5
|
require 'tempfile'
|
5
6
|
require 'fileutils'
|
@@ -8,6 +9,49 @@ require 'open3'
|
|
8
9
|
module Lydown
|
9
10
|
module Lilypond
|
10
11
|
class << self
|
12
|
+
MINIMAL_LILYPOND_VERSION = Gem::Version.new('2.18')
|
13
|
+
|
14
|
+
def lilypond_path
|
15
|
+
# detect lyp-installed lilypond
|
16
|
+
# path = `lyp which lilypond`.lines.last rescue nil
|
17
|
+
# return path.chomp if path
|
18
|
+
#
|
19
|
+
# path = `which lilypond` rescue nil
|
20
|
+
# return path.chomp if path && !path.empty?
|
21
|
+
|
22
|
+
return 'lilypond'
|
23
|
+
end
|
24
|
+
|
25
|
+
# detect the lilypond version. If lilypond is not found, or the version is
|
26
|
+
# less than the minimal supported version, display an error message.
|
27
|
+
def detect_lilypond_version(exit_on_error)
|
28
|
+
version = nil
|
29
|
+
if path = lilypond_path
|
30
|
+
msg = `#{lilypond_path} --version`
|
31
|
+
if msg.lines.first =~ /LilyPond ([\d\.]+)/
|
32
|
+
version = $1
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
unless version && Gem::Version.new(version) >= MINIMAL_LILYPOND_VERSION
|
37
|
+
display_lilypond_version_error_msg(version)
|
38
|
+
exit!(1) if exit_on_error
|
39
|
+
version = nil
|
40
|
+
end
|
41
|
+
version
|
42
|
+
rescue => e
|
43
|
+
display_lilypond_version_error_msg(nil)
|
44
|
+
exit!(1) if exit_on_error
|
45
|
+
end
|
46
|
+
|
47
|
+
def display_lilypond_version_error_msg(version)
|
48
|
+
if version
|
49
|
+
STDERR.puts "ERROR: The installed lilypond (version #{version}) is too old."
|
50
|
+
else
|
51
|
+
STDERR.puts "ERROR: No copy of lilypond found."
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
11
55
|
def tmpdir
|
12
56
|
@tmpdir ||= Dir.mktmpdir
|
13
57
|
end
|
@@ -67,14 +111,30 @@ module Lydown
|
|
67
111
|
end
|
68
112
|
end
|
69
113
|
|
114
|
+
# In order to be able to run the lyp lilypond wrapper (if present),
|
115
|
+
# we need to reset the environment variables set by bundler when running
|
116
|
+
# lydown.
|
117
|
+
RESET_ENV = {
|
118
|
+
"_ORIGINAL_GEM_PATH" => "",
|
119
|
+
"BUNDLE_GEMFILE" => "",
|
120
|
+
"BUNDLE_BIN_PATH" => "",
|
121
|
+
"RUBYOPT" => "",
|
122
|
+
"RUBYLIB" => ""
|
123
|
+
}
|
124
|
+
|
70
125
|
# Run lilypond, pipe source into its STDIN, and capture its STDERR
|
71
126
|
def invoke(source, opts = {})
|
72
|
-
|
127
|
+
tmp_source_path = Tempfile.new('lydown').path
|
128
|
+
File.open(tmp_source_path, 'w') {|f| f << source}
|
129
|
+
|
130
|
+
cmd = format_cmd(opts, tmp_source_path)
|
131
|
+
puts cmd if opts[:verbose]
|
73
132
|
|
74
133
|
err_info = ''
|
75
134
|
exit_value = nil
|
76
|
-
|
77
|
-
|
135
|
+
|
136
|
+
Open3.popen2e(RESET_ENV, cmd) do |input, output, wait_thr|
|
137
|
+
err_info = exec(wait_thr, input, output, opts)
|
78
138
|
exit_value = wait_thr.value
|
79
139
|
end
|
80
140
|
if exit_value != 0
|
@@ -87,23 +147,23 @@ module Lydown
|
|
87
147
|
end
|
88
148
|
end
|
89
149
|
|
90
|
-
def format_cmd(opts)
|
150
|
+
def format_cmd(opts, source_path)
|
91
151
|
format = opts[:format]
|
92
152
|
format = nil if (format == :midi) || (format == :mp3)
|
93
153
|
|
94
|
-
cmd =
|
95
|
-
cmd << "-dbackend=eps " if opts[:mode] == :proof
|
154
|
+
cmd = "#{lilypond_path} "
|
155
|
+
# cmd << "-dbackend=eps " if opts[:mode] == :proof
|
96
156
|
cmd << "-o #{opts[:output_filename]} "
|
97
157
|
cmd << "-dno-point-and-click "
|
98
158
|
cmd << "--#{opts[:format]} " if format
|
99
|
-
cmd <<
|
159
|
+
cmd << "-V " if opts[:verbose]
|
160
|
+
cmd << source_path
|
100
161
|
|
101
162
|
cmd
|
102
163
|
end
|
103
164
|
|
104
|
-
def exec(wait_thr, input, output,
|
165
|
+
def exec(wait_thr, input, output, opts)
|
105
166
|
Lydown::CLI.register_abortable_process(wait_thr.pid)
|
106
|
-
input.puts source
|
107
167
|
input.close_write
|
108
168
|
err_info = read_lilypond_progress(output, opts)
|
109
169
|
output.close
|
@@ -128,7 +188,7 @@ module Lydown
|
|
128
188
|
|
129
189
|
def read_lilypond_progress(f, opts)
|
130
190
|
info = ''
|
131
|
-
|
191
|
+
if !opts[:verbose] && !opts[:no_progress_bar]
|
132
192
|
Lydown::CLI::show_progress('Compile', STATUS_TOTAL) do |bar|
|
133
193
|
while !f.eof?
|
134
194
|
line = f.gets
|
@@ -140,6 +200,12 @@ module Lydown
|
|
140
200
|
end
|
141
201
|
bar.progress = STATUS_TOTAL
|
142
202
|
end
|
203
|
+
elsif opts[:verbose]
|
204
|
+
while !f.eof?
|
205
|
+
line = f.gets
|
206
|
+
STDERR.puts line
|
207
|
+
info += line
|
208
|
+
end
|
143
209
|
else
|
144
210
|
info = f.read
|
145
211
|
end
|
data/lib/lydown/ly_lib/lib.ly
CHANGED
@@ -1,53 +1,53 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
#(define-markup-command (mm-feed layout props amount) (number?)
|
2
|
+
(let ((o-s (ly:output-def-lookup layout 'output-scale)))
|
3
|
+
(ly:make-stencil "" '(0 . 0) (cons 0 (abs (/ amount o-s))))))
|
4
4
|
|
5
5
|
segno = {
|
6
|
-
\once \override Score.RehearsalMark
|
6
|
+
\once \override Score.RehearsalMark.font-size = #-2
|
7
7
|
\mark \markup { \musicglyph #"scripts.segno" }
|
8
8
|
}
|
9
9
|
|
10
10
|
segnobottom = {
|
11
|
-
\once \override Score.RehearsalMark
|
12
|
-
\once \override Score.RehearsalMark
|
11
|
+
\once \override Score.RehearsalMark.direction = #DOWN
|
12
|
+
\once \override Score.RehearsalMark.font-size = #-2
|
13
13
|
\mark \markup { \musicglyph #"scripts.segno" }
|
14
14
|
}
|
15
15
|
|
16
16
|
dalsegno = {
|
17
|
-
\once \override Score.RehearsalMark
|
18
|
-
\once \override Score.RehearsalMark
|
19
|
-
\once \override Score.RehearsalMark
|
20
|
-
\once \override Score.RehearsalMark
|
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
21
|
\mark \markup { \fontsize #2 {"dal segno "} \musicglyph #"scripts.segno" }
|
22
22
|
}
|
23
23
|
|
24
24
|
dacapo = {
|
25
|
-
\once \override Score.RehearsalMark
|
26
|
-
\once \override Score.RehearsalMark
|
27
|
-
\once \override Score.RehearsalMark
|
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
28
|
\mark \markup {\bold {\italic {"Da capo"}}}
|
29
29
|
}
|
30
30
|
|
31
31
|
dalsegnoadlib = {
|
32
|
-
\once \override Score.RehearsalMark
|
33
|
-
\once \override Score.RehearsalMark
|
34
|
-
\once \override Score.RehearsalMark
|
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
35
|
\mark \markup { \musicglyph #"scripts.segno" ad lib }
|
36
36
|
}
|
37
37
|
|
38
38
|
finedellaparteprima = {
|
39
|
-
\once \override Score.RehearsalMark
|
40
|
-
\once \override Score.RehearsalMark
|
41
|
-
\once \override Score.RehearsalMark
|
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
42
|
\mark \markup {\bold {\italic {"Fine della parte prima"}}}
|
43
43
|
}
|
44
44
|
|
45
45
|
padbarlinebefore = {
|
46
|
-
\once \override Staff.BarLine
|
46
|
+
\once \override Staff.BarLine.extra-spacing-width = #'(-2 . 0)
|
47
47
|
}
|
48
48
|
|
49
49
|
padbarlineafter = {
|
50
|
-
\once \override Staff.BarLine
|
50
|
+
\once \override Staff.BarLine.extra-spacing-width = #'(0 . 2)
|
51
51
|
}
|
52
52
|
|
53
53
|
editF = \markup { \center-align \concat { \bold { \italic ( }
|
@@ -63,7 +63,8 @@ fort = \markup { \center-align \bold { \italic fort }}
|
|
63
63
|
ten = \markup { \italic ten. }
|
64
64
|
|
65
65
|
ficta = {
|
66
|
-
\once \override AccidentalSuggestion
|
66
|
+
\once \override AccidentalSuggestion.avoid-slur = #'outside
|
67
|
+
\once \override AccidentalSuggestion.parenthesized = ##t
|
67
68
|
\once \set suggestAccidentals = ##t
|
68
69
|
}
|
69
70
|
|
@@ -84,99 +85,6 @@ ficta = {
|
|
84
85
|
#f))))
|
85
86
|
|
86
87
|
|
87
|
-
\layout {
|
88
|
-
#(layout-set-staff-size 17)
|
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
88
|
|
181
89
|
% trill = #(make-articulation "stopped")
|
182
90
|
trillSharp = #(make-articulation "trillSharp")
|
@@ -277,21 +185,126 @@ prallupbefore = {
|
|
277
185
|
(markup #:fontsize 0 fig-markup)
|
278
186
|
empty-markup)))
|
279
187
|
|
280
|
-
\layout {
|
188
|
+
\layout {
|
281
189
|
\context {
|
282
190
|
\FiguredBass
|
283
191
|
figuredBassFormatter = #better-format-bass-figure
|
284
|
-
% \override BassFigure
|
285
|
-
% \override BassFigure
|
192
|
+
% \override BassFigure.font-size = #-1
|
193
|
+
% \override BassFigure.font-name = #"Georgia"
|
286
194
|
}
|
287
195
|
|
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
196
|
}
|
197
|
+
|
198
|
+
#(define-markup-command (when-property layout props symbol markp) (symbol?
|
199
|
+
markup?)
|
200
|
+
(if (chain-assoc-get symbol props)
|
201
|
+
(interpret-markup layout props markp)
|
202
|
+
(ly:make-stencil empty-stencil)))
|
203
|
+
|
204
|
+
#(define-markup-command (apply-fromproperty layout props fn symbol)
|
205
|
+
(procedure? symbol?)
|
206
|
+
(let ((m (chain-assoc-get symbol props)))
|
207
|
+
(if (markup? m)
|
208
|
+
(interpret-markup layout props (fn m))
|
209
|
+
empty-stencil)))
|
210
|
+
|
211
|
+
\header { tagline = ##f } % no tagline
|
212
|
+
|
213
|
+
setVerticalMargins = #(define-scheme-function
|
214
|
+
(parser location top-staff top-markup bottom) (number? number? number?)
|
215
|
+
#{
|
216
|
+
\paper {
|
217
|
+
top-system-spacing.basic-distance = #top-staff
|
218
|
+
top-system-spacing.minimum-distance = #top-staff
|
219
|
+
top-system-spacing.padding = -100 % negative padding to ignore skyline
|
220
|
+
top-system-spacing.stretchability = 0 % fixed position
|
221
|
+
|
222
|
+
top-markup-spacing.basic-distance = #top-markup
|
223
|
+
top-markup-spacing.minimum-distance = #top-markup
|
224
|
+
top-markup-spacing.padding = -100 % negative padding to ignore skyline
|
225
|
+
top-markup-spacing.stretchability = 0 % fixed position
|
226
|
+
|
227
|
+
last-bottom-spacing.basic-distance = #bottom
|
228
|
+
last-bottom-spacing.minimum-distance = #bottom
|
229
|
+
last-bottom-spacing.padding = -100 % negative padding to ignore skyline
|
230
|
+
last-bottom-spacing.stretchability = 0 % fixed position
|
231
|
+
}
|
232
|
+
#}
|
233
|
+
)
|
234
|
+
|
235
|
+
halfBarline = {
|
236
|
+
\once \hide Score.SpanBar
|
237
|
+
\once \override Score.BarLine.bar-extent = #'(-1 . 1)
|
238
|
+
\noBreak
|
239
|
+
\bar "|"
|
240
|
+
}
|
241
|
+
|
242
|
+
scoreMode = #(define-void-function (parser location music) (scheme?)
|
243
|
+
(if (eq? lydown:render-mode 'score)
|
244
|
+
#{ #music #}
|
245
|
+
))
|
246
|
+
|
247
|
+
partMode = #(define-music-function (parser location music) (ly:music?)
|
248
|
+
(if (eq? lydown:render-mode 'part)
|
249
|
+
#{ #music #}
|
250
|
+
#{ #}
|
251
|
+
))
|
252
|
+
|
253
|
+
#(define lydown:score-mode (eq? lydown:render-mode 'score))
|
254
|
+
#(define lydown:part-mode (eq? lydown:render-mode 'part))
|
255
|
+
|
256
|
+
\layout {
|
257
|
+
% The OrchestraGroup is used in score mode as a wrapping context for staff
|
258
|
+
% groups. It is based on the ChoirStaff in order to allow individual span
|
259
|
+
% bars.
|
260
|
+
\context {
|
261
|
+
\ChoirStaff
|
262
|
+
\name "OrchestraGroup"
|
263
|
+
\accepts StaffGroup
|
264
|
+
systemStartDelimiter = #'SystemStartBar
|
265
|
+
}
|
266
|
+
|
267
|
+
\context {
|
268
|
+
\Score
|
269
|
+
\accepts OrchestraGroup
|
270
|
+
}
|
271
|
+
}
|
272
|
+
|
273
|
+
tacetScore = {
|
274
|
+
\new Staff \with {
|
275
|
+
\override StaffSymbol.staff-space = 0.001
|
276
|
+
\override StaffSymbol.line-count = 1
|
277
|
+
\override StaffSymbol.thickness = 0
|
278
|
+
\override StaffSymbol.color = #(rgb-color 1 1 1)
|
279
|
+
\remove "Time_signature_engraver"
|
280
|
+
\remove "Clef_engraver"
|
281
|
+
}
|
282
|
+
{ s4 }
|
283
|
+
}
|
284
|
+
|
285
|
+
% Shaping commands
|
286
|
+
|
287
|
+
sR = #(define-music-function (parser location r) (number?)
|
288
|
+
#{ \once \override Slur.ratio = #r #}
|
289
|
+
)
|
290
|
+
sE = #(define-music-function (parser location e) (number?)
|
291
|
+
#{ \once \override Slur.eccentricity = #e #}
|
292
|
+
)
|
293
|
+
|
294
|
+
sHL = #(define-music-function (parser location l) (number?)
|
295
|
+
#{ \once \override Slur.height-limit = #l #}
|
296
|
+
)
|
297
|
+
|
298
|
+
sP = #(define-music-function (parser location p1 p2) (number? number?)
|
299
|
+
#{ \once \override Slur.positions = #(cons p1 p2) #}
|
300
|
+
)
|
301
|
+
|
302
|
+
#(define (convert-shape-coords s)
|
303
|
+
(map (lambda (v) (if (eq? v #f) '(0 . 0) v)) s)
|
304
|
+
)
|
305
|
+
|
306
|
+
sS = #(define-music-function (parser location s) (scheme?)
|
307
|
+
#{ \once \shape #(convert-shape-coords s) Slur #}
|
308
|
+
)
|
309
|
+
|
310
|
+
knee = \once \override Beam.auto-knee-gap = #0
|