module Alda::EventList

Including this module can make your class have the ability to have an event list. See docs below to get an overview of its functions.

Attributes

events[RW]

The array containing the events (Alda::Event objects), most of which are Alda::EventContainer objects.

variables[RW]

The set containing the available variable names.

Public Class Methods

new(&block) → Alda::EventList click to toggle source

block is to be passed with the Alda::EventList object as self.

Note that block is not called immediately. It is instead called in on_contained. Specially, Alda::Score::new calls on_contained.

Alda::Score.new do
  tempo! 108           # inline lisp
  piano_               # piano part
  o4                   # octave 4
  c8; d; e; f          # notes
  g4 g a f g e f d e c # a sequence
  d4_8                 # cannot have '~', use '_' instead
  o3 b8 o4 c2          # a sequence
end
# => #<Alda::Score:0x... @events=[...]>

For a list of sugars, see method_missing.

# File lib/alda-rb/event_list.rb, line 177
def initialize &block
        @events ||= []
        @variables ||= Set.new
        @block ||= block
end

Public Instance Methods

events_alda_codes(delimiter=" ") → String click to toggle source

Join the alda codes of events with a specified delimiter. Returns a string representing the result.

# File lib/alda-rb/event_list.rb, line 198
def events_alda_codes delimiter = ' '
        @events.map(&:to_alda_code).join delimiter
end
has_variable?(name) → true or false click to toggle source

Whether there is a previously declared alda variable whose name is specified by name.

Searches variables in parent.

# File lib/alda-rb/event_list.rb, line 138
def has_variable? name
        @variables.include?(name) || !!@parent&.has_variable?(name)
end
import(event_list) → nil click to toggle source

Append the events of another Alda::EventList object here. This method covers the disadvantage of alda's being unable to import scores from other files. See github.com/alda-lang/alda-core/issues/8.

# File lib/alda-rb/event_list.rb, line 150
def import event_list
        @events.concat event_list.events
        nil
end
(some sugar) → Alda::EventContainer click to toggle source

Make the object have the ability to append its events conveniently.

Here is a list of sugar. When the name of a method meets certain condition, the method is regarded as an event appended to events.

  1. Ending with 2 underlines: set variable. See Alda::SetVariable.

  2. Starting with 2 lowercase letters and ending with underline character: instrument. See Alda::Part.

  3. Starting with 2 lowercase letters: inline lisp code, set variable, or get variable. One of the above three is chosen intelligently. See Alda::InlineLisp, Alda::SetVariable, Alda::GetVariable.

  4. Starting with “t”: CRAM. See Alda::Cram.

  5. Starting with one of “a”, “b”, …, “g”: note. See Alda::Note.

  6. Starting with “r”: rest. See Alda::Rest.

  7. “x”: chord. See Alda::Chord.

  8. “s”: sequence. See Alda::Sequence.

  9. Starting with “o”: octave. See Alda::Octave.

  10. Starting with “v”: voice. See Alda::Voice.

  11. Starting with “__” (2 underlines): at marker. See Alda::AtMarker.

  12. Starting with “_” (underline) and ending with “_” (underline): lisp identifier. See Alda::LispIdentifier.

  13. Starting with “_” (underline): marker. See Alda::Marker.

All the appended events are contained in an Alda::EventContainer object, which is to be returned.

These sugars forms a DSL. See ::new for examples.

Calls superclass method
# File lib/alda-rb/event_list.rb, line 67
def method_missing name, *args, &block
        if @parent&.respond_to? name, true
                return @parent.__send__ name, *args, &block
        end
        sequence_sugar = ->event do
                if args.size == 1
                        Alda::Sequence.join event, args.first.tap(&:detach_from_parent)
                else
                        event
                end
        end
        case
        when /\A(?<head>[a-z][a-z].*)__\z/        =~ name
                Alda::SetVariable.new head, *args, &block
        when /\A(?<part>[a-z][a-z].*)_\z/         =~ name
                if args.first.is_a? String
                        Alda::Part.new [part], args.first
                else
                        sequence_sugar.(Alda::Part.new [part])
                end
        when /\A[a-z][a-z].*\z/                   =~ name
                arg = args.first
                if block || !has_variable?(name) && args.size == 1 && arg.is_a?(Alda::Event) &&
                                !arg.is_a?(Alda::InlineLisp) && !arg.is_a?(Alda::LispIdentifier) &&
                                !(arg.is_a?(Alda::EventContainer) &&
                                                (arg.event.is_a?(Alda::InlineLisp) || arg.event.is_a?(Alda::LispIdentifier)))
                        Alda::SetVariable.new name, *args, &block
                elsif has_variable?(name) && (args.empty? || args.size == 1 && arg.is_a?(Alda::Event))
                        sequence_sugar.(Alda::GetVariable.new name)
                else
                        Alda::InlineLisp.new name, *args
                end
        when /\At(?<duration>.*)\z/               =~ name
                Alda::Cram.new duration, &block
        when /\A(?<pitch>[a-g])(?<duration>.*)\z/ =~ name
                sequence_sugar.(Alda::Note.new pitch, duration)
        when /\Ar(?<duration>.*)\z/               =~ name
                sequence_sugar.(Alda::Rest.new duration)
        when /\Ax\z/                              =~ name
                Alda::Chord.new &block
        when /\As\z/                              =~ name
                Alda::Sequence.new *args, &block
        when /\Ao!\z/                             =~ name
                sequence_sugar.(Alda::Octave.new('').tap { _1.up_or_down = 1})
        when /\Ao\?\z/                            =~ name
                sequence_sugar.(Alda::Octave.new('').tap { _1.up_or_down = -1})
        when /\Ao(?<num>\d*)\z/                   =~ name
                sequence_sugar.(Alda::Octave.new num)
        when /\Av(?<num>\d+)\z/                   =~ name
                sequence_sugar.(Alda::Voice.new num)
        when /\A__(?<head>.+)\z/                  =~ name
                sequence_sugar.(Alda::AtMarker.new head)
        when /\A_(?<head>.+)_\z/                  =~ name
                sequence_sugar.(Alda::LispIdentifier.new head)
        when /\A_(?<head>.+)\z/                   =~ name
                sequence_sugar.(Alda::Marker.new head)
        else
                super
        end.then do |event|
                Alda::EventContainer.new event, self
        end.tap { @events.push _1 }
end
on_contained() click to toggle source
Calls superclass method
# File lib/alda-rb/event_list.rb, line 18
def on_contained
        super if defined? super
        instance_eval &@block if @block
end
to_a → Array click to toggle source

Same as events.

# File lib/alda-rb/event_list.rb, line 188
def to_a
        @events
end