alda-rb 0.2.1 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
  ##