alda-rb 0.1.4 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: