alda-rb 0.2.1 → 0.3.1
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/.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
|