inform-runtime 1.3.1 → 1.4.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/engine.rb +8 -24
- data/lib/story_teller/grammar_parser.rb +4 -0
- data/lib/story_teller/io.rb +7 -64
- data/lib/story_teller/library/bootstrap.rb +0 -1
- data/lib/story_teller/library/location.rb +1 -7
- data/lib/story_teller/library.rb +0 -1
- data/lib/story_teller/session.rb +95 -4
- data/lib/story_teller/stdlib.rb +6 -3
- 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: 474087cc0143425969470924c1fe5e944b06f2d17ee76a097551345c4ca1959e
|
|
4
|
+
data.tar.gz: 8f933a9f47d17a247d804d226a32f8ff7d57e38698d0b0a262e40a796efd7972
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 606603f0fa1048e8cf566204167646989a99b1fcc80746ec3c8a7490d737ced8cdfb09be0e0cc7b0674123ed96b8588b387f6ed010328963c700816c172167a1
|
|
7
|
+
data.tar.gz: 3bab288d8358fcf11ca366756a1e451f3cfab0b231aa7e35d144397b4cba04257b1a92f2406581611628c03521d986db01aa32501818fe059f85f439d2a34370
|
data/lib/story_teller/engine.rb
CHANGED
|
@@ -43,7 +43,6 @@ module StoryTeller
|
|
|
43
43
|
environment: 'default',
|
|
44
44
|
inform6lib_gem_code_prefix: 'inform',
|
|
45
45
|
language: 'English',
|
|
46
|
-
persist_player_location: false,
|
|
47
46
|
properties: 'player actor action action_to_be ' \
|
|
48
47
|
'results parameters pattern ' \
|
|
49
48
|
'noun second inp1 inp2 ' \
|
|
@@ -60,16 +59,6 @@ module StoryTeller
|
|
|
60
59
|
@libraries ||= {}
|
|
61
60
|
end
|
|
62
61
|
|
|
63
|
-
def persist_player_location?
|
|
64
|
-
return @persist_player_location unless @persist_player_location.nil?
|
|
65
|
-
|
|
66
|
-
default_config.fetch(:persist_player_location, false)
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
def persist_player_location=(value)
|
|
70
|
-
@persist_player_location = value
|
|
71
|
-
end
|
|
72
|
-
|
|
73
62
|
def player_object
|
|
74
63
|
@player_object || parser_selfobj
|
|
75
64
|
end
|
|
@@ -107,26 +96,21 @@ module StoryTeller
|
|
|
107
96
|
libraries[selfobj] = inform_library
|
|
108
97
|
selfobj.inflib = inform_library if selfobj.respond_to?(:inflib=)
|
|
109
98
|
|
|
110
|
-
|
|
99
|
+
seed_library_location(inform_library) if location_unset?(inform_library)
|
|
111
100
|
|
|
112
101
|
inform_library
|
|
113
102
|
end
|
|
114
103
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
return if inflib.nil?
|
|
119
|
-
|
|
120
|
-
existing_location = inflib.instance_variable_get(:@location)
|
|
121
|
-
return unless existing_location.nil?
|
|
122
|
-
|
|
123
|
-
player = inflib.selfobj
|
|
124
|
-
location = player.location if player.respond_to?(:location)
|
|
125
|
-
location ||= player.spawn_point if player.respond_to?(:spawn_point)
|
|
104
|
+
def seed_library_location(inflib)
|
|
105
|
+
player_obj = inflib.selfobj
|
|
106
|
+
location = player_obj.location if player_obj.respond_to?(:location)
|
|
126
107
|
|
|
127
108
|
inflib.instance_variable_set(:@location, location) unless location.nil?
|
|
128
109
|
end
|
|
129
|
-
|
|
110
|
+
|
|
111
|
+
def location_unset?(inflib)
|
|
112
|
+
inflib&.instance_variable_get(:@location).nil?
|
|
113
|
+
end
|
|
130
114
|
|
|
131
115
|
def parser_selfobj
|
|
132
116
|
return nil unless defined?(Inform::Parser::SelfObj)
|
|
@@ -362,6 +362,10 @@ module Inform
|
|
|
362
362
|
!StoryTeller::Privileges.privileged?(obj, :builder))
|
|
363
363
|
end
|
|
364
364
|
|
|
365
|
+
def visible_to?(verb, actor)
|
|
366
|
+
verb.grammars.any? { |grammar| !guarded?(grammar, actor) }
|
|
367
|
+
end
|
|
368
|
+
|
|
365
369
|
def role(obj)
|
|
366
370
|
return :admin if StoryTeller::Privileges.privileged?(obj, :admin)
|
|
367
371
|
return :builder if StoryTeller::Privileges.privileged?(obj, :builder)
|
data/lib/story_teller/io.rb
CHANGED
|
@@ -27,7 +27,9 @@ module StoryTeller
|
|
|
27
27
|
return @session if defined?(@session) && !@session.nil?
|
|
28
28
|
return nil unless defined?(StoryTeller::IO::Session)
|
|
29
29
|
|
|
30
|
-
StoryTeller::IO::Session.of(self)
|
|
30
|
+
StoryTeller::IO::Session.of(self).tap do |session|
|
|
31
|
+
log.trace "self: #{self}, session: #{session.inspect}"
|
|
32
|
+
end
|
|
31
33
|
end
|
|
32
34
|
|
|
33
35
|
def noop; end
|
|
@@ -40,13 +42,11 @@ module StoryTeller
|
|
|
40
42
|
subscribed_connections
|
|
41
43
|
end
|
|
42
44
|
|
|
43
|
-
def read
|
|
44
|
-
$stdin.gets(chomp: true)
|
|
45
|
-
end
|
|
46
|
-
|
|
47
45
|
def out(s)
|
|
48
46
|
if defined?(Curses)
|
|
49
47
|
Curses.addstr s
|
|
48
|
+
elsif session
|
|
49
|
+
session.write_output(s)
|
|
50
50
|
else
|
|
51
51
|
$stdout.write(s)
|
|
52
52
|
end
|
|
@@ -64,13 +64,9 @@ module StoryTeller
|
|
|
64
64
|
alias update inform
|
|
65
65
|
|
|
66
66
|
def flush_io
|
|
67
|
-
|
|
68
|
-
end
|
|
67
|
+
return if session
|
|
69
68
|
|
|
70
|
-
|
|
71
|
-
s.gsub!(/^\n+/, "\n")
|
|
72
|
-
return s if s.length < columns || columns == 0
|
|
73
|
-
s.gsub(/(.{#{columns}}\S+)( +|$\n?)/, "\\1\n")
|
|
69
|
+
$stdout.flush
|
|
74
70
|
end
|
|
75
71
|
|
|
76
72
|
def new_line
|
|
@@ -128,59 +124,6 @@ module StoryTeller
|
|
|
128
124
|
DefaultLineLength
|
|
129
125
|
end
|
|
130
126
|
|
|
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
127
|
# rubocop: disable Metrics/AbcSize
|
|
185
128
|
# rubocop: disable Metrics/CyclomaticComplexity
|
|
186
129
|
# rubocop: disable Metrics/MethodLength
|
|
@@ -26,17 +26,11 @@ module StoryTeller
|
|
|
26
26
|
# module Location
|
|
27
27
|
module Location
|
|
28
28
|
def location
|
|
29
|
-
return @location unless StoryTeller::Engine.persist_player_location?
|
|
30
|
-
|
|
31
29
|
@player&.location || @location
|
|
32
30
|
end
|
|
33
31
|
|
|
34
32
|
def location=(obj)
|
|
35
|
-
|
|
36
|
-
@player.location = obj
|
|
37
|
-
else
|
|
38
|
-
@location = obj
|
|
39
|
-
end
|
|
33
|
+
@player.location = @location = obj
|
|
40
34
|
end
|
|
41
35
|
end
|
|
42
36
|
|
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
|
|
@@ -170,6 +197,7 @@ class Session
|
|
|
170
197
|
@settings = settings
|
|
171
198
|
@status = nil
|
|
172
199
|
@last_activity = Time.now
|
|
200
|
+
@outbound = OutputBuffer.new
|
|
173
201
|
|
|
174
202
|
self.class.register(channel, self) unless channel.nil?
|
|
175
203
|
control(player) unless player.nil?
|
|
@@ -178,11 +206,73 @@ class Session
|
|
|
178
206
|
|
|
179
207
|
alias preferences settings
|
|
180
208
|
|
|
209
|
+
def write_output(value)
|
|
210
|
+
@outbound.write(value)
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def drain_output
|
|
214
|
+
tidy_output(@outbound.drain)
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def tidy_output(value, columns = word_wrap_column)
|
|
218
|
+
output = value.to_s
|
|
219
|
+
return '' if output.empty?
|
|
220
|
+
|
|
221
|
+
columns = columns.to_i
|
|
222
|
+
return output if columns <= 0
|
|
223
|
+
|
|
224
|
+
# output = output.gsub(/^\n+/, "\n")
|
|
225
|
+
output.each_line.map do |line|
|
|
226
|
+
newline = line.end_with?("\n") ? "\n" : ''
|
|
227
|
+
wrap_line(line.chomp, columns) + newline
|
|
228
|
+
end.join
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
# rubocop: disable Metrics/AbcSize
|
|
232
|
+
# rubocop: disable Metrics/MethodLength
|
|
233
|
+
def wrap_line(line, columns)
|
|
234
|
+
return line if line.length <= columns
|
|
235
|
+
|
|
236
|
+
indentation = line[/\A[ \t]*/].to_s
|
|
237
|
+
words = line.strip.split(/[ \t]+/)
|
|
238
|
+
return line if words.empty?
|
|
239
|
+
|
|
240
|
+
lines = []
|
|
241
|
+
current = indentation.dup
|
|
242
|
+
|
|
243
|
+
words.each do |word|
|
|
244
|
+
candidate = current == indentation ? "#{current}#{word}" : "#{current} #{word}"
|
|
245
|
+
|
|
246
|
+
if candidate.length <= columns || current == indentation
|
|
247
|
+
current = candidate
|
|
248
|
+
else
|
|
249
|
+
lines << current.rstrip
|
|
250
|
+
current = "#{indentation}#{word}"
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
lines << current.rstrip
|
|
255
|
+
lines.join("\n")
|
|
256
|
+
end
|
|
257
|
+
# rubocop: enable Metrics/AbcSize
|
|
258
|
+
# rubocop: enable Metrics/MethodLength
|
|
259
|
+
|
|
260
|
+
def word_wrap_column
|
|
261
|
+
value = preferences[:word_wrap]
|
|
262
|
+
return 76 if value.nil?
|
|
263
|
+
|
|
264
|
+
value.to_i
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
def reset_output
|
|
268
|
+
@outbound.reset
|
|
269
|
+
end
|
|
270
|
+
|
|
181
271
|
def init_channel_session(channel)
|
|
182
272
|
Session[channel] = self
|
|
183
273
|
@channel = channel
|
|
184
|
-
@inbound = Inbound.new(self)
|
|
185
|
-
@outbound =
|
|
274
|
+
@inbound = Inbound.new(self) if defined?(Inbound)
|
|
275
|
+
@outbound = OutputBuffer.new
|
|
186
276
|
@last_activity = Time.now
|
|
187
277
|
end
|
|
188
278
|
|
|
@@ -230,7 +320,7 @@ class Session
|
|
|
230
320
|
end
|
|
231
321
|
|
|
232
322
|
def process(message, machine = @machine)
|
|
233
|
-
raise ArgumentError, '
|
|
323
|
+
raise ArgumentError, 'Session machine is required' if machine.nil?
|
|
234
324
|
|
|
235
325
|
@machine = machine
|
|
236
326
|
@buffer = sanitize(message)
|
|
@@ -239,10 +329,11 @@ class Session
|
|
|
239
329
|
|
|
240
330
|
expose_to(machine)
|
|
241
331
|
update(machine)
|
|
332
|
+
drain_output
|
|
242
333
|
end
|
|
243
334
|
|
|
244
335
|
def respond
|
|
245
|
-
|
|
336
|
+
drain_output
|
|
246
337
|
end
|
|
247
338
|
|
|
248
339
|
def safely_progress(machine = self)
|
data/lib/story_teller/stdlib.rb
CHANGED
|
@@ -49,7 +49,7 @@ module StdLib
|
|
|
49
49
|
end
|
|
50
50
|
|
|
51
51
|
def inversion
|
|
52
|
-
print Inform::VERSION
|
|
52
|
+
print Inform::VERSION.dup
|
|
53
53
|
end
|
|
54
54
|
|
|
55
55
|
def standard_interpreter
|
|
@@ -764,6 +764,10 @@ module Rules
|
|
|
764
764
|
page_index: 0, limit: 10, help: nil, done: :playing
|
|
765
765
|
}.freeze
|
|
766
766
|
|
|
767
|
+
MORE_HELP_STRING = "Press Enter to show the next page.\n" +
|
|
768
|
+
"Type q or quit to stop paging and return to the command prompt.\n" +
|
|
769
|
+
"Type ? to show this help."
|
|
770
|
+
|
|
767
771
|
# This method supports the MoreSub verb implementation.
|
|
768
772
|
# rubocop: disable Metrics/AbcSize
|
|
769
773
|
# rubocop: disable Metrics/CyclomaticComplexity
|
|
@@ -788,7 +792,7 @@ module Rules
|
|
|
788
792
|
|
|
789
793
|
case input
|
|
790
794
|
when /\?/
|
|
791
|
-
println params[:help] ||
|
|
795
|
+
println params[:help] || MORE_HELP_STRING
|
|
792
796
|
when /^(q|quit)$/
|
|
793
797
|
@more = nil
|
|
794
798
|
@prompt = nil
|
|
@@ -816,7 +820,6 @@ module Rules
|
|
|
816
820
|
session.state = :more
|
|
817
821
|
else
|
|
818
822
|
new_line
|
|
819
|
-
prompt nil
|
|
820
823
|
session.state = params[:done]
|
|
821
824
|
end
|
|
822
825
|
end
|
data/lib/story_teller/version.rb
CHANGED