alda-rb 0.2.1 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/main.yml +18 -0
- data/.gitignore +2 -2
- data/CHANGELOG.md +296 -0
- data/CODE_OF_CONDUCT.md +1 -1
- data/Gemfile +3 -2
- data/Gemfile.lock +56 -0
- data/README.md +58 -7
- data/Rakefile +2 -2
- data/alda-rb.gemspec +30 -25
- data/examples/bwv846_prelude.rb +3 -3
- data/examples/clapping_music.rb +1 -1
- data/examples/dot_accessor.rb +1 -1
- data/examples/dynamics.rb +22 -0
- data/examples/entropy.rb +2 -2
- data/examples/hanon.rb +2 -2
- data/examples/marriage_d_amour.rb +114 -0
- data/examples/multi_poly.rb +2 -2
- data/examples/track-volume.rb +32 -0
- data/examples/variables-2.rb +16 -0
- data/exe/alda-irb +32 -0
- data/lib/alda-rb/commandline.rb +176 -33
- data/lib/alda-rb/error.rb +93 -9
- data/lib/alda-rb/event.rb +441 -49
- data/lib/alda-rb/event_list.rb +57 -10
- data/lib/alda-rb/patches.rb +88 -14
- data/lib/alda-rb/repl.rb +330 -61
- data/lib/alda-rb/utils.rb +47 -0
- data/lib/alda-rb/version.rb +1 -1
- data/lib/alda-rb.rb +1 -0
- metadata +74 -8
data/lib/alda-rb/event.rb
CHANGED
@@ -40,7 +40,7 @@ class Alda::Event
|
|
40
40
|
end
|
41
41
|
|
42
42
|
##
|
43
|
-
# Delete itself from its #parent.
|
43
|
+
# Delete itself (or its topmost container if it has) from its #parent.
|
44
44
|
# If it is not at its #parent's end, raises Alda::OrderError.
|
45
45
|
#
|
46
46
|
# Here is a list of cases where the method is invoked:
|
@@ -60,11 +60,40 @@ class Alda::Event
|
|
60
60
|
# pushed to its #parent.
|
61
61
|
# However, the cases above requires the event be contained
|
62
62
|
# in another object.
|
63
|
-
|
64
|
-
|
65
|
-
|
63
|
+
#
|
64
|
+
# The parameter +except+ specifies an Array of classes.
|
65
|
+
# If #parent is an instance of any of the classes in +except+,
|
66
|
+
# the method does nothing.
|
67
|
+
def detach_from_parent except = []
|
68
|
+
event = self
|
69
|
+
event = event.container while event.container
|
70
|
+
if @parent && except.none? { @parent.is_a? _1 } && event != (got = @parent.events.pop)
|
71
|
+
raise Alda::OrderError.new event, got
|
66
72
|
end
|
67
73
|
end
|
74
|
+
|
75
|
+
##
|
76
|
+
# :call-seq:
|
77
|
+
# is_event_of?(klass) -> true or false
|
78
|
+
#
|
79
|
+
# Whether it is an event of the given class (+klass+).
|
80
|
+
# By default, this is the same as +is_a?(klass)+.
|
81
|
+
# It is overridden in Alda::EventContainer.
|
82
|
+
def is_event_of? klass
|
83
|
+
is_a? klass
|
84
|
+
end
|
85
|
+
|
86
|
+
##
|
87
|
+
# :call-seq:
|
88
|
+
# event == other -> true or false
|
89
|
+
#
|
90
|
+
# Whether it is equal to +other+.
|
91
|
+
# To be overriden.
|
92
|
+
#
|
93
|
+
# Note that #parent and #container should not be taken into account when comparing two events.
|
94
|
+
def == other
|
95
|
+
super
|
96
|
+
end
|
68
97
|
end
|
69
98
|
|
70
99
|
##
|
@@ -83,6 +112,8 @@ class Alda::EventContainer < Alda::Event
|
|
83
112
|
# p((e/g).event.class) # => Alda::Chord
|
84
113
|
# p((a b).event.class) # => Alda::Sequence
|
85
114
|
# end
|
115
|
+
#
|
116
|
+
# When setting this attribute, #on_containing is invoked.
|
86
117
|
attr_accessor :event
|
87
118
|
|
88
119
|
##
|
@@ -114,9 +145,11 @@ class Alda::EventContainer < Alda::Event
|
|
114
145
|
#
|
115
146
|
# +parent+ is the Alda::EventList object containing the event.
|
116
147
|
def initialize event, parent
|
148
|
+
super()
|
117
149
|
@event = event
|
118
|
-
@parent = parent
|
119
150
|
@labels = []
|
151
|
+
@count = 1
|
152
|
+
self.parent = parent
|
120
153
|
on_containing
|
121
154
|
end
|
122
155
|
|
@@ -124,13 +157,31 @@ class Alda::EventContainer < Alda::Event
|
|
124
157
|
# :call-seq:
|
125
158
|
# container / other -> container
|
126
159
|
#
|
127
|
-
#
|
160
|
+
# If at first #event is not an Alda::Part,
|
161
|
+
# makes #event an Alda::Chord object.
|
128
162
|
#
|
129
163
|
# Alda::Score.new { piano_; c/-e/g }.play
|
130
164
|
# # (plays the chord Cm)
|
131
165
|
#
|
132
|
-
#
|
166
|
+
# This usage assumes that +other+ is an Alda::EventContainer and will extract the contained event
|
167
|
+
# out from +other+.
|
168
|
+
# This will lose some information about +other+, such as #count and #labels,
|
169
|
+
# and potentially lead to confusing results.
|
170
|
+
#
|
171
|
+
# Because the #labels information about +other+ is lost,
|
172
|
+
# the label on +d+ disappears in the following example:
|
173
|
+
#
|
174
|
+
# Alda::Score.new { c/(d%1) }.to_s # => "c/d"
|
175
|
+
#
|
176
|
+
# The following example shows that the two ways of writing a chord with a label are equivalent:
|
177
|
+
# adding the label and then using slash, or using slash and then adding the label.
|
178
|
+
# This is because #labels and #count are retained while the #event is updated when #/ is called.
|
179
|
+
#
|
180
|
+
# Alda::Score.new { p c%1/d == c/d%1 }.to_s # (prints "true") => "c/d'1 c/d'1"
|
181
|
+
#
|
182
|
+
# If at first #event is an Alda::Part object,
|
133
183
|
# makes #event a new Alda::Part object.
|
184
|
+
# The meaning is to play the two parts simultaneously.
|
134
185
|
#
|
135
186
|
# Alda::Score.new { violin_/viola_/cello_; e; f; g}.play
|
136
187
|
# # (plays notes E, F, G with three instruments simultaneously)
|
@@ -145,12 +196,15 @@ class Alda::EventContainer < Alda::Event
|
|
145
196
|
self
|
146
197
|
end
|
147
198
|
|
199
|
+
##
|
200
|
+
# :call-seq:
|
201
|
+
# to_alda_code() -> String
|
202
|
+
#
|
203
|
+
# Overrides Alda::Event#to_alda_code.
|
148
204
|
def to_alda_code
|
149
205
|
result = @event.to_alda_code
|
150
|
-
unless @labels.empty?
|
151
|
-
|
152
|
-
end
|
153
|
-
result.concat ?*, @count.to_alda_code if @count
|
206
|
+
result.concat ?', @labels.map(&:to_alda_code).join(?,) unless @labels.empty?
|
207
|
+
result.concat ?*, @count.to_alda_code if @count != 1
|
154
208
|
result
|
155
209
|
end
|
156
210
|
|
@@ -163,6 +217,7 @@ class Alda::EventContainer < Alda::Event
|
|
163
217
|
# For examples, see #%.
|
164
218
|
def * num
|
165
219
|
@count = (@count || 1) * num
|
220
|
+
check_in_chord
|
166
221
|
self
|
167
222
|
end
|
168
223
|
|
@@ -177,28 +232,86 @@ class Alda::EventContainer < Alda::Event
|
|
177
232
|
def % labels
|
178
233
|
labels = [labels] unless labels.is_a? Array
|
179
234
|
@labels.replace labels.to_a
|
235
|
+
check_in_chord
|
180
236
|
self
|
181
237
|
end
|
182
238
|
|
239
|
+
def event= event # :nodoc:
|
240
|
+
@event = event.tap { on_containing }
|
241
|
+
end
|
242
|
+
|
183
243
|
##
|
184
244
|
# :call-seq:
|
185
|
-
#
|
245
|
+
# check_in_chord() -> true or false
|
186
246
|
#
|
187
|
-
#
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
247
|
+
# This method is called in #%, #*, and #parent=.
|
248
|
+
# It checks if #parent is an Alda::Chord and warns about potential dangers.
|
249
|
+
# Returns true if there is no danger, and false otherwise.
|
250
|
+
#
|
251
|
+
# Because \Alda 2 does not support specifying alternative endings inside a chord
|
252
|
+
# (something like <tt>a'1/b</tt>)
|
253
|
+
# ({alda-lang/alda#383}[https://github.com/alda-lang/alda/issues/383#issuecomment-886084486]),
|
254
|
+
# this method will warn about this if such thing happens and we are using \Alda 2.
|
255
|
+
#
|
256
|
+
# Alda.v2!
|
257
|
+
# Alda::Score.new { x{a%1;b} }.to_s # (warns) => "a'1/b"
|
258
|
+
#
|
259
|
+
# This method will warn about repetitions inside a chord in both generations
|
260
|
+
# because the resultant \Alda code is not valid.
|
261
|
+
#
|
262
|
+
# Alda::Score.new { x{a*2;b} }.to_s # (warns) => "a*2/b"
|
263
|
+
def check_in_chord
|
264
|
+
if @parent.is_a?(Alda::Event) && @parent.is_event_of?(Alda::Chord)
|
265
|
+
Alda::Utils.warn 'alternative endings in chord not allowed in v2' if Alda.v2? && !@labels&.empty?
|
266
|
+
Alda::Utils.warn 'repetitions in chord not allowed' if @count && @count != 1
|
267
|
+
false
|
268
|
+
else
|
269
|
+
true
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
##
|
274
|
+
# :call-seq:
|
275
|
+
# parent=(event) -> event
|
276
|
+
#
|
277
|
+
# Overrides Alda::Event#parent=.
|
278
|
+
# Sets the Alda::Event#parent of the container as well as that of #event.
|
279
|
+
def parent= event
|
280
|
+
@parent = event
|
281
|
+
check_in_chord
|
282
|
+
@event.parent = event
|
192
283
|
end
|
193
284
|
|
194
285
|
##
|
195
286
|
# A callback invoked in #event= and ::new.
|
196
287
|
def on_containing
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
288
|
+
return unless @event
|
289
|
+
@event.container = self
|
290
|
+
@event.parent = @parent
|
291
|
+
@event.on_contained
|
292
|
+
end
|
293
|
+
|
294
|
+
##
|
295
|
+
# :call-seq:
|
296
|
+
# is_event_of?(klass) -> true or false
|
297
|
+
#
|
298
|
+
# Overrides Alda::Event#is_event_of?.
|
299
|
+
# Whether it is an event of the given class (+klass+)
|
300
|
+
# or the contained event is.
|
301
|
+
def is_event_of? klass
|
302
|
+
super || @event.is_event_of?(klass)
|
303
|
+
end
|
304
|
+
|
305
|
+
##
|
306
|
+
# :call-seq:
|
307
|
+
# container == other -> true or false
|
308
|
+
#
|
309
|
+
# Overrides Alda::Event#==.
|
310
|
+
# Returns true if +other+ is an Alda::EventContainer object
|
311
|
+
# and #event, #count and #labels are all equal (using <tt>==</tt>).
|
312
|
+
def == other
|
313
|
+
super || other.is_a?(Alda::EventContainer) &&
|
314
|
+
@event == other.event && @count == other.count && @labels == other.labels
|
202
315
|
end
|
203
316
|
|
204
317
|
##
|
@@ -221,15 +334,14 @@ class Alda::EventContainer < Alda::Event
|
|
221
334
|
# end
|
222
335
|
def method_missing(...)
|
223
336
|
result = @event.__send__(...)
|
224
|
-
result
|
225
|
-
result
|
337
|
+
result == @event ? self : result
|
226
338
|
end
|
227
339
|
end
|
228
340
|
|
229
341
|
##
|
230
342
|
# An inline lisp event. An Alda::EventContainer containing
|
231
343
|
# an Alda::InlineLisp can be derived using event list
|
232
|
-
# sugar
|
344
|
+
# sugar (see Alda::EventList#method_missing) or by using Alda::EventList#l.
|
233
345
|
#
|
234
346
|
# Sometimes you need help from Alda::LispIdentifier.
|
235
347
|
#
|
@@ -253,6 +365,9 @@ end
|
|
253
365
|
# end
|
254
366
|
#
|
255
367
|
# You can operate a score by purely using inline lisp events.
|
368
|
+
# The following example only works in \Alda 1 due to breaking changes in \Alda 2
|
369
|
+
# ({alda-lang/alda#483}[https://github.com/alda-lang/alda/issues/483],
|
370
|
+
# {alda-lang/alda#484}[https://github.com/alda-lang/alda/issues/484]).
|
256
371
|
#
|
257
372
|
# Alda::Score.new do
|
258
373
|
# part 'piano'
|
@@ -288,10 +403,11 @@ end
|
|
288
403
|
#
|
289
404
|
# If you want, you can generate lisp codes using ruby.
|
290
405
|
#
|
406
|
+
# Alda.generation = :v1
|
291
407
|
# Alda::Score.new do
|
292
408
|
# println reduce _into_, {}, [{dog: 'food'}, {cat: 'chow'}]
|
293
409
|
# end.save 'temp.clj'
|
294
|
-
# `
|
410
|
+
# `clojure temp.clj` # => "{:dog food, :cat chow}\n"
|
295
411
|
class Alda::InlineLisp < Alda::Event
|
296
412
|
|
297
413
|
##
|
@@ -313,18 +429,37 @@ class Alda::InlineLisp < Alda::Event
|
|
313
429
|
#
|
314
430
|
# The underlines "_" in +head+ will be converted to hyphens "-".
|
315
431
|
def initialize head, *args
|
316
|
-
|
432
|
+
super()
|
433
|
+
@head = Alda::Utils.snake_to_slug head
|
317
434
|
@args = args
|
318
435
|
end
|
319
436
|
|
437
|
+
##
|
438
|
+
# :call-seq:
|
439
|
+
# to_alda_code() -> String
|
440
|
+
#
|
441
|
+
# Overrides Alda::Event#to_alda_code.
|
320
442
|
def to_alda_code
|
321
443
|
"(#{head} #{args.map(&:to_alda_code).join ' '})"
|
322
444
|
end
|
323
445
|
|
446
|
+
##
|
447
|
+
# See Alda::Event#on_contained.
|
324
448
|
def on_contained
|
325
449
|
super
|
326
450
|
@args.detach_from_parent
|
327
451
|
end
|
452
|
+
|
453
|
+
##
|
454
|
+
# :call-seq:
|
455
|
+
# inline_lisp == other -> true or false
|
456
|
+
#
|
457
|
+
# Overrides Alda::Event#==.
|
458
|
+
# Returns true if +other+ is an Alda::InlineLisp
|
459
|
+
# and has the same #head and #args as +inline_lisp+ (using <tt>==</tt>).
|
460
|
+
def == other
|
461
|
+
super || other.is_a?(Alda::InlineLisp) && @head == other.head && @args == other.args
|
462
|
+
end
|
328
463
|
end
|
329
464
|
|
330
465
|
##
|
@@ -373,6 +508,7 @@ class Alda::Note < Alda::Event
|
|
373
508
|
# slur if 2,
|
374
509
|
# both natural and slur if 3.
|
375
510
|
def initialize pitch, duration
|
511
|
+
super()
|
376
512
|
@pitch = pitch.to_s
|
377
513
|
@duration = duration.to_s.tr ?_, ?~
|
378
514
|
case @duration[-1]
|
@@ -431,11 +567,27 @@ class Alda::Note < Alda::Event
|
|
431
567
|
self
|
432
568
|
end
|
433
569
|
|
570
|
+
##
|
571
|
+
# :call-seq:
|
572
|
+
# to_alda_code() -> String
|
573
|
+
#
|
574
|
+
# Overrides Alda::Event#to_alda_code.
|
434
575
|
def to_alda_code
|
435
576
|
result = @pitch + @duration
|
436
577
|
result.concat ?*, @count.to_alda_code if @count
|
437
578
|
result
|
438
579
|
end
|
580
|
+
|
581
|
+
##
|
582
|
+
# :call-seq:
|
583
|
+
# note == other -> true or false
|
584
|
+
#
|
585
|
+
# Overrides Alda::Event#==.
|
586
|
+
# Returns true if +other+ is an Alda::Note
|
587
|
+
# and has the same #pitch and #duration as +note+ (using <tt>==</tt>).
|
588
|
+
def == other
|
589
|
+
super || other.is_a?(Alda::Note) && @pitch == other.pitch && @duration == other.duration
|
590
|
+
end
|
439
591
|
end
|
440
592
|
|
441
593
|
##
|
@@ -463,12 +615,29 @@ class Alda::Rest < Alda::Event
|
|
463
615
|
#
|
464
616
|
# Underlines "_" in +duration+ will be converted to tildes "~".
|
465
617
|
def initialize duration
|
618
|
+
super()
|
466
619
|
@duration = duration.to_s.tr ?_, ?~
|
467
620
|
end
|
468
621
|
|
622
|
+
##
|
623
|
+
# :call-seq:
|
624
|
+
# to_alda_code() -> String
|
625
|
+
#
|
626
|
+
# Overrides Alda::Event#to_alda_code.
|
469
627
|
def to_alda_code
|
470
628
|
?r + @duration
|
471
629
|
end
|
630
|
+
|
631
|
+
##
|
632
|
+
# :call-seq:
|
633
|
+
# rest == other -> true or false
|
634
|
+
#
|
635
|
+
# Overrides Alda::Event#==.
|
636
|
+
# Returns true if +other+ is an Alda::Rest
|
637
|
+
# and has the same #duration as +rest+ (using <tt>==</tt>).
|
638
|
+
def == other
|
639
|
+
super || other.is_a?(Alda::Rest) && @duration == other.duration
|
640
|
+
end
|
472
641
|
end
|
473
642
|
|
474
643
|
##
|
@@ -501,6 +670,7 @@ class Alda::Octave < Alda::Event
|
|
501
670
|
#
|
502
671
|
# Creates an Alda::Octave.
|
503
672
|
def initialize num
|
673
|
+
super()
|
504
674
|
@num = num.to_s
|
505
675
|
@up_or_down = 0
|
506
676
|
end
|
@@ -531,6 +701,11 @@ class Alda::Octave < Alda::Event
|
|
531
701
|
self
|
532
702
|
end
|
533
703
|
|
704
|
+
##
|
705
|
+
# :call-seq:
|
706
|
+
# to_alda_code() -> String
|
707
|
+
#
|
708
|
+
# Overrides Alda::Event#to_alda_code.
|
534
709
|
def to_alda_code
|
535
710
|
case @up_or_down <=> 0
|
536
711
|
when 0
|
@@ -541,6 +716,17 @@ class Alda::Octave < Alda::Event
|
|
541
716
|
?< * -@up_or_down
|
542
717
|
end
|
543
718
|
end
|
719
|
+
|
720
|
+
##
|
721
|
+
# :call-seq:
|
722
|
+
# octave == other -> true or false
|
723
|
+
#
|
724
|
+
# Overrides Alda::Event#==.
|
725
|
+
# Returns true if +other+ is an Alda::Octave
|
726
|
+
# and has the same #num and #up_or_down as +octave+ (using <tt>==</tt>).
|
727
|
+
def == other
|
728
|
+
super || other.is_a?(Alda::Octave) && @num == other.num && @up_or_down == other.up_or_down
|
729
|
+
end
|
544
730
|
end
|
545
731
|
|
546
732
|
##
|
@@ -574,12 +760,39 @@ class Alda::Chord < Alda::Event
|
|
574
760
|
# Alda::Score.new { piano_; x { c; -e; g } }.play
|
575
761
|
# # (plays chord Cm)
|
576
762
|
def initialize *events, &block
|
763
|
+
events.each { _1.parent = self if _1.is_a? Alda::Event }
|
577
764
|
@events = events
|
578
765
|
super &block
|
579
766
|
end
|
580
767
|
|
768
|
+
##
|
769
|
+
# :call-seq:
|
770
|
+
# to_alda_code() -> String
|
771
|
+
#
|
772
|
+
# Overrides Alda::Event#to_alda_code.
|
773
|
+
#
|
774
|
+
# Behaves differently for \Alda 1 and \Alda 2:
|
775
|
+
# because \Alda 2 does not allow octave changes as part of a chord
|
776
|
+
# (something like <tt>a/>/c</tt>, and we have to write <tt>a>/c</tt> or <tt>a/>c</tt> instead)
|
777
|
+
# ({alda-lang/alda#383}[https://github.com/alda-lang/alda/issues/383]),
|
778
|
+
# the code generated by this method will omit the slash before an octave change.
|
779
|
+
#
|
780
|
+
# Alda.generation = :v1
|
781
|
+
# Alda::Score.new { a/o!/c; a/o5/c }.to_s # => "a/>/c a/o5/c"
|
782
|
+
# Alda.generation = :v2
|
783
|
+
# Alda::Score.new { a/o!/c; a/o5/c }.to_s # => "a>/c a o5/c"
|
581
784
|
def to_alda_code
|
582
|
-
events_alda_codes ?/
|
785
|
+
return events_alda_codes ?/ if Alda.v1?
|
786
|
+
@events.each_with_index.with_object '' do |(event, i), result|
|
787
|
+
if i == 0
|
788
|
+
# concat nothing
|
789
|
+
elsif event.is_event_of? Alda::Octave
|
790
|
+
result.concat ' ' unless event.num.empty?
|
791
|
+
else
|
792
|
+
result.concat '/'
|
793
|
+
end
|
794
|
+
result.concat event.to_alda_code
|
795
|
+
end
|
583
796
|
end
|
584
797
|
end
|
585
798
|
|
@@ -631,10 +844,16 @@ class Alda::Part < Alda::Event
|
|
631
844
|
#
|
632
845
|
# Creates an Alda::Part.
|
633
846
|
def initialize names, arg = nil
|
634
|
-
|
847
|
+
super()
|
848
|
+
@names = names.map { Alda::Utils.snake_to_slug _1 }
|
635
849
|
@arg = arg
|
636
850
|
end
|
637
851
|
|
852
|
+
##
|
853
|
+
# :call-seq:
|
854
|
+
# to_alda_code() -> String
|
855
|
+
#
|
856
|
+
# Overrides Alda::Event#to_alda_code.
|
638
857
|
def to_alda_code
|
639
858
|
result = @names.join ?/
|
640
859
|
result.concat " \"#{@arg}\"" if @arg
|
@@ -657,17 +876,26 @@ class Alda::Part < Alda::Event
|
|
657
876
|
str[-1] = ''
|
658
877
|
@names.last.concat ?., str
|
659
878
|
if args.size == 1
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
@container.event = Alda::Sequence.join self, args.first.tap(&:detach_from_parent)
|
666
|
-
@container
|
879
|
+
arg = args.first.tap &:detach_from_parent
|
880
|
+
detach_from_parent
|
881
|
+
container = Alda::EventContainer.new Alda::Sequence.join(self, arg), @parent
|
882
|
+
@parent.events.push container
|
883
|
+
container
|
667
884
|
else
|
668
885
|
@container || self
|
669
886
|
end
|
670
887
|
end
|
888
|
+
|
889
|
+
##
|
890
|
+
# :call-seq:
|
891
|
+
# part == other -> true or false
|
892
|
+
#
|
893
|
+
# Overrides Alda::Event#==.
|
894
|
+
# Returns true if +other+ is an Alda::Part
|
895
|
+
# and has the same #names and #arg as +part+ (using <tt>==</tt>).
|
896
|
+
def == other
|
897
|
+
super || other.is_a?(Alda::Part) && @names == other.names && @arg == other.arg
|
898
|
+
end
|
671
899
|
end
|
672
900
|
|
673
901
|
##
|
@@ -690,12 +918,29 @@ class Alda::Voice < Alda::Event
|
|
690
918
|
#
|
691
919
|
# Creates an Alda::Voice.
|
692
920
|
def initialize num
|
921
|
+
super()
|
693
922
|
@num = num
|
694
923
|
end
|
695
924
|
|
925
|
+
##
|
926
|
+
# :call-seq:
|
927
|
+
# to_alda_code() -> String
|
928
|
+
#
|
929
|
+
# Overrides Alda::Event#to_alda_code.
|
696
930
|
def to_alda_code
|
697
931
|
?V + num + ?:
|
698
932
|
end
|
933
|
+
|
934
|
+
##
|
935
|
+
# :call-seq:
|
936
|
+
# voice == other -> true or false
|
937
|
+
#
|
938
|
+
# Overrides Alda::Event#==.
|
939
|
+
# Returns true if +other+ is an Alda::Voice
|
940
|
+
# and has the same #num as +voice+ (using <tt>==</tt>).
|
941
|
+
def == other
|
942
|
+
super || other.is_a?(Alda::Voice) && @num == other.num
|
943
|
+
end
|
699
944
|
end
|
700
945
|
|
701
946
|
##
|
@@ -731,9 +976,25 @@ class Alda::Cram < Alda::Event
|
|
731
976
|
super &block
|
732
977
|
end
|
733
978
|
|
979
|
+
##
|
980
|
+
# :call-seq:
|
981
|
+
# to_alda_code() -> String
|
982
|
+
#
|
983
|
+
# Overrides Alda::Event#to_alda_code.
|
734
984
|
def to_alda_code
|
735
985
|
"{#{events_alda_codes}}#@duration"
|
736
986
|
end
|
987
|
+
|
988
|
+
##
|
989
|
+
# :call-seq:
|
990
|
+
# cram == other -> true or false
|
991
|
+
#
|
992
|
+
# Overrides Alda::EventList#==.
|
993
|
+
# Returns true if the super method returns true and +other+
|
994
|
+
# has the same #duration as +cram+ (using <tt>==</tt>).
|
995
|
+
def == other
|
996
|
+
super && @duration == other.duration
|
997
|
+
end
|
737
998
|
end
|
738
999
|
|
739
1000
|
##
|
@@ -760,12 +1021,29 @@ class Alda::Marker < Alda::Event
|
|
760
1021
|
#
|
761
1022
|
# Underlines in +name+ is converted to hyphens.
|
762
1023
|
def initialize name
|
763
|
-
|
1024
|
+
super()
|
1025
|
+
@name = Alda::Utils.snake_to_slug name
|
764
1026
|
end
|
765
1027
|
|
1028
|
+
##
|
1029
|
+
# :call-seq:
|
1030
|
+
# to_alda_code() -> String
|
1031
|
+
#
|
1032
|
+
# Overrides Alda::Event#to_alda_code.
|
766
1033
|
def to_alda_code
|
767
1034
|
?% + @name
|
768
1035
|
end
|
1036
|
+
|
1037
|
+
##
|
1038
|
+
# :call-seq:
|
1039
|
+
# marker == other -> true or false
|
1040
|
+
#
|
1041
|
+
# Overrides Alda::Event#==.
|
1042
|
+
# Returns true if +other+ is an Alda::Marker
|
1043
|
+
# and has the same #name as +marker+ (using <tt>==</tt>).
|
1044
|
+
def == other
|
1045
|
+
super || other.is_a?(Alda::Marker) && @name == other.name
|
1046
|
+
end
|
769
1047
|
end
|
770
1048
|
|
771
1049
|
##
|
@@ -789,12 +1067,29 @@ class Alda::AtMarker < Alda::Event
|
|
789
1067
|
#
|
790
1068
|
# Underlines "_" in +name+ is converted to hyphens "-".
|
791
1069
|
def initialize name
|
792
|
-
|
1070
|
+
super()
|
1071
|
+
@name = Alda::Utils.snake_to_slug name
|
793
1072
|
end
|
794
1073
|
|
1074
|
+
##
|
1075
|
+
# :call-seq:
|
1076
|
+
# to_alda_code() -> String
|
1077
|
+
#
|
1078
|
+
# Overrides Alda::Event#to_alda_code.
|
795
1079
|
def to_alda_code
|
796
1080
|
?@ + @name
|
797
1081
|
end
|
1082
|
+
|
1083
|
+
##
|
1084
|
+
# :call-seq:
|
1085
|
+
# at_marker == other -> true or false
|
1086
|
+
#
|
1087
|
+
# Overrides Alda::Event#==.
|
1088
|
+
# Returns true if +other+ is an Alda::AtMarker
|
1089
|
+
# and has the same #name as +at_marker+ (using <tt>==</tt>).
|
1090
|
+
def == other
|
1091
|
+
super || other.is_a?(Alda::AtMarker) && @name == other.name
|
1092
|
+
end
|
798
1093
|
end
|
799
1094
|
|
800
1095
|
##
|
@@ -814,7 +1109,8 @@ end
|
|
814
1109
|
# p((c d e f).event.class) # => Alda::Sequence
|
815
1110
|
# end
|
816
1111
|
#
|
817
|
-
# The effects of the two examples above are the same
|
1112
|
+
# The effects of the two examples above are technically the same
|
1113
|
+
# although actually the generated list of events are slightly different.
|
818
1114
|
class Alda::Sequence < Alda::Event
|
819
1115
|
include Alda::EventList
|
820
1116
|
|
@@ -829,6 +1125,8 @@ class Alda::Sequence < Alda::Event
|
|
829
1125
|
# [a].flatten # => [#<Object:...>]
|
830
1126
|
module RefineFlatten
|
831
1127
|
refine Array do
|
1128
|
+
##
|
1129
|
+
# Overrides Array#flatten.
|
832
1130
|
def flatten
|
833
1131
|
each_with_object [] do |element, result|
|
834
1132
|
if element.is_a? Array
|
@@ -842,8 +1140,13 @@ class Alda::Sequence < Alda::Event
|
|
842
1140
|
end
|
843
1141
|
using RefineFlatten
|
844
1142
|
|
1143
|
+
##
|
1144
|
+
# :call-seq:
|
1145
|
+
# to_alda_code() -> String
|
1146
|
+
#
|
1147
|
+
# Overrides Alda::Event#to_alda_code.
|
845
1148
|
def to_alda_code
|
846
|
-
|
1149
|
+
"[#{events_alda_codes}]"
|
847
1150
|
end
|
848
1151
|
|
849
1152
|
##
|
@@ -857,7 +1160,7 @@ class Alda::Sequence < Alda::Event
|
|
857
1160
|
def self.join *events
|
858
1161
|
new do
|
859
1162
|
@events = events.map do |event|
|
860
|
-
while event.is_a?(Alda::EventContainer) &&
|
1163
|
+
while event.is_a?(Alda::EventContainer) && event.count == 1 && event.labels.empty?
|
861
1164
|
event = event.event
|
862
1165
|
end
|
863
1166
|
event.is_a?(Alda::Sequence) ? event.events : event
|
@@ -894,10 +1197,6 @@ class Alda::SetVariable < Alda::Event
|
|
894
1197
|
# The name of the variable.
|
895
1198
|
attr_accessor :name
|
896
1199
|
|
897
|
-
##
|
898
|
-
# The events passed to it using arguments instead of a block.
|
899
|
-
attr_reader :original_events
|
900
|
-
|
901
1200
|
##
|
902
1201
|
# :call-seq:
|
903
1202
|
# new(name, *events, &block) -> Alda::SetVariable
|
@@ -905,21 +1204,38 @@ class Alda::SetVariable < Alda::Event
|
|
905
1204
|
# Creates an Alda::SetVariable.
|
906
1205
|
def initialize name, *events, &block
|
907
1206
|
@name = name.to_sym
|
908
|
-
@
|
909
|
-
@events = events.clone
|
1207
|
+
@events = events
|
910
1208
|
super &block
|
911
1209
|
end
|
912
1210
|
|
913
1211
|
##
|
1212
|
+
# :call-seq:
|
1213
|
+
# to_alda_code() -> String
|
1214
|
+
#
|
914
1215
|
# Specially, the returned value ends with a newline "\\n".
|
1216
|
+
# Overrides Alda::Event#to_alda_code.
|
915
1217
|
def to_alda_code
|
916
1218
|
"#@name = #{events_alda_codes}\n"
|
917
1219
|
end
|
918
1220
|
|
1221
|
+
##
|
1222
|
+
# See Alda::Event#on_contained.
|
919
1223
|
def on_contained
|
920
1224
|
super
|
921
1225
|
@parent.variables.add @name
|
922
|
-
@
|
1226
|
+
@events.detach_from_parent [self.class]
|
1227
|
+
@events.each { _1.parent = self if _1.is_a? Alda::Event }
|
1228
|
+
end
|
1229
|
+
|
1230
|
+
##
|
1231
|
+
# :call-seq:
|
1232
|
+
# set_variable == other -> true or false
|
1233
|
+
#
|
1234
|
+
# Overrides Alda::EventList#==.
|
1235
|
+
# Returns true if the super method returns true and +other+
|
1236
|
+
# has the same #name as +set_variable+ (using <tt>==</tt>).
|
1237
|
+
def == other
|
1238
|
+
super && @name == other.name
|
923
1239
|
end
|
924
1240
|
end
|
925
1241
|
|
@@ -942,12 +1258,29 @@ class Alda::GetVariable < Alda::Event
|
|
942
1258
|
#
|
943
1259
|
# Creates an Alda::GetVariable.
|
944
1260
|
def initialize name
|
1261
|
+
super()
|
945
1262
|
@name = name
|
946
1263
|
end
|
947
1264
|
|
1265
|
+
##
|
1266
|
+
# :call-seq:
|
1267
|
+
# to_alda_code() -> String
|
1268
|
+
#
|
1269
|
+
# Overrides Alda::Event#to_alda_code.
|
948
1270
|
def to_alda_code
|
949
1271
|
@name.to_s
|
950
1272
|
end
|
1273
|
+
|
1274
|
+
##
|
1275
|
+
# :call-seq:
|
1276
|
+
# get_variable == other -> true or false
|
1277
|
+
#
|
1278
|
+
# Overrides Alda::Event#==.
|
1279
|
+
# Returns true if +other+ is an Alda::GetVariable
|
1280
|
+
# and has the same #name as +get_variable+ (using <tt>==</tt>).
|
1281
|
+
def == other
|
1282
|
+
super || other.is_a?(Alda::GetVariable) && @name == other.name
|
1283
|
+
end
|
951
1284
|
end
|
952
1285
|
|
953
1286
|
##
|
@@ -974,10 +1307,69 @@ class Alda::LispIdentifier < Alda::Event
|
|
974
1307
|
#
|
975
1308
|
# Underlines "_" in +name+ is converted to hyphens "-".
|
976
1309
|
def initialize name
|
977
|
-
|
1310
|
+
super()
|
1311
|
+
@name = Alda::Utils.snake_to_slug name
|
978
1312
|
end
|
979
1313
|
|
1314
|
+
##
|
1315
|
+
# :call-seq:
|
1316
|
+
# to_alda_code() -> String
|
1317
|
+
#
|
1318
|
+
# Overrides Alda::Event#to_alda_code.
|
980
1319
|
def to_alda_code
|
981
1320
|
@name
|
982
1321
|
end
|
1322
|
+
|
1323
|
+
##
|
1324
|
+
# :call-seq:
|
1325
|
+
# lisp_identifier == other -> true or false
|
1326
|
+
#
|
1327
|
+
# Overrides Alda::Event#==.
|
1328
|
+
# Returns true if +other+ is an Alda::LispIdentifier
|
1329
|
+
# and has the same #name as +lisp_identifier+ (using <tt>==</tt>).
|
1330
|
+
def == other
|
1331
|
+
super || other.is_a?(Alda::LispIdentifier) && @name == other.name
|
1332
|
+
end
|
1333
|
+
end
|
1334
|
+
|
1335
|
+
##
|
1336
|
+
# A special event that contains raw \Alda codes.
|
1337
|
+
# This is a walkaround for the absence of <tt>alda-code</tt> function in \Alda 2
|
1338
|
+
# ({alda-lang/alda#379}[https://github.com/alda-lang/alda/issues/379]).
|
1339
|
+
# You can use Alda::EventList#raw to add an Alda::Raw event to the event list.
|
1340
|
+
class Alda::Raw < Alda::Event
|
1341
|
+
|
1342
|
+
##
|
1343
|
+
# The raw \Alda codes.
|
1344
|
+
attr_accessor :contents
|
1345
|
+
|
1346
|
+
##
|
1347
|
+
# :call-seq:
|
1348
|
+
# new(code) -> Alda::Raw
|
1349
|
+
#
|
1350
|
+
# Creates an Alda::Raw.
|
1351
|
+
def initialize contents
|
1352
|
+
super()
|
1353
|
+
@contents = contents
|
1354
|
+
end
|
1355
|
+
|
1356
|
+
##
|
1357
|
+
# :call-seq:
|
1358
|
+
# to_alda_code() -> String
|
1359
|
+
#
|
1360
|
+
# Overrides Alda::Event#to_alda_code.
|
1361
|
+
def to_alda_code
|
1362
|
+
@contents
|
1363
|
+
end
|
1364
|
+
|
1365
|
+
##
|
1366
|
+
# :call-seq:
|
1367
|
+
# raw == other -> true or false
|
1368
|
+
#
|
1369
|
+
# Overrides Alda::Event#==.
|
1370
|
+
# Returns true if +other+ is an Alda::Raw
|
1371
|
+
# and has the same #contents as +raw+ (using <tt>==</tt>).
|
1372
|
+
def == other
|
1373
|
+
super || other.is_a?(Alda::Raw) && @contents == other.contents
|
1374
|
+
end
|
983
1375
|
end
|