alda-rb 0.2.1 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -15,6 +15,11 @@ module Alda::EventList
15
15
  # The set containing the available variable names.
16
16
  attr_accessor :variables
17
17
 
18
+ ##
19
+ # When the module is included by a subclass of Alda::Event,
20
+ # this method overrides Alda::Event#on_contained.
21
+ # When invoked, calls the overridden method (if any) and then evaluates the block
22
+ # given when ::new was called.
18
23
  def on_contained
19
24
  super if defined? super
20
25
  instance_eval &@block if @block
@@ -33,6 +38,9 @@ module Alda::EventList
33
38
  #
34
39
  # 2. Starting with 2 lowercase letters and
35
40
  # ending with underline character: instrument. See Alda::Part.
41
+ # This will trigger a warning if we are using \Alda 2 because
42
+ # parts inside a sequence are not allowed in \Alda 2
43
+ # ({alda-lang/alda#441}[https://github.com/alda-lang/alda/discussions/441#discussioncomment-3825064]).
36
44
  #
37
45
  # 3. Starting with 2 lowercase letters: inline lisp code,
38
46
  # set variable, or get variable.
@@ -82,14 +90,13 @@ module Alda::EventList
82
90
  if args.first.is_a? String
83
91
  Alda::Part.new [part], args.first
84
92
  else
93
+ Alda::Utils.warn 'parts in sequence not allowed in v2' if Alda.v2? && !args.empty?
85
94
  sequence_sugar.(Alda::Part.new [part])
86
95
  end
87
96
  when /\A[a-z][a-z].*\z/ =~ name
88
97
  arg = args.first
89
98
  if block || !has_variable?(name) && args.size == 1 && arg.is_a?(Alda::Event) &&
90
- !arg.is_a?(Alda::InlineLisp) && !arg.is_a?(Alda::LispIdentifier) &&
91
- !(arg.is_a?(Alda::EventContainer) &&
92
- (arg.event.is_a?(Alda::InlineLisp) || arg.event.is_a?(Alda::LispIdentifier)))
99
+ !arg.is_event_of?(Alda::InlineLisp) && !arg.is_event_of?(Alda::LispIdentifier)
93
100
  Alda::SetVariable.new name, *args, &block
94
101
  elsif has_variable?(name) && (args.empty? || args.size == 1 && arg.is_a?(Alda::Event))
95
102
  sequence_sugar.(Alda::GetVariable.new name)
@@ -145,8 +152,8 @@ module Alda::EventList
145
152
  #
146
153
  # Append the events of another Alda::EventList object here.
147
154
  # This method covers the disadvantage of alda's being unable to
148
- # import scores from other files.
149
- # See https://github.com/alda-lang/alda-core/issues/8.
155
+ # import scores from other files
156
+ # ({alda-lang/alda-core#8}[https://github.com/alda-lang/alda-core/issues/8]).
150
157
  def import event_list
151
158
  @events.concat event_list.events
152
159
  nil
@@ -156,7 +163,7 @@ module Alda::EventList
156
163
  # :call-seq:
157
164
  # new(&block) -> Alda::EventList
158
165
  #
159
- # +block+ is to be passed with the Alda::EventList object as +self+.
166
+ # The parameter +block+ is to be passed with the Alda::EventList object as +self+.
160
167
  #
161
168
  # Note that +block+ is not called immediately.
162
169
  # It is instead called in #on_contained.
@@ -198,6 +205,16 @@ module Alda::EventList
198
205
  def events_alda_codes delimiter = ' '
199
206
  @events.map(&:to_alda_code).join delimiter
200
207
  end
208
+
209
+ ##
210
+ # :call-seq:
211
+ # event_list == other -> true or false
212
+ #
213
+ # Returns true if +other+ is of the same class as +event_list+
214
+ # and they have the same (in the sense of <tt>==</tt>) #events and #variables.
215
+ def == other
216
+ super || self.class == other.class && @events == other.events && @variables == other.variables
217
+ end
201
218
  end
202
219
 
203
220
  ##
@@ -222,7 +239,7 @@ class Alda::Score
222
239
  # Alda::Score.new { piano_; c; d; e }.play from: 1
223
240
  # # (plays only an E note)
224
241
  def play **opts
225
- Alda.play code: self, **opts
242
+ Alda.env(ALDA_DISABLE_SPAWNING: :no) { Alda.play code: self, **opts }
226
243
  end
227
244
 
228
245
  ##
@@ -270,13 +287,13 @@ class Alda::Score
270
287
 
271
288
  ##
272
289
  # :call-seq:
273
- # load(filename) -> Alda::InlineLisp
290
+ # load(filename) -> Alda::Raw
274
291
  #
275
292
  # Loads alda codes from a file.
276
293
  #
277
- # Actually appends a Alda::InlineLisp event of +alda-code+ lisp call.
294
+ # Actually appends a Alda::Raw event with the contents in the file +filename+.
278
295
  def load filename
