alda-rb 0.1.4 → 0.2.0

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.
@@ -0,0 +1,245 @@
1
+ require 'colorize'
2
+ require 'irb/ruby-lex'
3
+ require 'json'
4
+ require 'readline'
5
+ require 'stringio'
6
+
7
+ ##
8
+ # :call-seq:
9
+ # repl() -> nil
10
+ #
11
+ # Start a REPL session.
12
+ def Alda.repl
13
+ Alda::REPL.new.run
14
+ end
15
+
16
+ ##
17
+ # An instance of this class is an \REPL session.
18
+ #
19
+ # It provides an Alda::REPL::TempScore for you to operate on.
20
+ # To see what methods you can call in an \REPL session,
21
+ # see instance methods of Alda::REPL::TempScore.
22
+ #
23
+ # The session uses "> " to indicate your input.
24
+ # Your input should be ruby codes, and the codes will be
25
+ # sent to an Alda::REPL::TempScore and executed.
26
+ #
27
+ # After executing the ruby codes, if the score is not empty,
28
+ # it is played, and the translated alda codes are printed.
29
+ #
30
+ # Note that every time your ruby codes input is executed,
31
+ # the score is cleared beforehand. To check the result of
32
+ # your previous input, run <tt>puts history</tt>.
33
+ #
34
+ # Unlike \IRB, this \REPL does not print the result of
35
+ # the executed codes. Use +p+ if you want.
36
+ #
37
+ # +Interrupt+ and +SystemExit+ exceptions are rescued and
38
+ # will not cause the process terminating.
39
+ # +exit+ terminates the \REPL session instead of the process.
40
+ #
41
+ # To start an \REPL session in a ruby program, use Alda::repl.
42
+ # To start an \REPL session conveniently from command line,
43
+ # run command <tt>ruby -ralda-rb -e "Alda.repl"</tt>.
44
+ #
45
+ # $ ruby -ralda-rb -e "Alda.repl"
46
+ # > puts status
47
+ # [27713] Server up (2/2 workers available, backend port: 33245)
48
+ # > piano_ c d e f
49
+ # [piano: c d e f]
50
+ # > 5.times do
51
+ # > c
52
+ # > end
53
+ # c c c c c
54
+ # > puts history
55
+ # [piano: c d e f]
56
+ # c c c c c
57
+ # > play
58
+ # > save 'temp.alda'
59
+ # > puts `cat temp.alda`
60
+ # [piano: c d e f]
61
+ # c c c c c
62
+ # > system 'rm temp.alda'
63
+ # > exit
64
+ class Alda::REPL
65
+
66
+ ##
67
+ # The score object used in Alda::REPL.
68
+ #
69
+ # Includes Alda, so it can refer to alda commandline.
70
+ #
71
+ # When you are in an \REPL session, you are actually
72
+ # in an instance of this class,
73
+ # so you can call the instance methods down here
74
+ # when you play with an \REPL.
75
+ class TempScore < Alda::Score
76
+ include Alda
77
+
78
+ Score.instance_methods(false).each do |meth|
79
+ define_method meth, Score.instance_method(meth)
80
+ end
81
+
82
+ def initialize session
83
+ super()
84
+ @session = session
85
+ end
86
+
87
+ def to_s
88
+ history
89
+ end
90
+
91
+ def history
92
+ @session.history.to_s
93
+ end
94
+
95
+ def clear_history
96
+ @session.clear_history
97
+ end
98
+
99
+ def get_binding
100
+ binding
101
+ end
102
+
103
+ def score
104
+ puts history
105
+ end
106
+
107
+ def map
108
+ puts JSON.generate JSON.parse(parse),
109
+ indent: ' ', space: ' ', object_nl: ?\n, array_nl: ?\n
110
+ end
111
+
112
+ alias quit exit
113
+ alias new clear_history
114
+ end
115
+
116
+ ##
117
+ # The history.
118
+ attr_reader :history
119
+
120
+ ##
121
+ # :call-seq:
122
+ # new() -> Alda::REPL
123
+ #
124
+ # Creates a new Alda::REPL.
125
+ def initialize
126
+ @score = TempScore.new self
127
+ @binding = @score.get_binding
128
+ @lex = RubyLex.new
129
+ @history = StringIO.new
130
+ end
131
+
132
+ ##
133
+ # :call-seq:
134
+ # run() -> nil
135
+ #
136
+ # Runs the session.
137
+ # Includes the start, the main loop, and the termination.
138
+ def run
139
+ start
140
+ while code = rb_code
141
+ break unless process_rb_code code
142
+ end
143
+ terminate
144
+ end
145
+
146
+ ##
147
+ # :call-seq:
148
+ # start() -> nil
149
+ #
150
+ # Starts the session. Currently does nothing.
151
+ def start
152
+ end
153
+
154
+ ##
155
+ # :call-seq:
156
+ # rb_code() -> String
157
+ #
158
+ # Reads and returns the next Ruby codes input in the \REPL session.
159
+ # It can intelligently continue reading if the code is not complete yet.
160
+ def rb_code
161
+ result = ''
162
+ begin
163
+ buf = Readline.readline '> '.green, true
164
+ return unless buf
165
+ result.concat buf, ?\n
166
+ ltype, indent, continue, block_open = @lex.check_state result
167
+ rescue Interrupt
168
+ $stdout.puts
169
+ retry
170
+ end while ltype || indent.nonzero? || continue || block_open
171
+ result
172
+ end
173
+
174
+ ##
175
+ # :call-seq:
176
+ # process_rb_code(code) -> true or false
177
+ #
178
+ # Processes the Ruby codes read.
179
+ # Sends it to a score and sends the result to command line alda.
180
+ # Returns +false+ for breaking the \REPL main loop, +true+ otherwise.
181
+ def process_rb_code code
182
+ @score.clear
183
+ begin
184
+ @binding.eval code
185
+ rescue StandardError, ScriptError => e
186
+ $stderr.print e.full_message
187
+ return true
188
+ rescue Interrupt
189
+ return true
190
+ rescue SystemExit
191
+ return false
192
+ end
193
+ code = @score.events_alda_codes
194
+ unless code.empty?
195
+ $stdout.puts code.yellow
196
+ play_score code
197
+ end
198
+ true
199
+ end
200
+
201
+ ##
202
+ # :call-seq:
203
+ # try_command() { ... } -> obj
204
+ #
205
+ # Tries to run the block and rescue Alda::CommandLineError.
206
+ def try_command
207
+ begin
208
+ yield
209
+ rescue Alda::CommandLineError => e
210
+ puts e.message.red
211
+ end
212
+ end
213
+
214
+ ##
215
+ # :call-seq:
216
+ # play_score(code) -> nil
217
+ #
218
+ # Plays the score by sending +code+ to command line alda.
219
+ def play_score code
220
+ try_command do
221
+ Alda.play code: code, history: @history
222
+ @history.puts code
223
+ end
224
+ end
225
+
226
+ ##
227
+ # :call-seq:
228
+ # terminate() -> nil
229
+ #
230
+ # Terminates the REPL session.
231
+ # Currently just clears #history.
232
+ def terminate
233
+ clear_history
234
+ end
235
+
236
+ ##
237
+ # :call-seq:
238
+ # clear_history() -> nil
239
+ #
240
+ # Clears #history.
241
+ def clear_history
242
+ @history = StringIO.new
243
+ nil
244
+ end
245
+ end
@@ -1,5 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ ##
4
+ # The module serving as a namespace.
3
5
  module Alda
4
- VERSION = '0.1.4'
6
+ ##
7
+ # The version number of alda-rb.
8
+ #
9
+ # The same as that in alda-rb gem spec.
10
+ VERSION = '0.2.0'
5
11
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: alda-rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ulysses Zhan
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-04-24 00:00:00.000000000 Z
11
+ date: 2020-08-13 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email:
@@ -44,6 +44,12 @@ files:
44
44
  - examples/showcase.rb
45
45
  - examples/variables.rb
46
46
  - lib/alda-rb.rb
47
+ - lib/alda-rb/commandline.rb
48
+ - lib/alda-rb/error.rb
49
+ - lib/alda-rb/event.rb
50
+ - lib/alda-rb/event_list.rb
51
+ - lib/alda-rb/patches.rb
52
+ - lib/alda-rb/repl.rb
47
53
  - lib/alda-rb/version.rb
48
54
  homepage: https://github.com/UlyssesZh/alda-rb
49
55
  licenses: