inform-runtime 1.2.2 → 1.3.1

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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +33 -41
  3. data/lib/story_teller/articles.rb +2 -1
  4. data/lib/story_teller/builtins.rb +63 -10
  5. data/lib/story_teller/color.rb +2 -1
  6. data/lib/story_teller/command.rb +4 -1
  7. data/lib/story_teller/context.rb +23 -27
  8. data/lib/story_teller/daemon.rb +2 -2
  9. data/lib/story_teller/engine.rb +80 -16
  10. data/lib/story_teller/events.rb +9 -2
  11. data/lib/story_teller/experimental/handler_dsl.rb +1 -16
  12. data/lib/story_teller/experimental/reverse_engineer_class.rb +1 -1
  13. data/lib/story_teller/grammar_parser.rb +60 -13
  14. data/lib/story_teller/helpers.rb +8 -18
  15. data/lib/story_teller/history.rb +2 -1
  16. data/lib/story_teller/inflector.rb +4 -2
  17. data/lib/story_teller/inform/ephemeral/link.rb +63 -31
  18. data/lib/story_teller/inform/ephemeral/module.rb +6 -5
  19. data/lib/story_teller/inform/ephemeral/object.rb +223 -236
  20. data/lib/story_teller/inform/ephemeral/tag.rb +27 -14
  21. data/lib/story_teller/io.rb +99 -49
  22. data/lib/story_teller/kernel.rb +13 -5
  23. data/lib/story_teller/library/bootstrap.rb +10 -27
  24. data/lib/story_teller/library/declarations.rb +1 -1
  25. data/lib/story_teller/library/directives.rb +1 -1
  26. data/lib/story_teller/library/loader.rb +4 -20
  27. data/lib/story_teller/library/location.rb +9 -3
  28. data/lib/story_teller/library.rb +1 -1
  29. data/lib/story_teller/logging.rb +165 -67
  30. data/lib/story_teller/mixins.rb +11 -4
  31. data/lib/story_teller/plurals.rb +2 -1
  32. data/lib/story_teller/privileges.rb +117 -0
  33. data/lib/story_teller/prototype.rb +158 -32
  34. data/lib/story_teller/publication.rb +2 -1
  35. data/lib/story_teller/session.rb +115 -25
  36. data/lib/story_teller/stdlib.rb +232 -2
  37. data/lib/story_teller/subscription.rb +2 -1
  38. data/lib/story_teller/tree.rb +2 -1
  39. data/lib/story_teller/version.rb +2 -2
  40. data/lib/story_teller/world_tree.rb +21 -23
  41. data/lib/story_teller.rb +18 -5
  42. metadata +7 -10
  43. data/lib/story_teller/core.rb +0 -38
  44. data/lib/story_teller/ephemeral_adapter.rb +0 -40
  45. data/lib/story_teller/inform/base.rb +0 -160
  46. data/lib/story_teller/model_adapter.rb +0 -132
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3c1f6b9a2d86d9855a752009619386dd1e8af63c40e2c0cf9dfba94f38b1ac3c
4
- data.tar.gz: b0558bb28bf5348f55b42b0b9a038ba23a77a75ee6c939e5deb843820f616022
3
+ metadata.gz: 1a9737a28a03ce80dd3698d1fc2824b22cb3090d4f0db6c3b52c84134e17a04c
4
+ data.tar.gz: 30ea465986dd84a628280ffa63c83228e04689db657d26c1bf449a15a779165a
5
5
  SHA512:
6
- metadata.gz: 73ad7ed36d79a1a512f9c69c9c1b0069a04718e72c7547869326559bfe3d56f3fea32c383e57191e6ef1c48048195aed4380bc1014d79be13d3a6514c52eebeb
7
- data.tar.gz: ebb8265637ff63fe25ea54b9f0dbcdd81a6c9aab2e1b9a900b02b113fe350011973083af788b68c3950a09c2506a514ed59b74daaa09037bfa582bbafed4d7d2
6
+ metadata.gz: f0f82b48842ed1cb74515abf3e26d2aeadc1c29004177a556e819ff814c3ce7ee63cf8b4225f5a53a3bfa8102c6bfa2ad0a21ad4b2654518269535c9fc3eca0f
7
+ data.tar.gz: e6122d69fc1a5fbbe2640709f567889a7d70d303740796883bec8ffb3001abd243b91597c02f12a7d31e9aac61de7e08b288cd648c9f784140e935279a2fb085
data/README.md CHANGED
@@ -1,16 +1,14 @@
1
- # StoryTeller
1
+ # StoryTeller Engine
2
2
 
