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.
- checksums.yaml +4 -4
- data/.github/workflows/main.yml +18 -0
- data/.gitignore +2 -2
- data/CHANGELOG.md +296 -0
- data/CODE_OF_CONDUCT.md +1 -1
- data/Gemfile +3 -2
- data/Gemfile.lock +56 -0
- data/README.md +58 -7
- data/Rakefile +2 -2
- data/alda-rb.gemspec +30 -25
- data/examples/bwv846_prelude.rb +3 -3
- data/examples/clapping_music.rb +1 -1
- data/examples/dot_accessor.rb +1 -1
- data/examples/dynamics.rb +22 -0
- data/examples/entropy.rb +2 -2
- data/examples/hanon.rb +2 -2
- data/examples/marriage_d_amour.rb +114 -0
- data/examples/multi_poly.rb +2 -2
- data/examples/track-volume.rb +32 -0
- data/examples/variables-2.rb +16 -0
- data/exe/alda-irb +32 -0
- data/lib/alda-rb/commandline.rb +176 -33
- data/lib/alda-rb/error.rb +93 -9
- data/lib/alda-rb/event.rb +441 -49
- data/lib/alda-rb/event_list.rb +57 -10
- data/lib/alda-rb/patches.rb +88 -14
- data/lib/alda-rb/repl.rb +330 -61
- data/lib/alda-rb/utils.rb +47 -0
- data/lib/alda-rb/version.rb +1 -1
- data/lib/alda-rb.rb +1 -0
- metadata +74 -8
@@ -0,0 +1,114 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'alda-rb'
|
4
|
+
|
5
|
+
# Marriage D' Amour
|
6
|
+
#
|
7
|
+
# Richard Clayderman
|
8
|
+
# Paul de Senneville
|
9
|
+
#
|
10
|
+
# sheet music:
|
11
|
+
# https://musescore.com/user/153958/scores/154629
|
12
|
+
|
13
|
+
using Alda::Sequence::RefineFlatten
|
14
|
+
|
15
|
+
module Alda::EventList
|
16
|
+
def up8 &block
|
17
|
+
result = block.()
|
18
|
+
result.events = result.events.map do |event|
|
19
|
+
if event.is_event_of? Alda::Octave
|
20
|
+
event
|
21
|
+
else
|
22
|
+
if event.respond_to? :labels
|
23
|
+
labels = event.labels
|
24
|
+
event.labels = []
|
25
|
+
end
|
26
|
+
sequence = Alda::Sequence.new
|
27
|
+
sequence.events = [Alda::Chord.new(
|
28
|
+
event,
|
29
|
+
+Alda::Octave.new(''),
|
30
|
+
event,
|
31
|
+
-Alda::Octave.new('')
|
32
|
+
)]
|
33
|
+
container = Alda::EventContainer.new(sequence, result)
|
34
|
+
container.labels = labels || []
|
35
|
+
container
|
36
|
+
end
|
37
|
+
end
|
38
|
+
result
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
Alda::Score.new do
|
43
|
+
key_sig! 'b- e-'
|
44
|
+
tempo! 80
|
45
|
+
piano_ 'right'
|
46
|
+
piano_ 'left'
|
47
|
+
|
48
|
+
right_
|
49
|
+
r2_4_8_16 o5 g16
|
50
|
+
left_
|
51
|
+
o2 g8 o! d b d b d b d
|
52
|
+
|
53
|
+
motif1 = -> do
|
54
|
+
right_
|
55
|
+
g16 a a b b a a g g d d o? b b g g o! f f e e d e f e4_8
|
56
|
+
left_
|
57
|
+
o2 g o! d b d b d b d e g o! e o? g o! e o? g
|
58
|
+
|
59
|
+
right_
|
60
|
+
v1 r16 e e f f g g a a f f c c e e d d c d e _marker1 d8_4
|
61
|
+
v2 __marker1 r8 o6 d32 o! d8_16_32 v0
|
62
|
+
left_
|
63
|
+
v1 o? f o! c a c a c a o? b o! f o! d o? d8_4
|
64
|
+
v2 __marker1 r8 o4 g4? v0
|
65
|
+
end
|
66
|
+
motif1.()
|
67
|
+
|
68
|
+
motif2 = -> do
|
69
|
+
right_
|
70
|
+
o5 s{ (d8 o? g16 b o! d c)*2; d8 (o? g16 b o! e d e8)*2; e16 d e e_ f8 f16 g f g d4_8 o!}*2
|
71
|
+
left_
|
72
|
+
s{o2 g8 o! d b d b d o? g o! d b c g o! e o? g o! e o? g o? f o! c a o? b
|
73
|
+
(o! b o? up8{s{a}})%1; up8{b a}%2}*2
|
74
|
+
end
|
75
|
+
motif2.()
|
76
|
+
|
77
|
+
motif3 = -> do
|
78
|
+
right_
|
79
|
+
o5 b8_16 d16 d e e8_16 c16 a g a8_16 c16 c d d8 o? b16 b o! g f g8_16 o? b16 b o! c c8_16 o? a16 o! d c d4_8
|
80
|
+
left_
|
81
|
+
up8{s{g}}; o! d b c g o! e o? o? f o! c a o? b o! f o? a g o! d b o? a o! e o! c o? d o? up8{e_ g?}
|
82
|
+
end
|
83
|
+
motif3.()
|
84
|
+
|
85
|
+
tt2 { s{o2 g o! d b c g o! e o? o? f o! c a o? b o! b o? up8{s{a}}; g o! d b c g o! e o? o? f o! c a o? g o! d b}*2 }
|
86
|
+
motif4 = -> do
|
87
|
+
tt1 = -> { (o5 b8_16 b16 b o! c c8_16 o? b16 a g f8_16 f16 g f d4_8%1)*2 }
|
88
|
+
right_
|
89
|
+
tt1.(); g4_8; up8{tt1.()}
|
90
|
+
left_
|
91
|
+
tt2 o4 d g b
|
92
|
+
end
|
93
|
+
motif4.()
|
94
|
+
right_; up8{s{g2_4}}
|
95
|
+
|
96
|
+
motif2.()
|
97
|
+
|
98
|
+
motif4.()
|
99
|
+
right_
|
100
|
+
o5 up8{s{g2_8}}; r16 g16
|
101
|
+
|
102
|
+
motif1.()
|
103
|
+
motif2.()
|
104
|
+
motif3.()
|
105
|
+
|
106
|
+
tt1 = -> { (o5 b8_16 b16 b o! c c8_16 o? b16 a g f8_16 f16 g f d4_8%1)*2 }
|
107
|
+
|
108
|
+
right_
|
109
|
+
tt1.(); g4_8
|
110
|
+
-> { up8{tt1.()}; up8{s{g4_8}} }*2
|
111
|
+
up8{tt1.()}; up8{s{g1}}
|
112
|
+
left_
|
113
|
+
tt2*2; o4 d g o! d g r8_16 o! g4_8
|
114
|
+
end.play
|
data/examples/multi_poly.rb
CHANGED
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'alda-rb'
|
4
|
+
|
5
|
+
Alda::Score.new do
|
6
|
+
tempo! 105
|
7
|
+
|
8
|
+
piano_
|
9
|
+
pmotif do
|
10
|
+
s do
|
11
|
+
o3
|
12
|
+
vol 100; a16
|
13
|
+
vol 90; -b
|
14
|
+
vol 80; a
|
15
|
+
vol 70; -b
|
16
|
+
vol 60; o! c d
|
17
|
+
vol 50; e f
|
18
|
+
end * 2
|
19
|
+
end
|
20
|
+
|
21
|
+
70.step(10, -20) { track_vol _1; pmotif }
|
22
|
+
|
23
|
+
clarinet_
|
24
|
+
cmotif do
|
25
|
+
quant 100; o5
|
26
|
+
vol 60; d8
|
27
|
+
vol 70; c
|
28
|
+
vol 80; o? +f2_4
|
29
|
+
end
|
30
|
+
|
31
|
+
10.step(70, 20) { track_vol _1; cmotif }
|
32
|
+
end.play
|
data/exe/alda-irb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'alda-rb'
|
4
|
+
require 'optparse'
|
5
|
+
|
6
|
+
HELP = 'Print this help message and exit'.freeze
|
7
|
+
HOST = 'The hostname of the Alda REPL server; only useful in Alda 2; see `alda repl --help`'.freeze
|
8
|
+
PORT = 'The port of the Alda REPL server; only useful in Alda 2; see `alda repl --help`'.freeze
|
9
|
+
NO_COLOR = 'Whether the output should not be colored'.freeze
|
10
|
+
NO_PREVIEW = 'Whether a preview of what Alda code will not be played everytime you input ruby codes'.freeze
|
11
|
+
NO_RELINE = 'Whether to use Reline to read input'.freeze
|
12
|
+
|
13
|
+
host = 'localhost'
|
14
|
+
port = -1
|
15
|
+
color = true
|
16
|
+
preview = true
|
17
|
+
reline = true
|
18
|
+
|
19
|
+
OptionParser.new do |opts|
|
20
|
+
opts.banner = 'Usage: alda-irb [options]'
|
21
|
+
opts.on('-h', '--help', HELP) { exit unless puts opts }
|
22
|
+
opts.on('-H', '--host string', HOST) { host = _1 }
|
23
|
+
opts.on('-p', '--port int', PORT) { port = _1 }
|
24
|
+
opts.on('-c', '--no-color', NO_COLOR) { color = false }
|
25
|
+
opts.on('-P', '--no-preview', NO_PREVIEW) { preview = false }
|
26
|
+
opts.on('-r', '--no-reline', NO_RELINE) { reline = false }
|
27
|
+
end.parse!
|
28
|
+
|
29
|
+
Alda.deduce_generation
|
30
|
+
opts = { color: color, preview: preview, reline: reline }
|
31
|
+
opts.merge! host: host, port: port unless Alda.v1?
|
32
|
+
Alda::REPL.new(**opts).run
|
data/lib/alda-rb/commandline.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
##
|
2
|
+
# Adding functions that is accessible everywhere.
|
1
3
|
module Kernel
|
2
4
|
##
|
3
5
|
# :call-seq:
|
@@ -19,7 +21,24 @@ end
|
|
19
21
|
module Alda
|
20
22
|
|
21
23
|
##
|
22
|
-
# The
|
24
|
+
# The Array of possible values of ::generation.
|
25
|
+
# It is just the array <tt>[:v1, :v2]</tt>
|
26
|
+
#
|
27
|
+
# You can use +:v1?+ and +:v2?+ to get whether the current generation is +:v1+ or +:v2+.
|
28
|
+
# For example, <tt>Alda.v1?</tt> is the same as <tt>Alda.generation == :v1</tt>.
|
29
|
+
# You can also use +:v1!+ and +:v2!+ to set the generation to +:v1+ or +:v2+.
|
30
|
+
# For example, <tt>Alda.v1!</tt> is the same as <tt>Alda.generation = :v1</tt>.
|
31
|
+
GENERATIONS = %i[v1 v2].freeze
|
32
|
+
|
33
|
+
GENERATIONS.each do |gen|
|
34
|
+
module_function define_method("#{gen}?") { @generation == gen }
|
35
|
+
module_function define_method("#{gen}!") { @generation = gen }
|
36
|
+
end
|
37
|
+
|
38
|
+
##
|
39
|
+
# The available subcommands of alda executable.
|
40
|
+
# This is a Hash, with keys being possible values of ::generation,
|
41
|
+
# and values being an Array of symbols of the available commands of that generation.
|
23
42
|
#
|
24
43
|
# Alda is able to invoke +alda+ at the command line.
|
25
44
|
# The subcommand is the name of the method invoked upon Alda.
|
@@ -36,37 +55,45 @@ module Alda
|
|
36
55
|
# Alda.parse code: 'bassoon: o3 c'
|
37
56
|
# # => "{\"chord-mode\":false,\"current-instruments\":...}\n"
|
38
57
|
#
|
39
|
-
# The available commands are:
|
40
|
-
#
|
41
|
-
#
|
42
|
-
# +
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
58
|
+
# The available commands are:
|
59
|
+
#
|
60
|
+
# * If ::generation is +:v1+:
|
61
|
+
# +help+, +update+, +repl+, +up+, +start_server+, +init+, +down+, +stop_server+,
|
62
|
+
# +downup+, +restart_server+, +list+, +status+, +version+, +play+, +stop+, +parse+,
|
63
|
+
# +instruments+, and +export+.
|
64
|
+
# * If ::generation is +:v2+:
|
65
|
+
# +doctor+, +export+, +help+, +import+, +instruments+, +parse+, +play+,
|
66
|
+
# +ps+, +repl+, +shutdown+, +stop+, +telemetry+, +update+, and +version+.
|
67
|
+
#
|
68
|
+
# Trying to run a command that is not support by the current generation set by ::generation
|
69
|
+
# will raise an Alda::GenerationError.
|
70
|
+
COMMANDS_FOR_VERSIONS = {
|
71
|
+
v1: %i[
|
72
|
+
help update repl up start_server init down stop_server
|
73
|
+
downup restart_server list status version play stop parse
|
74
|
+
instruments export
|
75
|
+
].freeze,
|
76
|
+
v2: %i[
|
77
|
+
doctor export help import instruments parse play ps repl shutdown stop
|
78
|
+
telemetry update version
|
79
|
+
].freeze
|
80
|
+
}.freeze
|
48
81
|
|
49
|
-
|
82
|
+
##
|
83
|
+
# The Hash of available commands.
|
84
|
+
# The symbols of commands are keys
|
85
|
+
# and each value is an Array of generations where the command is available.
|
86
|
+
COMMANDS = COMMANDS_FOR_VERSIONS.each_with_object({}) do |(gen, commands), r|
|
87
|
+
commands.each { (r[_1] ||= []).push gen }
|
88
|
+
end.freeze
|
89
|
+
|
90
|
+
COMMANDS.each do |command, generations|
|
50
91
|
define_method command do |*args, **opts|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
# executable
|
57
|
-
args.unshift Alda.executable
|
58
|
-
args.map! &:to_s
|
59
|
-
# options
|
60
|
-
Alda.options.each &block
|
61
|
-
# subcommand
|
62
|
-
args.push command.to_s
|
63
|
-
# subcommand options
|
64
|
-
opts.each &block
|
65
|
-
# subprocess
|
66
|
-
IO.popen(args, &:read).tap do
|
67
|
-
raise CommandLineError.new $?, _1 if $?.exitstatus.nonzero?
|
68
|
-
end
|
69
|
-
end
|
92
|
+
Alda::GenerationError.assert_generation generations
|
93
|
+
result = Alda.pipe command, *args, **opts, &:read
|
94
|
+
raise CommandLineError.new $?, result if $?.exitstatus.nonzero?
|
95
|
+
result
|
96
|
+
end.tap { module_function _1 }
|
70
97
|
end
|
71
98
|
|
72
99
|
class << self
|
@@ -84,6 +111,19 @@ module Alda
|
|
84
111
|
# Clear it using ::clear_options.
|
85
112
|
attr_reader :options
|
86
113
|
|
114
|
+
##
|
115
|
+
# The major version of the +alda+ command used.
|
116
|
+
# Possible values: +:v1+ or +:v2+ (i.e. one of the values in Alda::GENERATIONS).
|
117
|
+
# If you try to specify it to values other than those, an ArgumentError will be raised.
|
118
|
+
# This affects several things due to some incompatible changes from \Alda 1 to \Alda 2.
|
119
|
+
# You may use ::deduce_generation to automatically set it,
|
120
|
+
# or use #v1! or #v2! to set it in a shorter way.
|
121
|
+
attr_accessor :generation
|
122
|
+
def generation= gen # :nodoc:
|
123
|
+
raise ArgumentError, "bad generation: #{gen}" unless GENERATIONS.include? gen
|
124
|
+
@generation = gen
|
125
|
+
end
|
126
|
+
|
87
127
|
##
|
88
128
|
# :call-seq:
|
89
129
|
# Alda[**opts] -> self
|
@@ -91,6 +131,7 @@ module Alda
|
|
91
131
|
# Sets the options of alda command.
|
92
132
|
# Not the subcommand options.
|
93
133
|
#
|
134
|
+
# # This example only works for Alda 1.
|
94
135
|
# Alda[port: 1108].up # => "[1108] ..."
|
95
136
|
# Alda.status # => "[1108] ..."
|
96
137
|
#
|
@@ -115,14 +156,104 @@ module Alda
|
|
115
156
|
|
116
157
|
@executable = 'alda'
|
117
158
|
@options = {}
|
159
|
+
@env = {
|
160
|
+
'ALDA_DISABLE_SPAWNING' => 'yes',
|
161
|
+
'ALDA_DISABLE_TELEMETRY' => 'yes'
|
162
|
+
}
|
163
|
+
v2!
|
164
|
+
|
165
|
+
##
|
166
|
+
# :call-seq:
|
167
|
+
# env() -> Hash
|
168
|
+
# env(hash) -> Hash
|
169
|
+
# env(hash) { ... } -> Object
|
170
|
+
#
|
171
|
+
# When called with no arguments,
|
172
|
+
# returns the commandline environment variables (a Hash)
|
173
|
+
# used when running +alda+ on command line.
|
174
|
+
# It is <tt>{"ALDA_DISABLE_SPAWNING"=>"yes","ALDA_DISABLE_TELEMETRY"=>"yes"}</tt> by default
|
175
|
+
# (for speeding up the command line responses:
|
176
|
+
# {alda-lang/alda#368}[https://github.com/alda-lang/alda/issues/368]).
|
177
|
+
#
|
178
|
+
# When called with an argument +hash+,
|
179
|
+
# merge the old environment variables with +hash+ and set
|
180
|
+
# the merged Hash as the new environment variables.
|
181
|
+
# Returns the new environment variables (a Hash).
|
182
|
+
#
|
183
|
+
# When called with an argument +hash+ and a block,
|
184
|
+
# execute the block with the environment being set to the merge of the old environment
|
185
|
+
# and +hash+, and then restore the old environment.
|
186
|
+
# Returns the returned value of the block.
|
187
|
+
def env hash = nil, &block
|
188
|
+
if hash
|
189
|
+
@env = (old_env = @env).merge hash.map { |k, v| [k.to_s, v.to_s] }.to_h
|
190
|
+
block ? block.().tap { @env = old_env } : @env
|
191
|
+
else
|
192
|
+
@env
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
##
|
197
|
+
# :call-seq:
|
198
|
+
# pipe(command, *args, **opts) -> IO
|
199
|
+
# pipe(command, *args, **opts) { |io| ... } -> Object
|
200
|
+
#
|
201
|
+
# Runs +alda+ in command line as a child process and returns the pipe IO
|
202
|
+
# or pass the IO to the block.
|
203
|
+
# See COMMANDS_FOR_VERSIONS for an explanation of +args+ and +opts+.
|
204
|
+
def pipe command, *args, **opts, &block
|
205
|
+
add_option = ->((key, val)) do
|
206
|
+
next unless val
|
207
|
+
args.push "--#{Alda::Utils.snake_to_slug key}"
|
208
|
+
args.push val.to_s unless val == true
|
209
|
+
end
|
210
|
+
# executable
|
211
|
+
args.unshift Alda.executable
|
212
|
+
args.map! &:to_s
|
213
|
+
# options
|
214
|
+
Alda.options.each &add_option
|
215
|
+
# subcommand
|
216
|
+
args.push command.to_s
|
217
|
+
# subcommand options
|
218
|
+
opts.each &add_option
|
219
|
+
# subprocess
|
220
|
+
spawn_options = Alda::Utils.win_platform? ? { new_pgroup: true } : { pgroup: true }
|
221
|
+
IO.popen Alda.env, args, **spawn_options, &block
|
222
|
+
end
|
223
|
+
|
224
|
+
##
|
225
|
+
# :call-seq:
|
226
|
+
# processes() -> Array
|
227
|
+
#
|
228
|
+
# Returns a Array of details about running \Alda processes.
|
229
|
+
# Only available for \Alda 2.
|
230
|
+
# Each element in the Array is a Hash,
|
231
|
+
# and each Hash has the following keys:
|
232
|
+
# - +:id+: the player-id of the process, a three-letter String.
|
233
|
+
# - +:port+: the port number of the process, an Integer.
|
234
|
+
# - +:state+: the state of the process, a Symbol (may be +nil+, +:ready+, +:active+, or +:starting+).
|
235
|
+
# - +:expiry+: a human-readable description of expiry time of the process, a String (may be +nil+).
|
236
|
+
# - +:type+: the type of the process, a Symbol (may be +:player+ or +:repl_server+).
|
237
|
+
def processes
|
238
|
+
raise GenerationError.new [:v2] if v1?
|
239
|
+
Alda.ps.lines(chomp: true)[1..].map do |line|
|
240
|
+
id, port, state, expiry, type = line.split ?\t
|
241
|
+
port = port.to_i
|
242
|
+
state = state == ?- ? nil : state.to_sym
|
243
|
+
expiry = nil if expiry == ?-
|
244
|
+
type = Alda::Utils.slug_to_snake type
|
245
|
+
{ id: id, port: port, state: state, expiry: expiry, type: type }
|
246
|
+
end
|
247
|
+
end
|
118
248
|
|
119
249
|
##
|
120
250
|
# :call-seq:
|
121
251
|
# up?() -> true or false
|
122
252
|
#
|
123
253
|
# Whether the alda server is up.
|
254
|
+
# Checks whether there are any play processes in ::processes in \Alda 2.
|
124
255
|
def up?
|
125
|
-
status.include?
|
256
|
+
Alda.v1? ? Alda.status.include?('up') : Alda.processes.any? { _1[:type] == :player }
|
126
257
|
end
|
127
258
|
|
128
259
|
##
|
@@ -130,10 +261,22 @@ module Alda
|
|
130
261
|
# down? -> true or false
|
131
262
|
#
|
132
263
|
# Whether the alda server is down.
|
264
|
+
# Checks whether there are no play processes in ::processes in \Alda 2.
|
133
265
|
def down?
|
134
|
-
status.include?
|
266
|
+
Alda.v1? ? Alda.status.include?('down') : Alda.processes.none? { _1[:type] == :player }
|
267
|
+
end
|
268
|
+
|
269
|
+
##
|
270
|
+
# :call-seq:
|
271
|
+
# deduce_generation -> one of Alda::GENERATIONS
|
272
|
+
#
|
273
|
+
# Deduce the generation of \Alda being used by running <tt>alda version</tt> in command line,
|
274
|
+
# and then set ::generation accordingly.
|
275
|
+
def deduce_generation
|
276
|
+
/(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)/ =~ Alda.version
|
277
|
+
@generation = major == '1' ? :v1 : :v2
|
135
278
|
end
|
136
279
|
|
137
|
-
module_function :up?, :down?,
|
280
|
+
module_function :env, :pipe, :processes, :up?, :down?, :deduce_generation
|
138
281
|
|
139
282
|
end
|
data/lib/alda-rb/error.rb
CHANGED
@@ -9,33 +9,116 @@ class Alda::CommandLineError < StandardError
|
|
9
9
|
|
10
10
|
##
|
11
11
|
# The port on which the problematic alda server runs.
|
12
|
+
# This is only available for \Alda 1.
|
12
13
|
#
|
13
14
|
# begin
|
14
15
|
# Alda[port: 1108].play code: 'y'
|
15
16
|
# rescue CommandLineError => e
|
16
17
|
# e.port # => 1108
|
17
18
|
# end
|
18
|
-
|
19
|
+
def port
|
20
|
+
Alda::GenerationError.assert_generation [:v1]
|
21
|
+
@port
|
22
|
+
end
|
19
23
|
|
20
24
|
##
|
21
25
|
# :call-seq:
|
22
26
|
# new(status, msg=nil) -> Alda::CommandLineError
|
23
27
|
#
|
24
28
|
# Create a Alda::CommandLineError object.
|
25
|
-
# +status+ is the status of the process running +alda+ command.
|
26
|
-
# +msg+ is output of +alda+ command. port
|
29
|
+
# +status+ is the status of the process running +alda+ command (can be nil).
|
30
|
+
# +msg+ is the output of +alda+ command. #port info is extracted from +msg+ in \Alda 1.
|
27
31
|
def initialize status, msg = nil
|
28
|
-
if
|
29
|
-
super
|
30
|
-
@port =
|
32
|
+
if Alda.v1? && msg && /^\[(?<port>\d+)\]\sERROR\s(?<message>.*)$/ =~ msg
|
33
|
+
super message
|
34
|
+
@port = port.to_i
|
31
35
|
else
|
32
36
|
super msg
|
33
|
-
@port = nil
|
34
37
|
end
|
35
38
|
@status = status
|
36
39
|
end
|
37
40
|
end
|
38
41
|
|
42
|
+
##
|
43
|
+
# The error is raised when the \Alda nREPL server returns problems.
|
44
|
+
# This is only available for \Alda 2.
|
45
|
+
# See Alda::REPL#message.
|
46
|
+
class Alda::NREPLServerError < StandardError
|
47
|
+
|
48
|
+
##
|
49
|
+
# The hostname of the nREPL server.
|
50
|
+
attr_reader :host
|
51
|
+
|
52
|
+
##
|
53
|
+
# The port of the nREPL server.
|
54
|
+
attr_reader :port
|
55
|
+
|
56
|
+
##
|
57
|
+
# The problems returned by the nREPL server.
|
58
|
+
# This is an Array of String.
|
59
|
+
attr_reader :problems
|
60
|
+
|
61
|
+
##
|
62
|
+
# The status returned by the nREPL server.
|
63
|
+
# It is an Array of Symbol.
|
64
|
+
# Symbols must appear are +:done+, +:error+, and there may be +:unknown_op+.
|
65
|
+
attr_reader :status
|
66
|
+
|
67
|
+
##
|
68
|
+
# :call-seq:
|
69
|
+
# new(host, port, problems, status) -> Alda::NREPLServerError
|
70
|
+
#
|
71
|
+
# Creates a Alda::NREPLServerError object.
|
72
|
+
# Raises Alda::GenerationError if the current generation is not \Alda 2.
|
73
|
+
def initialize host, port, problems, status
|
74
|
+
Alda::GenerationError.assert_generation [:v2]
|
75
|
+
@status = status.map { Alda::Utils.slug_to_snake _1 }
|
76
|
+
if @status.include? :unknown_op
|
77
|
+
super 'unknown operation'
|
78
|
+
else
|
79
|
+
super problems.join ?\n
|
80
|
+
end
|
81
|
+
@host = host
|
82
|
+
@port = port
|
83
|
+
@problems = problems
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
##
|
88
|
+
# This error is raised when one tries to run commands that are not available for the generation
|
89
|
+
# of \Alda specified by Alda::generation.
|
90
|
+
#
|
91
|
+
# Alda.v1!
|
92
|
+
# Alda.import # (GenerationError)
|
93
|
+
class Alda::GenerationError < StandardError
|
94
|
+
|
95
|
+
##
|
96
|
+
# The actual generation that was set by Alda::generation when the error occurs.
|
97
|
+
attr_reader :generation
|
98
|
+
|
99
|
+
##
|
100
|
+
# The generations that could have been set to avoid the error.
|
101
|
+
# An Array.
|
102
|
+
attr_reader :fine_generations
|
103
|
+
|
104
|
+
##
|
105
|
+
# :call-seq:
|
106
|
+
# new(fine_generations) -> Alda::GenerationError
|
107
|
+
#
|
108
|
+
# Creates a Alda::GenerationError object.
|
109
|
+
def initialize fine_generations
|
110
|
+
super "bad Alda generation for this action; good ones are #{fine_generations}"
|
111
|
+
@generation = Alda.generation
|
112
|
+
@fine_generations = fine_generations
|
113
|
+
end
|
114
|
+
|
115
|
+
##
|
116
|
+
# Raises an Alda::GenerationError if the current generation is not in +fine_generations+.
|
117
|
+
def self.assert_generation fine_generations
|
118
|
+
raise new fine_generations unless fine_generations.include? Alda.generation
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
39
122
|
##
|
40
123
|
# This error is raised when one tries to
|
41
124
|
# append events in an Alda::EventList in a wrong order.
|
@@ -49,8 +132,7 @@ class Alda::OrderError < StandardError
|
|
49
132
|
|
50
133
|
##
|
51
134
|
# The expected element gotten if it is of the correct order.
|
52
|
-
#
|
53
|
-
# See #got
|
135
|
+
# See #got.
|
54
136
|
#
|
55
137
|
# Alda::Score.new do
|
56
138
|
# motif = f4 f e e d d c2
|
@@ -72,6 +154,8 @@ class Alda::OrderError < StandardError
|
|
72
154
|
##
|
73
155
|
# :call-seq:
|
74
156
|
# new(expected, got) -> Alda::OrderError
|
157
|
+
#
|
158
|
+
# Creates a Alda::OrderError object.
|
75
159
|
def initialize expected, got
|
76
160
|
super 'events are out of order'
|
77
161
|
@expected = expected
|