279
- event = Alda::InlineLisp.new :alda_code, File.read(filename)
296
+ event = Alda::Raw.new File.read filename
280
297
  @events.push event
281
298
  event
282
299
  end
@@ -310,4 +327,34 @@ class Alda::Score
310
327
  @variables.clear
311
328
  nil
312
329
  end
330
+
331
+ ##
332
+ # :call-seq:
333
+ # raw(contents) -> Alda::Raw
334
+ #
335
+ # Adds an Alda::Raw event to the event list and returns it.
336
+ # The event is not contained by a container.
337
+ #
338
+ # Alda::Score.new { raw 'piano: c d e' }.to_s # => "piano: c d e"
339
+ def raw contents
340
+ Alda::Raw.new(contents).tap { @events.push _1 }
341
+ end
342
+
343
+ ##
344
+ # :call-seq:
345
+ # l(head, *args) -> Alda::EventContainer
346
+ #
347
+ # Adds an Alda::EventContainer containing an Alda::InlineLisp event to the event list.
348
+ # In most cases, #method_misssing is a more convenient way to add an inline Lisp event.
349
+ # However, sometimes you may want to programmatically control which Lisp function to be called,
350
+ # or the function name is already a valid Ruby method name
351
+ # (for example, you want to use +f+ or +p+ as the dynamics but +f+ would be interpreted as a note
352
+ # and +p+ is already a Ruby method for printing)
353
+ # so that it cannot trigger #method_missing,
354
+ # then you should use this method.
355
+ #
356
+ # Alda::Score.new { piano_; l :p; c }.to_s # => "piano: (p ) c"
357
+ def l head, *args
358
+ Alda::EventContainer.new(Alda::InlineLisp.new(head, *args), self).tap { @events.push _1 }
359
+ end
313
360
  end
@@ -1,41 +1,89 @@
1
1
  require 'stringio'
2
2
 
3
3
  ##
4
+ # Contains patches to Ruby's core classes.
5
+ class Thread
6
+ ##
7
+ # Because \Alda 2 uses quoted lists to denote lists (vectors) of symbols,
8
+ # we have to keep track of whether we are inside a list already
9
+ # (because this notation is inconsistent for inner lists and outer lists).
10
+ attr_accessor :inside_alda_list
11
+ end
12
+
13
+ ##
14
+ # Contains patches to Ruby's core classes.
4
15
  class Array
5
16
 
6
17
  ##
18
+ # :call-seq:
19
+ # to_alda_code() -> String
20
+ #
7
21
  # See Alda::Event#to_alda_code.
22
+ # Behaves differently for \Alda 1 and \Alda 2 (due to
23
+ # {a breaking change}[https://github.com/alda-lang/alda/blob/master/doc/alda-2-migration-guide.md#attribute-syntax-has-changed-in-some-cases]).
8
24
  def to_alda_code
9
- "[#{map(&:to_alda_code).join ' '}]"
25
+ contents = -> { map(&:to_alda_code).join ' ' }
26
+ if Alda.v1?
27
+ "[#{contents.()}]"
28
+ else
29
+ thread = Thread.current
30
+ if thread.inside_alda_list
31
+ "(#{contents.()})"
32
+ else
33
+ thread.inside_alda_list = true
34
+ "'(#{contents.()})".tap { thread.inside_alda_list = false }
35
+ end
36
+ end
10
37
  end
11
38
 
12
39
  ##
13
40
  # See Alda::Event#detach_from_parent.
14
- def detach_from_parent
15
- reverse_each &:detach_from_parent
41
+ def detach_from_parent(...)
42
+ reverse_each { _1.detach_from_parent(...) }
16
43
  end
17
44
  end
18
45
 
19
46
  ##
47
+ # Contains patches to Ruby's core classes.
20
48
  class Hash
21
49
 
22
50
  ##
51
+ # :call-seq:
52
+ # to_alda_code() -> String
53
+ #
23
54
  # See Alda::Event#to_alda_code.
55
+ # Behaves differently for \Alda 1 and \Alda 2 (due to
56
+ # {a breaking change}[https://github.com/alda-lang/alda/blob/master/doc/alda-2-migration-guide.md#attribute-syntax-has-changed-in-some-cases]).
24
57
  def to_alda_code
25
- "[#{map(&:to_alda_code).join ' '}]"
58
+ contents = -> { map { "#{_1.to_alda_code} #{_2.to_alda_code}" }.join ' ' }
59
+ if Alda.v1?
60
+ "{#{contents.()}}"
61
+ else
62
+ thread = Thread.current
63
+ if thread.inside_alda_list
64
+ "(#{contents.()})"
65
+ else
66
+ thread.inside_alda_list = true
67
+ "'(#{contents.()})".tap { thread.inside_alda_list = false }
68
+ end
69
+ end
26
70
  end
27
71
 
28
72
  ##
29
73
  # See Alda::Event#detach_from_parent.
