alda-rb 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6e35ecf8cca36fa942f004ba62c203226064ec3de09f21974ba57eb04cddd79a
4
- data.tar.gz: 96f6a6540591c4a890034b234a737b68a678c199e2f88a8f73b4eadd5f824477
3
+ metadata.gz: 41c00c8e704980367ff2ca3cef0028e08cd5483106a0df2d89bc70644fea33a1
4
+ data.tar.gz: da32c375756258266cd4eee3818d8697f2ced17605f2bfe19db69e9eebffa5ca
5
5
  SHA512:
6
- metadata.gz: b8eb886e53075b0d4d154c0f2f29415eb366ce0ad1ca38aa6a0757eee136b028d952dab3e42f557d4037fcc41704b64f9467de4c89205f0cbd8d040b1d3ce70e
7
- data.tar.gz: cec492d17877348e1023b5d488bd3cb2b6e874d13e13eaa1141eee5260853ff094e0daa9b412fbb7210f6a91b5fb2808bfe0831e932a84a510b1809a8df97b91
6
+ metadata.gz: dc03761923a96fd3c596cd034ef86f51f26b0b8055e33287e8fff772f1f1c062de55f0a009f07930c7bea8b2f9c491246b70ae44dc37aeec388cbc5f0669971f
7
+ data.tar.gz: f578e781ba699b774c9a22f30b65f8dd1c734d09fa4cd32d49416874cbab96203efd9b357ef9740854864ff445b408b4a55c85aaabdf236337b889f488819850
data/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## v0.3.1 (2023-06-03)
4
+
5
+ New features and new API:
6
+
7
+ - Added Alda::NREPLServerError#status.
8
+ - Added Alda::env.
9
+ - Alda::down? and Alda::up? is now useful in \Alda 2.
10
+ - Added Alda::REPL#reline.
11
+
12
+ BREAKING changes of API:
13
+
14
+ - Now `status` should be specified as a parameter of Alda::NREPLServerError::new.
15
+
16
+ Fixed bugs:
17
+
18
+ - Fixed: `alda-irb` does not run correctly in Ruby 3.
19
+ - Fixed: cannot handle unknown-op error of nREPL server.
20
+ - Fixed: an excess message printed when exiting \REPL on Windows.
21
+
22
+ Other changes:
23
+
24
+ - Fixed dependencies.
25
+ - Fixed some changelog of 0.3.0.
26
+ - Added a gem badge in README.
27
+ - Updated bundler version.
28
+
3
29
  ## v0.3.0 (2023-05-29)
4
30
 
5
31
  ### Changes for \Alda 2
@@ -8,12 +34,12 @@ Added API for support \Alda 2 while still being able to support \Alda 1:
8
34
 
9
35
  - Added Alda::COMMANDS_FOR_VERSIONS and Alda::GENERATIONS.
10
36
  - Added Alda::generation, which can be `:v1` or `:v2`.
11
- Specifically, one of the values in the array Alda::GENERATIONS.
37
+ Specifically, one of the values in the array Alda::GENERATIONS.
12
38
  - Added Alda::v1?, Alda::v2?, Alda::v1!, Alda::v2! (See Alda::GENERATIONS).
13
39
  - Added Alda::deduce_generation.
14
40
  - Added Alda::GenerationError.
15
41
  - In Alda::Chord#to_alda_code, considering an undocumented breaking change about chords,
16
- the behavior is slightly different for \Alda 1 and \Alda 2.
42
+ the behavior is slightly different for \Alda 1 and \Alda 2.
17
43
  - Added Thread#inside_alda_list.
18
44
  - Added Alda::REPL#message and Alda::REPL#raw_message.
19
45
 
@@ -25,7 +51,7 @@ APIs that are modified to support \Alda 2:
25
51
  - Because \Alda 2 does not have the notion of down and up, if we are in v2,
26
52
  Alda::down? will always return false and Alda::up? will always return true.
27
53
  - Array#to_alda_code and Hash#to_alda_code behaves differently for \Alda 1 and \Alda 2 regarding
