class Alda::EventContainer

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.

Attributes

count[RW]

The repetition counts. nil if none.

Alda::Score.new do
  p((c*2).count)   # => 2
  p((d*3*5).count) # => 15
end
event[RW]

The contained Alda::Event object.

 Alda::Score.new do
   p c.event.class      # => Alda::Note
   p((e/g).event.class) # => Alda::Chord
   p((a b).event.class) # => Alda::Sequence
end

When setting this attribute, on_containing is invoked.

labels[RW]

The repetition labels. Empty if none.

Alda::Score.new do
  p((c%2).labels)        # => [2]
  p((c%[2,4..6]).labels) # => [2, 4..6]
end

Public Class Methods

new(event, parent) → Alda::EventContainer click to toggle source

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.

Calls superclass method
# File lib/alda-rb/event.rb, line 147
def initialize event, parent
  super()
  @event = event
  @labels = []
  @count = 1
  self.parent = parent
  on_containing
end

Public Instance Methods

container % labels → container click to toggle source

Marks alternative endings.

Alda::Score.new { (b a%1)*2 }.to_s
# => "[b a'1]*2"
# 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
container * num → container click to toggle source

Marks repetition.

For examples, see %.

# File lib/alda-rb/event.rb, line 218
def * num
  @count = (@count || 1) * num
  check_in_chord
  self
end
container / other → container click to toggle source

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)
# 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
container == other → true or false click to toggle source

Overrides Alda::Event#==. Returns true if other is an Alda::EventContainer object and event, count and labels are all equal (using ==).

Calls superclass method Alda::Event#==
# 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() → true or false click to toggle source

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"
# 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) → true or false click to toggle source

Overrides Alda::Event#is_event_of?. Whether it is an event of the given class (klass) or the contained event is.

Calls superclass method Alda::Event#is_event_of?
# File lib/alda-rb/event.rb, line 301
def is_event_of? klass
  super || @event.is_event_of?(klass)
end
(missing method) → obj click to toggle source

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
# File lib/alda-rb/event.rb, line 335
def method_missing(...)
  result = @event.__send__(...)
  result == @event ? self : result
end
on_containing() click to toggle source

A callback invoked in event= and ::new.

# 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) → event click to toggle source

Overrides Alda::Event#parent=. Sets the Alda::Event#parent of the container as well as that of event.

# File lib/alda-rb/event.rb, line 279
def parent= event
  @parent = event
  check_in_chord
  @event.parent = event
end
to_alda_code() → String click to toggle source

Overrides Alda::Event#to_alda_code.

# 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