30
- def detach_from_parent
31
- each.reverse_each &:detach_from_parent
74
+ def detach_from_parent(...)
75
+ each.reverse_each { _1.detach_from_parent(...) }
32
76
  end
33
77
  end
34
78
 
35
79
  ##
80
+ # Contains patches to Ruby's core classes.
36
81
  class String
37
82
 
38
83
  ##
84
+ # :call-seq:
85
+ # to_alda_code() -> String
86
+ #
39
87
  # See Alda::Event#to_alda_code.
40
88
  def to_alda_code
41
89
  dump
@@ -43,29 +91,37 @@ class String
43
91
 
44
92
  ##
45
93
  # See Alda::Event#detach_from_parent.
46
- def detach_from_parent
94
+ def detach_from_parent(...)
47
95
  end
48
96
  end
49
97
 
50
98
  ##
99
+ # Contains patches to Ruby's core classes.
51
100
  class Symbol
52
101
 
53
102
  ##
103
+ # :call-seq:
104
+ # to_alda_code() -> String
105
+ #
54
106
  # See Alda::Event#to_alda_code.
55
107
  def to_alda_code
56
- ?: + to_s
108
+ "#{Alda.v1? ? ?: : Thread.current.inside_alda_list ? '' : ?'}#{to_s}"
57
109
  end
58
110
 
59
111
  ##
60
112
  # See Alda::Event#detach_from_parent.
61
- def detach_from_parent
113
+ def detach_from_parent(...)
62
114
  end
63
115
  end
64
116
 
65
117
  ##
118
+ # Contains patches to Ruby's core classes.
66
119
  class Numeric
67
120
 
68
121
  ##
122
+ # :call-seq:
123
+ # to_alda_code() -> String
124
+ #
69
125
  # See Alda::Event#to_alda_code.
70
126
  def to_alda_code
71
127
  inspect
@@ -73,14 +129,18 @@ class Numeric
73
129
 
74
130
  ##
75
131
  # See Alda::Event#detach_from_parent.
76
- def detach_from_parent
132
+ def detach_from_parent(...)
77
133
  end
78
134
  end
79
135
 
80
136
  ##
137
+ # Contains patches to Ruby's core classes.
81
138
  class Range
82
139
 
83
140
  ##
141
+ # :call-seq:
142
+ # to_alda_code() -> String
143
+ #
84
144
  # See Alda::Event#to_alda_code.
85
145
  def to_alda_code
86
146
  "#{first}-#{last}"
@@ -88,14 +148,18 @@ class Range
88
148
 
89
149
  ##
90
150
  # See Alda::Event#detach_from_parent.
91
- def detach_from_parent
151
+ def detach_from_parent(...)
92
152
  end
93
153
  end
94
154
 
95
155
  ##
156
+ # Contains patches to Ruby's core classes.
96
157
  class TrueClass
97
158
 
98
159
  ##
160
+ # :call-seq:
161
+ # to_alda_code() -> String
162
+ #
99
163
  # See Alda::Event#to_alda_code.
100
164
  def to_alda_code
101
165
  'true'
@@ -103,14 +167,18 @@ class TrueClass
103
167
 
104
168
  ##
105
169
  # See Alda::Event#detach_from_parent.
106
- def detach_from_parent
170
+ def detach_from_parent(...)
107
171
  end
108
172
  end
109
173
 
110
174
  ##
175
+ # Contains patches to Ruby's core classes.
111
176
  class FalseClass
112
177
 
113
178
  ##
179
+ # :call-seq:
180
+ # to_alda_code() -> String
181
+ #
114
182
  # See Alda::Event#to_alda_code.
115
183
  def to_alda_code
116
184
  'false'
@@ -118,14 +186,18 @@ class FalseClass
118
186
 
119
187
  ##
120
188
  # See Alda::Event#detach_from_parent.
121
- def detach_from_parent
189
+ def detach_from_parent(...)
122
190
  end
123
191
  end
124
192
 
125
193
  ##
194
+ # Contains patches to Ruby's core classes.
126
195
  class NilClass
127
196
 
128
197
  ##
198
+ # :call-seq:
199
+ # to_alda_code() -> String
200
+ #
129
201
  # See Alda::Event#to_alda_code.
130
202
  def to_alda_code
131
203
  'nil'
@@ -133,11 +205,12 @@ class NilClass
133
205
 
134
206
  ##
135
207
  # See Alda::Event#detach_from_parent.
136
- def detach_from_parent
208
+ def detach_from_parent(...)
137
209
  end
138
210
  end
139
211
 
140
212
  ##
213
+ # Contains patches to Ruby's core classes.
141
214
  class Proc
142
215
 
143
216
  ##
@@ -155,6 +228,7 @@ class Proc
155
228
  end
156
229
 
157
230
  ##
231
+ # Contains patches to Ruby's core classes.
158
232
  class StringIO
159
233
 
160
234
  ##