Class: Alda::EventContainer
Overview
The class for objects containing an event.
Alda::EventContainer objects are literally everywhere if you are a heavy user of event list sugars. See Alda::EventList#method_missing.
Instance Attribute Summary collapse
-
#count ⇒ Object
The repetition counts.
-
#event ⇒ Object
The contained Alda::Event object.
-
#labels ⇒ Object
The repetition labels.
Attributes inherited from Event
Instance Method Summary collapse
-
#%(labels) ⇒ Object
:call-seq: container % labels -> container.
-
#*(num) ⇒ Object
:call-seq: container * num -> container.
-
#/(other) ⇒ Object
:call-seq: container / other -> container.
-
#==(other) ⇒ Object
:call-seq: container == other -> true or false.
-
#check_in_chord ⇒ Object
:call-seq: check_in_chord() -> true or false.
-
#initialize(event, parent) ⇒ EventContainer
constructor
:call-seq: new(event, parent) -> Alda::EventContainer.
-
#is_event_of?(klass) ⇒ Boolean
:call-seq: is_event_of?(klass) -> true or false.
-
#method_missing ⇒ Object
:call-seq: (missing method) -> obj.
-
#on_containing ⇒ Object
A callback invoked in #event= and ::new.
-
#parent=(event) ⇒ Object
:call-seq: parent=(event) -> event.
-
#to_alda_code ⇒ Object
:call-seq: to_alda_code() -> String.
Methods inherited from Event
#detach_from_parent, #on_contained
Constructor Details
#initialize(event, parent) ⇒ EventContainer
:call-seq:
new(event, parent) -> Alda::EventContainer
Creates a new Alda::EventContainer. Invokes #on_containing.
event
is the Alda::Event object to be contained.
parent
is the Alda::EventList object containing the event.
147 148 149 150 151 152 153 154 |
# File 'lib/alda-rb/event.rb', line 147 def initialize event, parent super() @event = event @labels = [] @count = 1 self.parent = parent on_containing end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing ⇒ Object
:call-seq:
(missing method) -> obj
Calls method on #event.
Note that if the method of #event returns #event itself, the method here returns the container itself.
Alda::Score.new do
container = c
p container.class # => Alda::EventContainer
p container.respond_to? :pitch # => false
p container.pitch # => "c"
p container.respond_to? :+@ # => false
p((+container).class) # => Alda::EventContainer
p to_s # => "c+"
end
335 336 337 338 |
# File 'lib/alda-rb/event.rb', line 335 def method_missing(...) result = @event.__send__(...) result == @event ? self : result end |
Instance Attribute Details
#count ⇒ Object
126 127 128 |
# File 'lib/alda-rb/event.rb', line 126 def count @count end |
#event ⇒ Object
117 118 119 |
# File 'lib/alda-rb/event.rb', line 117 def event @event end |
Instance Method Details
#%(labels) ⇒ Object
232 233 234 235 236 237 |
# File 'lib/alda-rb/event.rb', line 232 def % labels labels = [labels] unless labels.is_a? Array @labels.replace labels.to_a check_in_chord self end |
#*(num) ⇒ Object
:call-seq:
container * num -> container
Marks repetition.
For examples, see #%.
218 219 220 221 222 |
# File 'lib/alda-rb/event.rb', line 218 def * num @count = (@count || 1) * num check_in_chord self end |
#/(other) ⇒ Object
:call-seq:
container / other -> container
If at first #event is not an Alda::Part, makes #event an Alda::Chord object.
Alda::Score.new { piano_; c/-e/g }.play
# (plays the chord Cm)
This usage assumes that other
is an Alda::EventContainer and will extract the contained event out from other
. This will lose some information about other
, such as #count and #labels, and potentially lead to confusing results.
Because the #labels information about other
is lost, the label on d
disappears in the following example:
Alda::Score.new { c/(d%1) }.to_s # => "c/d"
The following example shows that the two ways of writing a chord with a label are equivalent: adding the label and then using slash, or using slash and then adding the label. This is because #labels and #count are retained while the #event is updated when #/ is called.
Alda::Score.new { p c%1/d == c/d%1 }.to_s # (prints "true") => "c/d'1 c/d'1"
If at first #event is an Alda::Part object, makes #event a new Alda::Part object. The meaning is to play the two parts simultaneously.
Alda::Score.new { violin_/viola_/cello_; e; f; g}.play
# (plays notes E, F, G with three instruments simultaneously)
188 189 190 191 192 193 194 195 196 197 |
# File 'lib/alda-rb/event.rb', line 188 def / other other.detach_from_parent @event = if @event.is_a? Alda::Part Alda::Part.new @event.names + other.event.names, other.event.arg else Alda::Chord.new @event, other.event end self end |
#==(other) ⇒ Object
:call-seq:
container == other -> true or false
Overrides Alda::Event#==. Returns true if other
is an Alda::EventContainer object and #event, #count and #labels are all equal (using ==
).
312 313 314 315 |
# File 'lib/alda-rb/event.rb', line 312 def == other super || other.is_a?(Alda::EventContainer) && @event == other.event && @count == other.count && @labels == other.labels end |
#check_in_chord ⇒ Object
:call-seq:
check_in_chord() -> true or false
This method is called in #%, #*, and #parent=. It checks if #parent is an Alda::Chord and warns about potential dangers. Returns true if there is no danger, and false otherwise.
Because Alda 2 does not support specifying alternative endings inside a chord (something like a'1/b
) (alda-lang/alda#383), this method will warn about this if such thing happens and we are using Alda 2.
Alda.v2!
Alda::Score.new { x{a%1;b} }.to_s # (warns) => "a'1/b"
This method will warn about repetitions inside a chord in both generations because the resultant Alda code is not valid.
Alda::Score.new { x{a*2;b} }.to_s # (warns) => "a*2/b"
263 264 265 266 267 268 269 270 271 |
# File 'lib/alda-rb/event.rb', line 263 def check_in_chord if @parent.is_a?(Alda::Event) && @parent.is_event_of?(Alda::Chord) Alda::Utils.warn 'alternative endings in chord not allowed in v2' if Alda.v2? && !@labels&.empty? Alda::Utils.warn 'repetitions in chord not allowed' if @count && @count != 1 false else true end end |
#is_event_of?(klass) ⇒ Boolean
:call-seq:
is_event_of?(klass) -> true or false
Overrides Alda::Event#is_event_of?. Whether it is an event of the given class (klass
) or the contained event is.
301 302 303 |
# File 'lib/alda-rb/event.rb', line 301 def is_event_of? klass super || @event.is_event_of?(klass) end |
#on_containing ⇒ Object
A callback invoked in #event= and ::new.
287 288 289 290 291 292 |
# File 'lib/alda-rb/event.rb', line 287 def on_containing return unless @event @event.container = self @event.parent = @parent @event.on_contained end |
#parent=(event) ⇒ Object
:call-seq:
parent=(event) -> event
Overrides Alda::Event#parent=. Sets the Alda::Event#parent of the container as well as that of #event.
279 280 281 282 283 |
# File 'lib/alda-rb/event.rb', line 279 def parent= event @parent = event check_in_chord @event.parent = event end |
#to_alda_code ⇒ Object
:call-seq:
to_alda_code() -> String
Overrides Alda::Event#to_alda_code.
204 205 206 207 208 209 |
# File 'lib/alda-rb/event.rb', line 204 def to_alda_code result = @event.to_alda_code result.concat ?', @labels.map(&:to_alda_code).join(?,) unless @labels.empty? result.concat ?*, @count.to_alda_code if @count != 1 result end |