Module: Alda::EventList
- Included in:
- Chord, Cram, Score, Sequence, SetVariable
- Defined in:
- lib/alda-rb/event_list.rb
Overview
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.
Instance Attribute Summary collapse
-
#events ⇒ Object
The array containing the events (Alda::Event objects), most of which are Alda::EventContainer objects.
-
#variables ⇒ Object
The set containing the available variable names.
Instance Method Summary collapse
-
#==(other) ⇒ Object
:call-seq: event_list == other -> true or false.
-
#events_alda_codes(delimiter = ' ') ⇒ Object
:call-seq: events_alda_codes(delimiter=“ ”) -> String.
-
#has_variable?(name) ⇒ Boolean
:call-seq: has_variable?(name) -> true or false.
-
#import(event_list) ⇒ Object
:call-seq: import(event_list) -> nil.
-
#initialize(&block) ⇒ Object
:call-seq: new(&block) -> Alda::EventList.
-
#method_missing(name, *args, &block) ⇒ Object
:call-seq: (some sugar) -> Alda::EventContainer.
-
#on_contained ⇒ Object
When the module is included by a subclass of Alda::Event, this method overrides Alda::Event#on_contained.
-
#to_a ⇒ Object
:call-seq: to_a -> Array.
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(name, *args, &block) ⇒ Object
:call-seq:
(some sugar) -> Alda::EventContainer
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.
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
# 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 |
Instance Attribute Details
#events ⇒ Object
The array containing the events (Alda::Event objects), most of which are Alda::EventContainer objects.
12 13 14 |
# File 'lib/alda-rb/event_list.rb', line 12 def events @events end |
#variables ⇒ Object
The set containing the available variable names.
16 17 18 |
# File 'lib/alda-rb/event_list.rb', line 16 def variables @variables end |
Instance Method Details
#==(other) ⇒ Object
:call-seq:
event_list == other -> true or false
Returns true if other
is of the same class as event_list
and they have the same (in the sense of ==
) #events and #variables.
215 216 217 |
# File 'lib/alda-rb/event_list.rb', line 215 def == other super || self.class == other.class && @events == other.events && @variables == other.variables end |
#events_alda_codes(delimiter = ' ') ⇒ Object
:call-seq:
events_alda_codes(delimiter=" ") -> String
Join the alda codes of #events with a specified delimiter. Returns a string representing the result.
205 206 207 |
# File 'lib/alda-rb/event_list.rb', line 205 def events_alda_codes delimiter = ' ' @events.map(&:to_alda_code).join delimiter end |
#has_variable?(name) ⇒ Boolean
:call-seq:
has_variable?(name) -> true or false
Whether there is a previously declared alda variable whose name is specified by name
.
Searches variables in #parent.
145 146 147 |
# File 'lib/alda-rb/event_list.rb', line 145 def has_variable? name @variables.include?(name) || !!@parent&.has_variable?(name) end |
#import(event_list) ⇒ Object
:call-seq:
import(event_list) -> nil
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).
157 158 159 160 |
# File 'lib/alda-rb/event_list.rb', line 157 def import event_list @events.concat event_list.events nil end |
#initialize(&block) ⇒ Object
:call-seq:
new(&block) -> Alda::EventList
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.
184 185 186 187 188 |
# File 'lib/alda-rb/event_list.rb', line 184 def initialize &block @events ||= [] @variables ||= Set.new @block ||= block end |
#on_contained ⇒ Object
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.
23 24 25 26 |
# File 'lib/alda-rb/event_list.rb', line 23 def on_contained super if defined? super instance_eval &@block if @block end |
#to_a ⇒ Object
:call-seq:
to_a -> Array
Same as #events.
195 196 197 |
# File 'lib/alda-rb/event_list.rb', line 195 def to_a @events end |