28
- [a breaking change](https://github.com/alda-lang/alda/blob/master/doc/alda-2-migration-guide.md#attribute-syntax-has-changed-in-some-cases).
54
+ [a breaking change](https://github.com/alda-lang/alda/blob/master/doc/alda-2-migration-guide.md#attribute-syntax-has-changed-in-some-cases).
29
55
 
30
56
  Documents that modified for notice about \Alda 2:
31
57
 
@@ -47,11 +73,11 @@ Examples that are modified to work in \Alda 2:
47
73
  New features:
48
74
 
49
75
  - Added warnings about structures that probably trigger errors in \Alda.
50
- See Alda::EventContainer#check_in_chord, Alda::EventList#method_missing.
76
+ See Alda::EventContainer#check_in_chord, Alda::EventList#method_missing.
51
77
  - Now you can specify a parameter in Alda::Event#detach_from_parent to exclude some
52
- classes of parents that will be detached from.
78
+ classes of parents that will be detached from.
53
79
  - (Potentially BREAKING) Alda::Event#detach_from_parent now tries to detach the topmost container
54
- instead of the event itself from the parent.
80
+ instead of the event itself from the parent.
55
81
  - Added a commandline program called `alda-irb`. See Alda::REPL.
56
82
  - Traceback of exception will also be printed now if an Interrupt is caught in \REPL.
57
83
  - <kbd>Ctrl</kbd>+<kbd>C</kbd> can now be used to discard the current input in \REPL.
@@ -63,7 +89,7 @@ New APIs:
63
89
 
64
90
  - Added Alda::Raw.
65
91
  - Added Alda::Utils::warn, Alda::Utils::win_platform?,
66
- Alda::Utils::snake_to_slug, Alda::Utils::slug_to_snake.
92
+ Alda::Utils::snake_to_slug, Alda::Utils::slug_to_snake.
67
93
  - Added Alda::Event#is_event_of?. It is overridden in Alda::EventContainer#is_event_of?.
68
94
  - Added Alda::Event#== and Alda::EventList#==. It is overridden in many subclasses.
69
95
  - Added Alda::EventContainer#check_in_chord.
@@ -72,7 +98,7 @@ Alda::Utils::snake_to_slug, Alda::Utils::slug_to_snake.
72
98
  - Added Alda::REPL#color, Alda::REPL#preview.
73
99
  - Added Alda::REPL#setup_repl, Alda::REPL#readline.
74
100
  - Added Alda::REPL::TempScore#new_score, Alda::REPL::TempScore#score_text,
75
- Alda::REPL::TempScore#score_data, Alda::REPL::TempScore#score_events.
101
+ Alda::REPL::TempScore#score_data, Alda::REPL::TempScore#score_events.
76
102
  - Added Alda::pipe.
77
103
  - Added Alda::processes.
78
104
  - Added Alda::NREPLServerError.
@@ -81,10 +107,9 @@ Alda::REPL::TempScore#score_data, Alda::REPL::TempScore#score_events.
81
107
  Slightly improved docs:
82
108
 
83
109
  - Alda::EventContainer#event.
84
- - The overriding +to_alda_code+'s and +on_contained+'s.
110
+ - The overriding `to_alda_code`'s and `on_contained`'s.
85
111
  - Alda::Sequence, Alda::Sequence::RefineFlatten#flatten.
86
112
  - The patches to Ruby's core classes.
87
- - Alda::repl.
88
113
  - Kernel.
89
114
  - Alda::EventList::new.
90
115
  - Alda::OrderError::new.
@@ -109,7 +134,7 @@ Removed APIs:
109
134
 
110
135
  - Removed Alda::SetVariable#original_events.
111
136
  - Removed Alda::repl. Now calling `Alda.repl` will trigger commandline `alda repl`.
112
- For the old REPL function, use `Alda::REPL.new.run` instead.
137
+ For the old REPL function, use `Alda::REPL.new.run` instead.
113
138
  - Removed Alda::REPL::TempScore#history.
114
139
 
115
140
  Modified APIs or features:
@@ -120,11 +145,11 @@ Modified APIs or features:
120
145
  ### Fixed bugs
121
146
 
122
147
  - Fixed: sometimes Alda::Event#parent returns wrong result
123
- because it is not updated in some cases.
148
+ because it is not updated in some cases.
124
149
  - Fixed (potentially BREAKING): Hash#to_alda_code returns `[[k1 v1] [k2 v2]]`.
125
- Now, it returns `{k1 v1 k2 v2}`.
150
+ Now, it returns `{k1 v1 k2 v2}`.
126
151
  - Use reline instead of readline in Alda::REPL
127
- because Ruby 3.3 is dropping the shipment of readline-ext.
152
+ because Ruby 3.3 is dropping the shipment of readline-ext.
128
153
 
129
154
  ### Others
130
155
 
@@ -135,9 +160,9 @@ because Ruby 3.3 is dropping the shipment of readline-ext.
135
160
  ## v0.2.1 (2020-08-13)
136
161
 
137
162
  - Fixed the bug in `examples/bwv846_prelude.rb`.
138
- The file isn't changed when the version change
139
- from [v0.1.4](#v014-2020-04-23) to [v0.2.0](#v020-2020-05-08)
140
- but the new features in 0.2.0 made some codes in that file stop working.
163
+ The file isn't changed when the version change
164
+ from [v0.1.4](#v014-2020-04-23) to [v0.2.0](#v020-2020-05-08)
165
+ but the new features in 0.2.0 made some codes in that file stop working.
141
166
 
142
167
  ## v0.2.0 (2020-05-08)
143
168
 
@@ -178,9 +203,9 @@ c c c c c
178
203
  > exit
179
204
  ```
180
205
  - More than 2 events written together will become an Alda::Sequence object
181
- (contained by an Alda::EventContainer).
182
- Events that can use such sugar includes:
183
- part (supports dot accessor), note, rest, octave, voice, marker, at-marker.
206
+ (contained by an Alda::EventContainer).
207
+ Events that can use such sugar includes:
208
+ part (supports dot accessor), note, rest, octave, voice, marker, at-marker.
184
209
  ```ruby
185
210
  Alda::Score.new { p((c d e).event.class) } # => Alda::Sequence
186
211
  ```
data/Gemfile CHANGED
@@ -2,11 +2,11 @@ source "https://rubygems.org"
2
2
 
3
3
  gemspec
4
4
 
5
- gem "rake", "~> 12.0"
6
- gem "minitest", "~> 5.0"
7
5
  gem "colorize"
8
6
  gem "bencode"
9
7
  group :develop do
8
+ gem "rake", "~> 12.0"
9
+ gem "minitest", "~> 5.0"
10
10
  gem 'rubocop'
11
11
  gem 'rdoc'
12
12
  end
data/Gemfile.lock CHANGED
@@ -1,7 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- alda-rb (0.3.0)
4
+ alda-rb (0.3.1)
5
+ bencode
6
+ colorize
5
7
 
6
8
  GEM
7
9
  remote: https://rubygems.org/
@@ -51,4 +53,4 @@ DEPENDENCIES
51
53
  rubocop
52
54
 
53
55
  BUNDLED WITH
54
- 2.4.1
56
+ 2.4.13
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # alda-rb
2
2
 
3
+ [![Gem Version](https://badge.fury.io/rb/alda-rb.svg)](https://badge.fury.io/rb/alda-rb)
4
+
3
5
  A Ruby library for live-coding music with [Alda](https://alda.io/).
4
6
  Also provides an alda DSL in Ruby.
5
7
 
data/alda-rb.gemspec CHANGED
@@ -3,29 +3,34 @@
3
3
  require_relative 'lib/alda-rb/version'
4
4
 
5
5
  Gem::Specification.new do |spec|
6
- spec.name = "alda-rb"
7
- spec.version = Alda::VERSION
8
- spec.authors = ["Ulysses Zhan"]
9
- spec.email = ["UlyssesZhan@gmail.com"]
10
-
11
- spec.summary = %q{A Ruby library for live-coding music with Alda.}
12
- # spec.description = %q{TODO: Write a longer description or delete this line.}
13
- spec.homepage = "https://ulysseszh.github.io/doc/alda-rb"
14
- spec.license = "MIT"
15
- spec.required_ruby_version = Gem::Requirement.new(">= 2.7.0")
16
-
17
- # spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
18
-
19
- spec.metadata["homepage_uri"] = spec.homepage
20
- spec.metadata["source_code_uri"] = "https://github.com/UlyssesZh/alda-rb"
21
- spec.metadata["changelog_uri"] = "https://ulysseszh.github.io/doc/alda-rb/CHANGELOG_md.html"
22
-
23
- # Specify which files should be added to the gem when it is released.
24
- # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
25
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
26
- `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
27
- end
28
- spec.bindir = "exe"
29
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
30
- spec.require_paths = ["lib"]
6
+ spec.name = "alda-rb"
7
+ spec.version = Alda::VERSION
8
+ spec.authors = ["Ulysses Zhan"]
9
+ spec.email = ["UlyssesZhan@gmail.com"]
10
+
11
+ spec.summary = %q{A Ruby library for live-coding music with Alda.}
12
+ # spec.description = %q{TODO: Write a longer description or delete this line.}
13
+ spec.homepage = "https://ulysseszh.github.io/doc/alda-rb"
14
+ spec.license = "MIT"
15
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.7.0")
16
+
17
+ # spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
18
+
19
+ spec.metadata["homepage_uri"] = spec.homepage
20
+ spec.metadata["source_code_uri"] = "https://github.com/UlyssesZh/alda-rb"
21
+ spec.metadata["changelog_uri"] = "https://ulysseszh.github.io/doc/alda-rb/CHANGELOG_md.html"
22
+
23
+ # Specify which files should be added to the gem when it is released.
24
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
25
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
26
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
27
+ end
28
+ spec.bindir = "exe"
29
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
30
+ spec.require_paths = ["lib"]
31
+
32
+ spec.add_runtime_dependency 'bencode'
33
+ spec.add_runtime_dependency 'colorize'
34
+ spec.add_development_dependency 'minitest', '~> 5.0'
35
+ spec.add_development_dependency 'rake', '~> 12.0'
31
36
  end
data/exe/alda-irb CHANGED
@@ -8,11 +8,13 @@ HOST = 'The hostname of the Alda REPL server; only useful in Alda 2; see `alda r
8
8
  PORT = 'The port of the Alda REPL server; only useful in Alda 2; see `alda repl --help`'.freeze
9
9
  NO_COLOR = 'Whether the output should not be colored'.freeze
10
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
11
12
 
12
13
  host = 'localhost'
13
14
  port = -1
14
15
  color = true
15
16
  preview = true
17
+ reline = true
16
18
 
17
19
  OptionParser.new do |opts|
18
20
  opts.banner = 'Usage: alda-irb [options]'
@@ -21,9 +23,10 @@ OptionParser.new do |opts|
21
23
  opts.on('-p', '--port int', PORT) { port = _1 }
22
24
  opts.on('-c', '--no-color', NO_COLOR) { color = false }
23
25
  opts.on('-P', '--no-preview', NO_PREVIEW) { preview = false }
26
+ opts.on('-r', '--no-reline', NO_RELINE) { reline = false }
24
27
  end.parse!
25
28
 
26
29
  Alda.deduce_generation
27
- opts = {color: color, preview: preview}
30
+ opts = { color: color, preview: preview, reline: reline }
28
31
  opts.merge! host: host, port: port unless Alda.v1?
29
32
  Alda::REPL.new(**opts).run
@@ -90,7 +90,9 @@ module Alda
90
90
  COMMANDS.each do |command, generations|
91
91
  define_method command do |*args, **opts|
92
92
  Alda::GenerationError.assert_generation generations
93
- Alda.pipe(command, *args, **opts, &:read).tap { raise CommandLineError.new $?, _1 if $?.exitstatus.nonzero? }
93
+ result = Alda.pipe command, *args, **opts, &:read
94
+ raise CommandLineError.new $?, result if $?.exitstatus.nonzero?
95
+ result
94
96
  end.tap { module_function _1 }
95
97
  end
96
98
 
@@ -154,8 +156,43 @@ module Alda
154
156
 
155
157
  @executable = 'alda'
156
158
  @options = {}
159
+ @env = {
160
+ 'ALDA_DISABLE_SPAWNING' => 'yes',
161
+ 'ALDA_DISABLE_TELEMETRY' => 'yes'
162
+ }
157
163
  v2!
158
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
+
159
196
  ##
160
197
  # :call-seq:
161
198
  # pipe(command, *args, **opts) -> IO
@@ -165,7 +202,7 @@ module Alda
165
202
  # or pass the IO to the block.
166
203
  # See COMMANDS_FOR_VERSIONS for an explanation of +args+ and +opts+.
167
204
  def pipe command, *args, **opts, &block
168
- add_option = ->key, val do
205
+ add_option = ->((key, val)) do
169
206
  next unless val
170
207
  args.push "--#{Alda::Utils.snake_to_slug key}"
171
208
  args.push val.to_s unless val == true
@@ -180,8 +217,8 @@ module Alda
180
217
  # subcommand options
181
218
  opts.each &add_option
182
219
  # subprocess
183
- spawn_options = Alda::Utils.win_platform? ? {new_pgroup: true} : {pgroup: true}
184
- IO.popen args, **spawn_options, &block
220
+ spawn_options = Alda::Utils.win_platform? ? { new_pgroup: true } : { pgroup: true }
221
+ IO.popen Alda.env, args, **spawn_options, &block
185
222
  end
186
223
 
187
224
  ##
@@ -194,7 +231,7 @@ module Alda
194
231
  # and each Hash has the following keys:
195
232
  # - +:id+: the player-id of the process, a three-letter String.
196
233
  # - +:port+: the port number of the process, an Integer.
197
- # - +:state+: the state of the process, a Symbol (may be +nil+, +:ready+, +:active+ etc.).
234
+ # - +:state+: the state of the process, a Symbol (may be +nil+, +:ready+, +:active+, or +:starting+).
198
235
  # - +:expiry+: a human-readable description of expiry time of the process, a String (may be +nil+).
199
236
  # - +:type+: the type of the process, a Symbol (may be +:player+ or +:repl_server+).
200
237
  def processes
@@ -205,7 +242,7 @@ module Alda
205
242
  state = state == ?- ? nil : state.to_sym
206
243
  expiry = nil if expiry == ?-
207
244
  type = Alda::Utils.slug_to_snake type
208
- {id: id, port: port, state: state, expiry: expiry, type: type}
245
+ { id: id, port: port, state: state, expiry: expiry, type: type }
209
246
  end
210
247
  end
211
248
 
@@ -214,9 +251,9 @@ module Alda
214
251
  # up?() -> true or false
215
252
  #
216
253
  # Whether the alda server is up.
217
- # Always returns true if ::generation is +:v2+.
254
+ # Checks whether there are any play processes in ::processes in \Alda 2.
218
255
  def up?
219
- Alda.v2? || Alda.status.include?('up')
256
+ Alda.v1? ? Alda.status.include?('up') : Alda.processes.any? { _1[:type] == :player }
220
257
  end
221
258
 
222
259
  ##
@@ -224,9 +261,9 @@ module Alda
224
261
  # down? -> true or false
225
262
  #
226
263
  # Whether the alda server is down.
227
- # Always returns false if ::generation is +:v2+.
264
+ # Checks whether there are no play processes in ::processes in \Alda 2.
228
265
  def down?
229
- !Alda.v2? && Alda.status.include?('down')
266
+ Alda.v1? ? Alda.status.include?('down') : Alda.processes.none? { _1[:type] == :player }
230
267
  end
231
268
 
232
269
  ##
@@ -240,6 +277,6 @@ module Alda
240
277
  @generation = major == '1' ? :v1 : :v2
241
278
  end
242
279
 
243
- module_function :pipe, :processes, :up?, :down?, :deduce_generation
280
+ module_function :env, :pipe, :processes, :up?, :down?, :deduce_generation
244
281
 
245
282
  end
data/lib/alda-rb/error.rb CHANGED
@@ -58,15 +58,26 @@ class Alda::NREPLServerError < StandardError
58
58
  # This is an Array of String.
59
59
  attr_reader :problems
60
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
+
61
67
  ##
62
68
  # :call-seq:
63
- # new(host, port, problems) -> Alda::NREPLServerError
69
+ # new(host, port, problems, status) -> Alda::NREPLServerError
64
70
  #
65
71
  # Creates a Alda::NREPLServerError object.
66
72
  # Raises Alda::GenerationError if the current generation is not \Alda 2.
67
- def initialize host, port, problems
73
+ def initialize host, port, problems, status
68
74
  Alda::GenerationError.assert_generation [:v2]
69
- super problems.join ?\n
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
70
81
  @host = host
71
82
  @port = port
72
83
  @problems = problems
data/lib/alda-rb/event.rb CHANGED
@@ -365,7 +365,7 @@ end
365
365
  # end
366
366
  #
367
367
  # You can operate a score by purely using inline lisp events.
368
- # The following example only works in Alda 1 due to breaking changes in Alda 2
368
+ # The following example only works in \Alda 1 due to breaking changes in \Alda 2
369
369
  # ({alda-lang/alda#483}[https://github.com/alda-lang/alda/issues/483],
370
370
  # {alda-lang/alda#484}[https://github.com/alda-lang/alda/issues/484]).
371
371
  #
@@ -152,8 +152,8 @@ module Alda::EventList
152
152
  #
153
153
  # Append the events of another Alda::EventList object here.
154
154
  # This method covers the disadvantage of alda's being unable to
155
- # import scores from other files.
156
- # 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]).
157
157
  def import event_list
158
158
  @events.concat event_list.events
159
159
  nil
@@ -239,7 +239,7 @@ class Alda::Score
239
239
  # Alda::Score.new { piano_; c; d; e }.play from: 1
240
240
  # # (plays only an E note)
241
241
  def play **opts
242
- Alda.play code: self, **opts
242
+ Alda.env(ALDA_DISABLE_SPAWNING: :no) { Alda.play code: self, **opts }
243
243
  end
244
244
 
245
245
  ##
data/lib/alda-rb/repl.rb CHANGED
@@ -222,6 +222,11 @@ class Alda::REPL
222
222
  # Whether a preview of what \Alda code will be played everytime you input ruby codes.
223
223
  attr_accessor :preview
224
224
 
225
+ ##
226
+ # Whether to use Reline for input.
227
+ # When it is false, the \REPL session will be less buggy but less powerful.
228
+ attr_accessor :reline
229
+
225
230
  ##
226
231
  # :call-seq:
227
232
  # new(**opts) -> Alda::REPL
@@ -230,6 +235,7 @@ class Alda::REPL
230
235
  # The parameter +color+ specifies whether the output should be colored (sets #color).
231
236
  # The parameter +preview+ specifies whether a preview of what \Alda code will be played
232
237
  # everytime you input ruby codes (sets #preview).
238
+ # The parameter +reline+ specifies whether to use Reline for input.
233
239
  #
234
240
  # The +opts+ are passed to the command line of <tt>alda repl</tt>.
235
241
  # Available options are +host+, +port+, etc.
@@ -240,12 +246,14 @@ class Alda::REPL
240
246
  # A new one will be started only if no existing server is found.
241
247
  #
242
248
  # The +opts+ are ignored in \Alda 1.
243
- def initialize color: true, preview: true, **opts
249
+ def initialize color: true, preview: true, reline: true, **opts
244
250
  @score = TempScore.new self
245
251
  @binding = @score.get_binding
246
- @lex = RubyLex.new
252
+ # IRB once changed the API of RubyLex#initialize. Take care of that.
253
+ @lex = RubyLex.new *(RubyLex.instance_method(:initialize).arity == 0 ? [] : [@binding])
247
254
  @color = color
248
255
  @preview = preview
256
+ @reline = reline
249
257
  setup_repl opts
250
258
  end
251
259
 
@@ -261,14 +269,12 @@ class Alda::REPL
261
269
  if Alda.v1?
262
270
  @history = StringIO.new
263
271
  else
264
- if opts[:port] && [nil, 'localhost', '127.0.0.1'].include?(opts[:host]) &&
265
- Alda.processes.any? { _1[:port] == opts[:port].to_i && _1[:type] == :repl_server }
266
- @port = opts[:port].to_i
267
- @host = opts[:host] || 'localhost'
268
- else
269
- @nrepl_pipe = Alda.pipe :repl, **opts, server: true
270
- /nrepl:\/\/(?<host>[a-zA-Z0-9._\-]+):(?<port>\d+)/ =~ @nrepl_pipe.gets
271
- @host = host
272
+ @port = (opts.fetch :port, -1).to_i
273
+ @host = opts.fetch :host, 'localhost'
274
+ unless @port.positive? && %w[localhost 127.0.0.1].include?(@host) &&
275
+ Alda.processes.any? { _1[:port] == @port && _1[:type] == :repl_server }
276
+ Alda.env(ALDA_DISABLE_SPAWNING: :no) { @nrepl_pipe = Alda.pipe :repl, **opts, server: true }
277
+ /nrepl:\/\/[a-zA-Z0-9._\-]+:(?<port>\d+)/ =~ @nrepl_pipe.gets
272
278
  @port = port.to_i
273
279
  Process.detach @nrepl_pipe.pid
274
280
  end
@@ -314,8 +320,8 @@ class Alda::REPL
314
320
  def message op, **params
315
321
  result = raw_message op: Alda::Utils.snake_to_slug(op), **params
316
322
  result.transform_keys! { Alda::Utils.slug_to_snake _1 }
317
- if result.delete(:status).include? 'error'
318
- raise Alda::NREPLServerError.new @host, @port, result.delete(:problems)
323
+ if (status = result.delete :status).include? 'error'
324
+ raise Alda::NREPLServerError.new @host, @port, result.delete(:problems), status
319
325
  end
320
326
  case result.size
321
327
  when 0 then nil
@@ -358,7 +364,9 @@ class Alda::REPL
358
364
  indent = 0
359
365
  begin
360
366
  result.concat readline(indent).tap { return unless _1 }, ?\n
361
- ltype, indent, continue, block_open = @lex.check_state result
367
+ # IRB once changed the API of RubyLex#check_state. Take care of that.
368
+ opts = @lex.method(:check_state).arity.positive? ? {} : { context: @binding }
369
+ ltype, indent, continue, block_open = @lex.check_state result, **opts
362
370
  rescue Interrupt
363
371
  $stdout.puts
364
372
  return ''
@@ -372,18 +380,25 @@ class Alda::REPL
372
380
  #
373
381
  # Prompts the user to input a line.
374
382
  # The parameter +indent+ is the indentation level.
375
- # Twice the number of spaces is already in the input field before the user fills in.
383
+ # Twice the number of spaces is already in the input field before the user fills in
384
+ # if #reline is true.
376
385
  # The prompt hint is different for zero +indent+ and nonzero +indent+.
377
386
  # Returns the user input.
378
387
  def readline indent = 0
379
388
  prompt = indent.nonzero? ? '. ' : '> '
380
389
  prompt = prompt.green if @color
381
- Reline.pre_input_hook = -> do
382
- Reline.insert_text ' ' * indent
383
- Reline.redisplay
384
- Reline.pre_input_hook = nil
390
+ if @reline
391
+ Reline.pre_input_hook = -> do
392
+ Reline.insert_text ' ' * indent
393
+ Reline.redisplay
394
+ Reline.pre_input_hook = nil
395
+ end
396
+ Reline.readline prompt, true
397
+ else
398
+ $stdout.print prompt
399
+ $stdout.flush
400
+ $stdin.gets chomp: true
385
401
  end
386
- Reline.readline prompt, true
387
402
  end
388
403
 
389
404
  ##
@@ -456,7 +471,9 @@ class Alda::REPL
456
471
  else
457
472
  if @nrepl_pipe
458
473
  if Alda::Utils.win_platform?
459
- system 'taskkill', '/f', '/pid', @nrepl_pipe.pid.to_s
474
+ unless IO.popen(['taskkill', '/f', '/pid', @nrepl_pipe.pid.to_s], &:read).include? 'SUCCESS'
475
+ Alda::Warning.warn 'failed to kill nREPL server; may become zombie process'
476
+ end
460
477
  else
461
478
  Process.kill :INT, @nrepl_pipe.pid
462
479
  end
@@ -7,5 +7,5 @@ module Alda
7
7
  # The version number of alda-rb.
8
8
  #
9
9
  # The same as that in alda-rb gem spec.
10
- VERSION = '0.3.0'
10
+ VERSION = '0.3.1'
11
11
  end
metadata CHANGED
@@ -1,15 +1,71 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: alda-rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ulysses Zhan
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-05-30 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2023-06-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bencode
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: colorize
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '5.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '5.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '12.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '12.0'
13
69
  description:
14
70
  email:
15
71
  - UlyssesZhan@gmail.com
@@ -83,7 +139,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
83
139
  - !ruby/object:Gem::Version
84
140
  version: '0'
85
141
  requirements: []
86
- rubygems_version: 3.1.6
142
+ rubygems_version: 3.4.13
87
143
  signing_key:
88
144
  specification_version: 4
89
145
  summary: A Ruby library for live-coding music with Alda.