inform-runtime 1.3.2 → 1.5.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.
- checksums.yaml +4 -4
- data/lib/story_teller/io.rb +15 -66
- data/lib/story_teller/library.rb +0 -1
- data/lib/story_teller/session.rb +101 -5
- data/lib/story_teller/stdlib.rb +1 -1
- data/lib/story_teller/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1f6e015e55549341a59f8e1556996c1aa58073a0fd59eefd773aa1258a126668
|
|
4
|
+
data.tar.gz: 3841f6b206db14c64d5f7da3535992998932e5e80af56b819ce132e539e930f1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1cece70cd39f757e3c455e2dfc5712fb7d3f0aa3b21b0c66aaef53743ad375061a06529aed3cd44ed9e43341d6662377345ff347c0f9500b08fba65b9467d510
|
|
7
|
+
data.tar.gz: 4887504a753634d4247e792823a9389eda28fafc7b48acfd5603fa7a2586d5606977209a9efa64f6b5f2f4a4ed80cad5f21bcf7c96ac5fe78901d48f0428528c
|
data/lib/story_teller/io.rb
CHANGED
|
@@ -23,11 +23,17 @@
|
|
|
23
23
|
module StoryTeller
|
|
24
24
|
# The IO module
|
|
25
25
|
module IO
|
|
26
|
+
class << self
|
|
27
|
+
attr_accessor :default_output
|
|
28
|
+
end
|
|
29
|
+
|
|
26
30
|
def session
|
|
27
31
|
return @session if defined?(@session) && !@session.nil?
|
|
28
32
|
return nil unless defined?(StoryTeller::IO::Session)
|
|
29
33
|
|
|
30
|
-
StoryTeller::IO::Session.of(self)
|
|
34
|
+
StoryTeller::IO::Session.of(self).tap do |session|
|
|
35
|
+
log.trace "self: #{self}, session: #{session.inspect}"
|
|
36
|
+
end
|
|
31
37
|
end
|
|
32
38
|
|
|
33
39
|
def noop; end
|
|
@@ -40,13 +46,13 @@ module StoryTeller
|
|
|
40
46
|
subscribed_connections
|
|
41
47
|
end
|
|
42
48
|
|
|
43
|
-
def read
|
|
44
|
-
$stdin.gets(chomp: true)
|
|
45
|
-
end
|
|
46
|
-
|
|
47
49
|
def out(s)
|
|
48
|
-
|
|
49
|
-
|
|
50
|
+
current_session = session
|
|
51
|
+
|
|
52
|
+
if current_session
|
|
53
|
+
current_session.write_output(s)
|
|
54
|
+
elsif StoryTeller::IO.default_output
|
|
55
|
+
StoryTeller::IO.default_output.write(s)
|
|
50
56
|
else
|
|
51
57
|
$stdout.write(s)
|
|
52
58
|
end
|
|
@@ -64,13 +70,9 @@ module StoryTeller
|
|
|
64
70
|
alias update inform
|
|
65
71
|
|
|
66
72
|
def flush_io
|
|
67
|
-
|
|
68
|
-
end
|
|
73
|
+
return if session
|
|
69
74
|
|
|
70
|
-
|
|
71
|
-
s.gsub!(/^\n+/, "\n")
|
|
72
|
-
return s if s.length < columns || columns == 0
|
|
73
|
-
s.gsub(/(.{#{columns}}\S+)( +|$\n?)/, "\\1\n")
|
|
75
|
+
$stdout.flush
|
|
74
76
|
end
|
|
75
77
|
|
|
76
78
|
def new_line
|
|
@@ -128,59 +130,6 @@ module StoryTeller
|
|
|
128
130
|
DefaultLineLength
|
|
129
131
|
end
|
|
130
132
|
|
|
131
|
-
# def many_per_line(items)
|
|
132
|
-
# max = 0
|
|
133
|
-
|
|
134
|
-
# lines = []
|
|
135
|
-
# prefs = @player.linkto :preferences
|
|
136
|
-
# line_length = preferred_line_length
|
|
137
|
-
# buffer = ''
|
|
138
|
-
|
|
139
|
-
# items.each do |item|
|
|
140
|
-
# max = [item.length, max].max
|
|
141
|
-
# end
|
|
142
|
-
# max += MinimumColumnPadding
|
|
143
|
-
# width = (line_length - MinimumCellPadding) / max
|
|
144
|
-
# height = (items.length / width).ceil - 1
|
|
145
|
-
|
|
146
|
-
# return if width == 0
|
|
147
|
-
|
|
148
|
-
# columns = []
|
|
149
|
-
# i = 0
|
|
150
|
-
# loop do
|
|
151
|
-
# # Build a list of columns with nil padding
|
|
152
|
-
# column = items[i, height]
|
|
153
|
-
# columns << column + Array.new(height - column.length)
|
|
154
|
-
# i += height
|
|
155
|
-
# break if (i + height) >= (items.length + height)
|
|
156
|
-
# end
|
|
157
|
-
|
|
158
|
-
# m = []
|
|
159
|
-
# loop do
|
|
160
|
-
# m << []
|
|
161
|
-
# for column in columns
|
|
162
|
-
# m.last << column.shift
|
|
163
|
-
# end
|
|
164
|
-
# break if columns.last.empty?
|
|
165
|
-
# end
|
|
166
|
-
|
|
167
|
-
# m.each do |row|
|
|
168
|
-
# buffer = "\e[51m"
|
|
169
|
-
# row.each do |item|
|
|
170
|
-
# next unless item
|
|
171
|
-
# n = [max - item.length, MinimumColumnPadding].max
|
|
172
|
-
# padding = " " * n unless item == row.last
|
|
173
|
-
# buffer += format(ItemPaddingString, item: item, padding: padding)
|
|
174
|
-
# end
|
|
175
|
-
# buffer += "\e[56m"
|
|
176
|
-
# lines << buffer.strip
|
|
177
|
-
# buffer = ''
|
|
178
|
-
# end
|
|
179
|
-
|
|
180
|
-
# lines
|
|
181
|
-
# end
|
|
182
|
-
# # def many_per_line
|
|
183
|
-
|
|
184
133
|
# rubocop: disable Metrics/AbcSize
|
|
185
134
|
# rubocop: disable Metrics/CyclomaticComplexity
|
|
186
135
|
# rubocop: disable Metrics/MethodLength
|
data/lib/story_teller/library.rb
CHANGED
|
@@ -65,7 +65,6 @@ module StoryTeller
|
|
|
65
65
|
library_methods.merge(mod.instance_methods(false))
|
|
66
66
|
end
|
|
67
67
|
@methods_index.concat(library_methods.to_a).sort
|
|
68
|
-
log.trace "Loaded library methods: #{@methods_index}"
|
|
69
68
|
end
|
|
70
69
|
# rubocop: enable Metrics/AbcSize
|
|
71
70
|
# rubocop: enable Metrics/MethodLength
|
data/lib/story_teller/session.rb
CHANGED
|
@@ -144,6 +144,33 @@ end
|
|
|
144
144
|
module StoryTeller
|
|
145
145
|
# module IO
|
|
146
146
|
module IO
|
|
147
|
+
# The OutputBuffer class
|
|
148
|
+
class OutputBuffer
|
|
149
|
+
def initialize
|
|
150
|
+
@content = String.new # rubocop: disable Style/EmptyLiteral
|
|
151
|
+
@mutex = Mutex.new
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def write(value)
|
|
155
|
+
return if value.nil?
|
|
156
|
+
|
|
157
|
+
@mutex.synchronize { @content << value.to_s }
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def drain
|
|
161
|
+
@mutex.synchronize do
|
|
162
|
+
content = @content.dup
|
|
163
|
+
@content.clear
|
|
164
|
+
content.strip.length.positive? ? content : ''
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def reset
|
|
169
|
+
@mutex.synchronize { @content.clear }
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
# class OutputBuffer
|
|
173
|
+
|
|
147
174
|
# The Session class
|
|
148
175
|
# TODO: Refactor method implementations into modules
|
|
149
176
|
# rubocop: disable Metrics/ClassLength
|
|
@@ -154,7 +181,7 @@ class Session
|
|
|
154
181
|
include SessionManagementMethods
|
|
155
182
|
end
|
|
156
183
|
attr_accessor :channel, :machine, :player, :state, :status
|
|
157
|
-
attr_reader :last_good_state, :last_activity, :previous, :inbound, :outbound, :settings
|
|
184
|
+
attr_reader :last_good_state, :last_activity, :previous, :inbound, :outbound, :settings, :output
|
|
158
185
|
|
|
159
186
|
# These states accept any input, including no input
|
|
160
187
|
Promiscuous = Set.new
|
|
@@ -170,6 +197,7 @@ class Session
|
|
|
170
197
|
@settings = settings
|
|
171
198
|
@status = nil
|
|
172
199
|
@last_activity = Time.now
|
|
200
|
+
self.output = OutputBuffer.new
|
|
173
201
|
|
|
174
202
|
self.class.register(channel, self) unless channel.nil?
|
|
175
203
|
control(player) unless player.nil?
|
|
@@ -178,11 +206,78 @@ class Session
|
|
|
178
206
|
|
|
179
207
|
alias preferences settings
|
|
180
208
|
|
|
209
|
+
def output=(sink)
|
|
210
|
+
@output = sink
|
|
211
|
+
@outbound = sink
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
def write_output(value)
|
|
215
|
+
@output.write(value)
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
def drain_output
|
|
219
|
+
tidy_output(@outbound.drain)
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
def tidy_output(value, columns = word_wrap_column)
|
|
223
|
+
output = value.to_s
|
|
224
|
+
return '' if output.empty?
|
|
225
|
+
|
|
226
|
+
columns = columns.to_i
|
|
227
|
+
return output if columns <= 0
|
|
228
|
+
|
|
229
|
+
output.each_line.map do |line|
|
|
230
|
+
newline = line.end_with?("\n") ? "\n" : ''
|
|
231
|
+
wrap_line(line.chomp, columns) + newline
|
|
232
|
+
end.join
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
# rubocop: disable Metrics/AbcSize
|
|
236
|
+
# rubocop: disable Metrics/MethodLength
|
|
237
|
+
def wrap_line(line, columns)
|
|
238
|
+
return line if line.length <= columns
|
|
239
|
+
|
|
240
|
+
indentation = line[/\A[ \t]*/].to_s
|
|
241
|
+
words = line.strip.split(/[ \t]+/)
|
|
242
|
+
return line if words.empty?
|
|
243
|
+
|
|
244
|
+
lines = []
|
|
245
|
+
current = indentation.dup
|
|
246
|
+
|
|
247
|
+
words.each do |word|
|
|
248
|
+
candidate = current == indentation ? "#{current}#{word}" : "#{current} #{word}"
|
|
249
|
+
|
|
250
|
+
if candidate.length <= columns || current == indentation
|
|
251
|
+
current = candidate
|
|
252
|
+
else
|
|
253
|
+
lines << current.rstrip
|
|
254
|
+
current = "#{indentation}#{word}"
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
lines << current.rstrip
|
|
259
|
+
lines.join("\n")
|
|
260
|
+
end
|
|
261
|
+
# rubocop: enable Metrics/AbcSize
|
|
262
|
+
# rubocop: enable Metrics/MethodLength
|
|
263
|
+
|
|
264
|
+
def word_wrap_column
|
|
265
|
+
value = preferences[:word_wrap]
|
|
266
|
+
return 76 if value.nil?
|
|
267
|
+
|
|
268
|
+
value.to_i
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
def reset_output
|
|
272
|
+
@outbound.reset
|
|
273
|
+
end
|
|
274
|
+
|
|
181
275
|
def init_channel_session(channel)
|
|
182
276
|
Session[channel] = self
|
|
183
277
|
@channel = channel
|
|
184
|
-
@inbound = Inbound.new(self)
|
|
185
|
-
@
|
|
278
|
+
@inbound = Inbound.new(self) if defined?(Inbound)
|
|
279
|
+
@output = OutputBuffer.new
|
|
280
|
+
@outbound = @output
|
|
186
281
|
@last_activity = Time.now
|
|
187
282
|
end
|
|
188
283
|
|
|
@@ -230,7 +325,7 @@ class Session
|
|
|
230
325
|
end
|
|
231
326
|
|
|
232
327
|
def process(message, machine = @machine)
|
|
233
|
-
raise ArgumentError, '
|
|
328
|
+
raise ArgumentError, 'Session machine is required' if machine.nil?
|
|
234
329
|
|
|
235
330
|
@machine = machine
|
|
236
331
|
@buffer = sanitize(message)
|
|
@@ -239,10 +334,11 @@ class Session
|
|
|
239
334
|
|
|
240
335
|
expose_to(machine)
|
|
241
336
|
update(machine)
|
|
337
|
+
drain_output
|
|
242
338
|
end
|
|
243
339
|
|
|
244
340
|
def respond
|
|
245
|
-
|
|
341
|
+
drain_output
|
|
246
342
|
end
|
|
247
343
|
|
|
248
344
|
def safely_progress(machine = self)
|
data/lib/story_teller/stdlib.rb
CHANGED
data/lib/story_teller/version.rb
CHANGED