3
3
  [![License](https://img.shields.io/badge/license-GPLv3-blue.svg?style=flat)](license-gpl)
4
4
 
5
-
6
-
7
- **StoryTeller** is a runtime layer for use by software programs used to
5
+ **StoryTeller Engine** is a runtime layer for use by software programs used to
8
6
  play interactive-fiction games which are built for the [Inform 6 Ruby Port].
9
7
 
10
- StoryTeller is intended to simply provide the barest minimum facilities
11
- required by the Inform 6 Library Ruby Port software to function in the
12
- context of a game play specified by a game directory or file. It does not
13
- attempt to replicate a byte code interpreter runtime like frotz.
8
+ The StoryTeller Engine is intended to simply provide the barest minimum
9
+ facilities required by the Inform 6 Library Ruby Port software to function
10
+ in the context of a game play specified by a game directory or file. It
11
+ does not attempt to replicate a byte code interpreter runtime like frotz.
14
12
 
15
13
 
16
14
  ## Install mise-en-place
@@ -97,81 +95,75 @@ bundle exec rake test
97
95
  Here is a bird's-eye view of the project layout.
98
96
 
99
97
  ```sh
100
- # date && tree -A -I "game|logs|vendor|tmp|Gemfile.lock"
101
- Sat Dec 13 22:05:24 CST 2025
98
+ # $ date && tree -A -I "coverage|game|logs|vendor|tmp|Gemfile.lock"
99
+ Sun May 10 09:36:13 CDT 2026
102
100
  .
103
- ├── config
104
- │ └── database.yml
105
101
  ├── CONTRIBUTING.md
106
- ├── exe
107
- │ └── inform.rb
108
102
  ├── Gemfile
103
+ ├── inform-runtime-1.2.3.gem
109
104
  ├── inform-runtime.gemspec
110
105
  ├── lib
111
- │ ├── runtime
106
+ │ ├── story_teller
112
107
  │ │ ├── articles.rb
113
108
  │ │ ├── builtins.rb
114
109
  │ │ ├── color.rb
115
110
  │ │ ├── command.rb
116
- │ │ ├── config.rb
117
111
  │ │ ├── context.rb
118
112
  │ │ ├── daemon.rb
119
- │ │ ├── database.rb
113
+ │ │ ├── engine.rb
120
114
  │ │ ├── events.rb
121
115
  │ │ ├── experimental
122
- │ │ │ └── handler_dsl.rb
123
- │ │ ├── game_loader.rb
124
- │ │ ├── game.rb
116
+ │ │ │ ├── handler_dsl.rb
117
+ │ │ │ └── reverse_engineer_class.rb
125
118
  │ │ ├── grammar_parser.rb
126
119
  │ │ ├── helpers.rb
127
120
  │ │ ├── history.rb
128
121
  │ │ ├── inflector.rb
122
+ │ │ ├── inform
123
+ │ │ │ ├── ephemeral
124
+ │ │ │ │ ├── link.rb
125
+ │ │ │ │ ├── module.rb
126
+ │ │ │ │ ├── object.rb
127
+ │ │ │ │ └── tag.rb
128
+ │ │ │ └── models.rb
129
129
  │ │ ├── io.rb
130
130
  │ │ ├── kernel.rb
131
- │ │ ├── library_loader.rb
131
+ │ │ ├── library
132
+ │ │ │ ├── bootstrap.rb
133
+ │ │ │ ├── declarations.rb
134
+ │ │ │ ├── directives.rb
135
+ │ │ │ ├── loader.rb
136
+ │ │ │ └── location.rb
132
137
  │ │ ├── library.rb
133
- │ │ ├── link.rb
134
138
  │ │ ├── logging.rb
135
139
  │ │ ├── mixins.rb
136
- │ │ ├── module.rb
137
- │ │ ├── object.rb
138
- │ │ ├── options.rb
139
- │ │ ├── persistence.rb
140
140
  │ │ ├── plurals.rb
141
+ │ │ ├── privileges.rb
141
142
  │ │ ├── prototype.rb
142
143
  │ │ ├── publication.rb
143
- │ │ ├── runtime.rb
144
144
  │ │ ├── session.rb
145
- │ │ ├── snapshots.rb
146
145
  │ │ ├── stdlib.rb
147
146
  │ │ ├── subscription.rb
148
- │ │ ├── tag.rb
149
147
  │ │ ├── tree.rb
150
148
  │ │ ├── version.rb
151
149
  │ │ └── world_tree.rb
152
- │ └── runtime.rb
150
+ │ └── story_teller.rb
153
151
  ├── LICENSE
154
152
  ├── Rakefile
155
153
  ├── README.md
156
154
  ├── roller2.jpg
157
- ├── scripts
158
- │ ├── backup.rb
159
- │ ├── clone.rb
160
- │ ├── delete.rb
161
- │ ├── init.rb
162
- │ ├── rebuild.rb
163
- │ └── restore.rb
164
155
  └── spec
165
- ├── game_spec.rb
156
+ ├── engine_spec.rb
157
+ ├── inform_ephemeral_spec.rb
166
158
  ├── inform_spec.rb
167
- ├── inform_system_spec.rb
168
- ├── object_spec.rb
169
159
  ├── parser_spec.rb
160
+ ├── prototype_spec.rb
170
161
  ├── spec_helper.rb
162
+ ├── stdlib_spec.rb
171
163
  ├── verblib_spec.rb
172
164
  └── verify_gem_spec.rb
173
165
 
174
- 7 directories, 63 files
166
+ 8 directories, 57 files
175
167
  ```
176
168
 
177
169
  Thanks!
@@ -1,7 +1,8 @@
1
+ # lib/story_teller/articles.rb
1
2
  # encoding: utf-8
2
3
  # frozen_string_literal: false
3
4
 
4
- # Copyright Nels Nelson 2008-2025 but freely usable (see license)
5
+ # Copyright Nels Nelson 2008-2026 but freely usable (see license)
5
6
  #
6
7
  # This file is part of the StoryTeller.
7
8
  #
@@ -2,7 +2,7 @@
2
2
  # encoding: utf-8
3
3
  # frozen_string_literal: false
4
4
 
5
- # Copyright Nels Nelson 2008-2025 but freely usable (see license)
5
+ # Copyright Nels Nelson 2008-2026 but freely usable (see license)
6
6
  #
7
7
  # This file is part of the StoryTeller.
8
8
  #
@@ -165,25 +165,78 @@ module Builtins
165
165
 
166
166
  def objectloop(*_args, &block)
167
167
  if self.is_a?(InformLibrary)
168
- object_class = StoryTeller::ModelAdapter.object_class
169
- object_class&.all&.each { |o| block.call(o) }
168
+ inform_object_collection.each { |object| block.call(object) }
170
169
  elsif self.respond_to?(:descendants)
171
- self.descendants.each { |o| block.call(o) }
170
+ self.descendants.each { |object| block.call(object) }
172
171
  end
173
172
  end
174
173
 
175
174
  def getobject(id)
176
- object_class = StoryTeller::ModelAdapter.object_class!
177
- o = object_class[id]
178
- o.refresh
175
+ object = inform_object_fetch(id)
176
+ object.refresh if object.respond_to?(:refresh)
177
+ object
179
178
  rescue StandardError
180
179
  raise NoSuchObject
181
180
  end
182
181
 
182
+ # rubocop: disable Metrics/AbcSize
183
+ # rubocop: disable Metrics/CyclomaticComplexity
184
+ # rubocop: disable Metrics/MethodLength
183
185
  def findobject(*args, &block)
184
- object_class = StoryTeller::ModelAdapter.object_class!
185
- return object_class.dataset.order(:name, :id).grep(:name, *args).to_a if args.first.is_a?(Regexp)
186
- object_class.dataset.grep(&block).to_a
186
+ object_class = inform_object_class
187
+
188
+ if sequel_model?(object_class)
189
+ return object_class.dataset.order(:name, :id).grep(:name, *args).to_a if args.first.is_a?(Regexp)
190
+
191
+ return object_class.dataset.grep(&block).to_a
192
+ end
193
+
194
+ objects = inform_object_collection
195
+ if args.first.is_a?(Regexp)
196
+ return objects.select do |object|
197
+ object_name_matches?(object, args.first)
198
+ end
199
+ end
200
+
201
+ block.nil? ? objects : objects.select(&block)
202
+ end
203
+ # rubocop: enable Metrics/AbcSize
204
+ # rubocop: enable Metrics/CyclomaticComplexity
205
+ # rubocop: enable Metrics/MethodLength
206
+
207
+ def inform_object_class
208
+ if defined?(Inform::Object) && sequel_model?(Inform::Object)
209
+ Inform::Object
210
+ elsif defined?(Inform::Ephemeral::Object)
211
+ Inform::Ephemeral::Object
212
+ end
213
+ end
214
+
215
+ def sequel_model?(object_class)
216
+ !object_class.nil? && object_class.respond_to?(:dataset)
217
+ end
218
+
219
+ def inform_object_collection
220
+ object_class = inform_object_class
221
+ return Array::Empty if object_class.nil?
222
+ return object_class.all if object_class.respond_to?(:all)
223
+
224
+ Array::Empty
225
+ end
226
+
227
+ def inform_object_fetch(id)
228
+ object_class = inform_object_class
229
+ raise NoSuchObject if object_class.nil?
230
+
231
+ object = object_class[id] if object_class.respond_to?(:[])
232
+ raise NoSuchObject if object.nil?
233
+
234
+ object
235
+ end
236
+
237
+ def object_name_matches?(object, pattern)
238
+ name = object.name if object.respond_to?(:name)
239
+ Array(name).any? { |part| part.to_s.match?(pattern) } || name.to_s.match?(pattern)
187
240
  end
188
241
 
189
242
  def deadflag; @deadflag; end
@@ -1,7 +1,8 @@
1
+ # lib/story_teller/color.rb
1
2
  # encoding: utf-8
2
3
  # frozen_string_literal: false
3
4
 
4
- # Copyright Nels Nelson 2008-2025 but freely usable (see license)
5
+ # Copyright Nels Nelson 2008-2026 but freely usable (see license)
5
6
  #
6
7
  # This file is part of the StoryTeller.
7
8
  #
@@ -1,7 +1,8 @@
1
+ # lib/story_teller/command.rb
1
2
  # encoding: utf-8
2
3
  # frozen_string_literal: false
3
4
 
4
- # Copyright Nels Nelson 2008-2025 but freely usable (see license)
5
+ # Copyright Nels Nelson 2008-2026 but freely usable (see license)
5
6
  #
6
7
  # This file is part of the StoryTeller.
7
8
  #
@@ -85,6 +86,8 @@ module PublicCommandMethods
85
86
 
86
87
  def cancelled?
87
88
  return true if future.nil?
89
+ return false unless future.respond_to?(:cancelled?)
90
+
88
91
  future.cancelled?
89
92
  end
90
93
 
@@ -2,7 +2,7 @@
2
2
  # encoding: utf-8
3
3
  # frozen_string_literal: false
4
4
 
5
- # Copyright Nels Nelson 2008-2025 but freely usable (see license)
5
+ # Copyright Nels Nelson 2008-2026 but freely usable (see license)
6
6
  #
7
7
  # This file is part of the StoryTeller.
8
8
  #
@@ -34,42 +34,38 @@ end
34
34
  module Inform
35
35
  # Define Context module
36
36
  module Context
37
- module_function
38
-
39
37
  @definition = nil
40
38
 
41
- def definition
42
- @definition
43
- end
44
-
45
- alias get definition
46
-
47
39
  AttributeFieldReferenceTemplate = '@%<attribute>s'.freeze
40
+ AttributeSetterMethodTemplate = '%<attribute>s='.freeze
48
41
 
49
- def get_value(from, attribute)
50
- return from.send(attribute) if from.respond_to?(attribute)
51
- from.instance_variable_get(format(AttributeFieldReferenceTemplate, attribute: attribute).to_sym)
52
- end
42
+ class << self
43
+ attr_reader :definition
44
+ alias get definition
53
45
 
54
- AttributeSetterMethodTemplate = '%<attribute>s='.freeze
46
+ def get_value(from, attribute)
47
+ return from.send(attribute) if from.respond_to?(attribute)
48
+ from.instance_variable_get(format(AttributeFieldReferenceTemplate, attribute: attribute).to_sym)
49
+ end
55
50
 
56
- def setter_method(attribute)
57
- format(AttributeSetterMethodTemplate, attribute: attribute).to_sym
58
- end
51
+ def setter_method(attribute)
52
+ format(AttributeSetterMethodTemplate, attribute: attribute).to_sym
53
+ end
59
54
 
60
- def each_attribute(obj)
61
- @definition&.members&.each do |attribute|
62
- yield(attribute, get_value(obj, attribute))
55
+ def each_attribute(obj)
56
+ @definition&.members&.each do |attribute|
57
+ yield(attribute, get_value(obj, attribute))
58
+ end
63
59
  end
64
- end
65
60
 
66
- def set(definition)
67
- @definition = definition
68
- @definition&.members&.each do |attribute|
69
- StoryTeller::Command.send(:attr_accessor, attribute) unless StoryTeller::Command.respond_to? attribute
70
- Inform::Event.send(:attr_accessor, attribute) unless Inform::Event.respond_to? attribute
61
+ def set(definition)
62
+ @definition = definition
63
+ @definition&.members&.each do |attribute|
64
+ StoryTeller::Command.send(:attr_accessor, attribute) unless StoryTeller::Command.respond_to? attribute
65
+ Inform::Event.send(:attr_accessor, attribute) unless Inform::Event.respond_to? attribute
66
+ end
67
+ @definition
71
68
  end
72
- @definition
73
69
  end
74
70
  end
75
71
  # module Context
@@ -1,8 +1,8 @@
1
- # src/lib/daemon.rb
1
+ # lib/story_teller/daemon.rb
2
2
  # encoding: utf-8
3
3
  # frozen_string_literal: false
4
4
 
5
- # Copyright Nels Nelson 2008-2025 but freely usable (see license)
5
+ # Copyright Nels Nelson 2008-2026 but freely usable (see license)
6
6
  #
7
7
  # This file is part of the StoryTeller.
8
8
  #
@@ -2,7 +2,7 @@
2
2
  # encoding: utf-8
3
3
  # frozen_string_literal: false
4
4
 
5
- # Copyright Nels Nelson 2008-2025 but freely usable (see license)
5
+ # Copyright Nels Nelson 2008-2026 but freely usable (see license)
6
6
  #
7
7
  # This file is part of the StoryTeller.
8
8
  #
@@ -33,9 +33,7 @@ module StoryTeller
33
33
  module Library
34
34
  def play
35
35
  log.debug "Using engine-managed InformLibrary play method override"
36
- inform_library = StoryTeller::Engine.libraries[StoryTeller::Engine]
37
- inform_library.play
38
- inform_library
36
+ StoryTeller::Engine.library.tap(&:play)
39
37
  end
40
38
  end
41
39
 
@@ -45,6 +43,7 @@ module StoryTeller
45
43
  environment: 'default',
46
44
  inform6lib_gem_code_prefix: 'inform',
47
45
  language: 'English',
46
+ persist_player_location: false,
48
47
  properties: 'player actor action action_to_be ' \
49
48
  'results parameters pattern ' \
50
49
  'noun second inp1 inp2 ' \
@@ -61,6 +60,80 @@ module StoryTeller
61
60
  @libraries ||= {}
62
61
  end
63
62
 
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
+ def player_object
74
+ @player_object || parser_selfobj
75
+ end
76
+
77
+ def player_object=(object)
78
+ raise ManagedLibraryError, "player object is nil" if object.nil?
79
+
80
+ @player_object = object
81
+ replace_parser_selfobj(object)
82
+ libraries.clear
83
+ end
84
+
85
+ def library(selfobj = player_object)
86
+ return libraries[selfobj] if !selfobj.nil? && libraries.key?(selfobj)
87
+
88
+ inflib = InformLibrary.new.tap { |inflib| inflib.selfobj = selfobj }
89
+ bind_managed_library(inflib)
90
+ end
91
+
92
+ def replace_parser_selfobj(object)
93
+ return object unless defined?(Inform::Parser)
94
+
95
+ Inform::Parser.send(:remove_const, :SelfObj) if Inform::Parser.const_defined?(:SelfObj, false)
96
+ Inform::Parser.const_set(:SelfObj, object)
97
+
98
+ object
99
+ end
100
+
101
+ def bind_managed_library(inform_library)
102
+ raise ManagedLibraryError, "InformLibrary is nil" if inform_library.nil?
103
+
104
+ selfobj = inform_library.selfobj
105
+ raise ManagedLibraryError, "InformLibrary selfobj is nil" if selfobj.nil?
106
+
107
+ libraries[selfobj] = inform_library
108
+ selfobj.inflib = inform_library if selfobj.respond_to?(:inflib=)
109
+
110
+ ensure_player_location(inform_library) if persist_player_location?
111
+
112
+ inform_library
113
+ end
114
+
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)
126
+
127
+ inflib.instance_variable_set(:@location, location) unless location.nil?
128
+ end
129
+ # rubocop: enable Metrics/CyclomaticComplexity
130
+
131
+ def parser_selfobj
132
+ return nil unless defined?(Inform::Parser::SelfObj)
133
+
134
+ Inform::Parser::SelfObj
135
+ end
136
+
64
137
  def main_object=(obj)
65
138
  @main_object = obj
66
139
  end
@@ -125,22 +198,13 @@ module StoryTeller
125
198
 
126
199
  def prime_dictionary
127
200
  Inform::Object.select_map(:name).compact.each do |n|
128
- StoryTeller::Dictionary.merge(n.split(/[,\s]+/).grep_v(/[^a-z]/i).map(&:downcase).map(&:to_sym))
201
+ Array(n).join(' ').split(/[,\s]+/).grep_v(/[^a-z]/i).map(&:downcase).map(&:to_sym).each do |word|
202
+ StoryTeller::Dictionary.merge([word])
203
+ end
129
204
  end
130
205
  end
131
206
  end
132
207
  # module Engine
133
-
134
- # The StoryTeller::Privileges module to implement privilege
135
- module Privileges
136
- def admin?
137
- self.has?(:admin)
138
- end
139
-
140
- def builder?
141
- admin? || self.has?(:builder)
142
- end
143
- end
144
208
  end
145
209
  # module StoryTeller
146
210
 
@@ -2,7 +2,7 @@
2
2
  # encoding: utf-8
3
3
  # frozen_string_literal: false
4
4
 
5
- # Copyright Nels Nelson 2008-2025 but freely usable (see license)
5
+ # Copyright Nels Nelson 2008-2026 but freely usable (see license)
6
6
  #
7
7
  # This file is part of StoryTeller.
8
8
  #
@@ -113,7 +113,11 @@ module PublicEventMethods
113
113
  end
114
114
 
115
115
  def <<(event)
116
- @successors.add event
116
+ if @successors.respond_to?(:add)
117
+ @successors.add(event)
118
+ else
119
+ @successors << event
120
+ end
117
121
  event.antecedent = self
118
122
  end
119
123
 
@@ -141,6 +145,8 @@ module PublicEventMethods
141
145
 
142
146
  def cancelled?
143
147
  return true if future.nil?
148
+ return false unless future.respond_to?(:cancelled?)
149
+
144
150
  future.cancelled?
145
151
  end
146
152
 
@@ -752,6 +758,7 @@ module Inform
752
758
  Inform::Events.each(event_class) do |event|
753
759
  # Do not artificially terminate the source of an interruption.
754
760
  next if event == interruption
761
+ next unless event.future.respond_to?(:cancel)
755
762
 
756
763
  # Parameterizing Future#cancel with false is supposed to
757
764
  # abort the future without interrupting the executing thread.
@@ -2,7 +2,7 @@
2
2
  # encoding: utf-8
3
3
  # frozen_string_literal: false
4
4
 
5
- # Copyright Nels Nelson 2008-2025 but freely usable (see license)
5
+ # Copyright Nels Nelson 2008-2026 but freely usable (see license)
6
6
  #
7
7
  # This file is part of the StoryTeller.
8
8
  #
@@ -21,21 +21,6 @@
21
21
 
22
22
  # The Inform module
23
23
  module Inform
24
- # TODO: Testme
25
- # class Object
26
- # def after_initialize
27
- # super
28
- # return if new?
29
- # Inform::Behavior.attach(self)
30
- # apply_instance_behavior!
31
- # end
32
-
33
- # def after_refresh
34
- # super
35
- # apply_instance_behavior!
36
- # end
37
- # end
38
-
39
24
  # The Inform::Behavior module
40
25
  module Behavior
41
26
  class Registry < Hash; end
@@ -2,7 +2,7 @@
2
2
  # encoding: utf-8
3
3
  # frozen_string_literal: false
4
4
 
5
- # Copyright Nels Nelson 2008-2025 but freely usable (see license)
5
+ # Copyright Nels Nelson 2008-2026 but freely usable (see license)
6
6
  #
7
7
  # This file is part of StoryTeller.
8
8
  #