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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1a9737a28a03ce80dd3698d1fc2824b22cb3090d4f0db6c3b52c84134e17a04c
4
- data.tar.gz: 30ea465986dd84a628280ffa63c83228e04689db657d26c1bf449a15a779165a
3
+ metadata.gz: 474087cc0143425969470924c1fe5e944b06f2d17ee76a097551345c4ca1959e
4
+ data.tar.gz: 8f933a9f47d17a247d804d226a32f8ff7d57e38698d0b0a262e40a796efd7972
5
5
  SHA512:
6
- metadata.gz: f0f82b48842ed1cb74515abf3e26d2aeadc1c29004177a556e819ff814c3ce7ee63cf8b4225f5a53a3bfa8102c6bfa2ad0a21ad4b2654518269535c9fc3eca0f
7
- data.tar.gz: e6122d69fc1a5fbbe2640709f567889a7d70d303740796883bec8ffb3001abd243b91597c02f12a7d31e9aac61de7e08b288cd648c9f784140e935279a2fb085
6
+ metadata.gz: 606603f0fa1048e8cf566204167646989a99b1fcc80746ec3c8a7490d737ced8cdfb09be0e0cc7b0674123ed96b8588b387f6ed010328963c700816c172167a1
7
+ data.tar.gz: 3bab288d8358fcf11ca366756a1e451f3cfab0b231aa7e35d144397b4cba04257b1a92f2406581611628c03521d986db01aa32501818fe059f85f439d2a34370
@@ -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
- ensure_player_location(inform_library) if persist_player_location?
99
+ seed_library_location(inform_library) if location_unset?(inform_library)
111
100
 
112
101
  inform_library
113
102
  end
114
103
 
115
- # rubocop: disable Metrics/CyclomaticComplexity
116
- def ensure_player_location(inflib)
117
- return unless persist_player_location?
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
- # rubocop: enable Metrics/CyclomaticComplexity
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)
@@ -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
- $stdout.flush
68
- end
67
+ return if session
69
68
 
70
- def tidy_output(s, columns = 76)
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
@@ -38,7 +38,6 @@ module StoryTeller
38
38
  inflib = InformLibrary.new
39
39
  bind_inform_library(inflib, player)
40
40
  inflib.subscribe(inflib.selfobj)
41
- ensure_player_location(inflib) if StoryTeller::Engine.persist_player_location?
42
41
  inflib
43
42
  end
44
43
  end
@@ -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
- if StoryTeller::Engine.persist_player_location?
36
- @player.location = obj
37
- else
38
- @location = obj
39
- end
33
+ @player.location = @location = obj
40
34
  end
41
35
  end
42
36
 
@@ -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
@@ -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 = Outbound.new(self)
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, 'session machine is required' if machine.nil?
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
- flush_io
336
+ drain_output
246
337
  end
247
338
 
248
339
  def safely_progress(machine = self)
@@ -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] || "<Help for More goes here>"
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
@@ -23,7 +23,7 @@
23
23
  module StoryTeller
24
24
  # module Engine
25
25
  module Engine
26
- VERSION = '1.3.1'.freeze
26
+ VERSION = '1.4.0'.freeze
27
27
  end
28
28
  end
29
29
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: inform-runtime
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.1
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nels Nelson