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
The array containing the events (Alda::Event
objects), most of which are Alda::EventContainer
objects.
The set containing the available variable names.
Public Class Methods
The parameter 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 184 def initialize &block @events ||= [] @variables ||= Set.new @block ||= block end
Public Instance Methods
Returns true if other
is of the same class as event_list
and they have the same (in the sense of ==
) events
and variables
.
# File lib/alda-rb/event_list.rb, line 215 def == other super || self.class == other.class && @events == other.events && @variables == other.variables end
Join the alda codes of events
with a specified delimiter. Returns a string representing the result.
# File lib/alda-rb/event_list.rb, line 205 def events_alda_codes delimiter = ' ' @events.map(&:to_alda_code).join delimiter end
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 145 def has_variable? name @variables.include?(name) || !!@parent&.has_variable?(name) end
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 (alda-lang/alda-core#8).
# File lib/alda-rb/event_list.rb, line 157 def import event_list @events.concat event_list.events nil end
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
.
-
Ending with 2 underlines: set variable. See
Alda::SetVariable
. -
Starting with 2 lowercase letters and ending with underline character: instrument. See
Alda::Part
. This will trigger a warning if we are using Alda 2 because parts inside a sequence are not allowed in Alda 2 (alda-lang/alda#441). -
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
. -
Starting with “t”: CRAM. See
Alda::Cram
. -
Starting with one of “a”, “b”, …, “g”: note. See
Alda::Note
. -
Starting with “r”: rest. See
Alda::Rest
. -
“x”: chord. See
Alda::Chord
. -
“s”: sequence. See
Alda::Sequence
. -
Starting with “o”: octave. See
Alda::Octave
. -
Starting with “v”: voice. See
Alda::Voice
. -
Starting with “__” (2 underlines): at marker. See
Alda::AtMarker
. -
Starting with “_” (underline) and ending with “_” (underline): lisp identifier. See
Alda::LispIdentifier
. -
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.
# File lib/alda-rb/event_list.rb, line 75 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 Alda::Utils.warn 'parts in sequence not allowed in v2' if Alda.v2? && !args.empty? 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_event_of?(Alda::InlineLisp) && !arg.is_event_of?(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
When the module is included by a subclass of Alda::Event
, this method overrides Alda::Event#on_contained
. When invoked, calls the overridden method (if any) and then evaluates the block given when ::new
was called.
# File lib/alda-rb/event_list.rb, line 23 def on_contained super if defined? super instance_eval &@block if @block end
Same as events
.
# File lib/alda-rb/event_list.rb, line 195 def to_a @events end