inform-runtime 1.0.4 → 1.2.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/README.md +10 -12
- data/Rakefile +26 -16
- data/lib/{runtime → story_teller}/articles.rb +14 -10
- data/lib/{runtime → story_teller}/builtins.rb +50 -22
- data/lib/{runtime → story_teller}/color.rb +8 -8
- data/lib/{runtime → story_teller}/command.rb +26 -28
- data/lib/{runtime → story_teller}/context.rb +23 -24
- data/lib/story_teller/core.rb +38 -0
- data/lib/{runtime → story_teller}/daemon.rb +35 -36
- data/lib/story_teller/engine.rb +151 -0
- data/lib/story_teller/ephemeral_adapter.rb +42 -0
- data/lib/{runtime → story_teller}/events.rb +8 -9
- data/lib/{runtime → story_teller}/experimental/handler_dsl.rb +7 -18
- data/lib/story_teller/experimental/reverse_engineer_class.rb +37 -0
- data/lib/{runtime → story_teller}/grammar_parser.rb +24 -40
- data/lib/{runtime → story_teller}/helpers.rb +21 -7
- data/lib/{runtime → story_teller}/history.rb +5 -5
- data/lib/{runtime → story_teller}/inflector.rb +4 -5
- data/lib/story_teller/inform/base.rb +160 -0
- data/lib/{runtime → story_teller/inform/ephemeral}/link.rb +27 -45
- data/lib/{runtime → story_teller/inform/ephemeral}/module.rb +17 -58
- data/lib/story_teller/inform/ephemeral/object.rb +329 -0
- data/lib/{runtime → story_teller/inform/ephemeral}/tag.rb +54 -81
- data/lib/story_teller/inform/models.rb +25 -0
- data/lib/{runtime → story_teller}/io.rb +10 -10
- data/lib/{runtime → story_teller}/kernel.rb +21 -31
- data/lib/story_teller/library/bootstrap.rb +66 -0
- data/lib/story_teller/library/declarations.rb +53 -0
- data/lib/story_teller/library/directives.rb +91 -0
- data/lib/story_teller/library/loader.rb +104 -0
- data/lib/story_teller/library/location.rb +73 -0
- data/lib/{runtime → story_teller}/library.rb +27 -12
- data/lib/{runtime → story_teller}/logging.rb +47 -24
- data/lib/{runtime → story_teller}/mixins.rb +6 -6
- data/lib/story_teller/model_adapter.rb +132 -0
- data/lib/{runtime → story_teller}/plurals.rb +11 -11
- data/lib/{runtime → story_teller}/prototype.rb +11 -10
- data/lib/{runtime → story_teller}/publication.rb +9 -9
- data/lib/{runtime → story_teller}/session.rb +6 -8
- data/lib/{runtime → story_teller}/stdlib.rb +13 -11
- data/lib/{runtime → story_teller}/subscription.rb +8 -8
- data/lib/{runtime → story_teller}/tree.rb +6 -6
- data/lib/{runtime → story_teller}/version.rb +16 -6
- data/lib/story_teller/world_tree.rb +54 -0
- data/lib/story_teller.rb +26 -0
- metadata +59 -99
- data/config/database.yml +0 -37
- data/exe/inform.rb +0 -6
- data/game/config.yml +0 -5
- data/game/example.inf +0 -76
- data/game/example.rb +0 -90
- data/game/forms/example_form.rb +0 -2
- data/game/grammar/game_grammar.inf.rb +0 -11
- data/game/languages/english.rb +0 -2
- data/game/models/example_model.rb +0 -2
- data/game/modules/example_module.rb +0 -9
- data/game/rules/example_state.rb +0 -2
- data/game/scripts/example_script.rb +0 -2
- data/game/topics/example_topic.rb +0 -2
- data/game/verbs/game_verbs.rb +0 -15
- data/game/verbs/metaverbs.rb +0 -2028
- data/lib/runtime/config.rb +0 -48
- data/lib/runtime/database.rb +0 -500
- data/lib/runtime/game.rb +0 -74
- data/lib/runtime/game_loader.rb +0 -132
- data/lib/runtime/library_loader.rb +0 -135
- data/lib/runtime/object.rb +0 -761
- data/lib/runtime/options.rb +0 -104
- data/lib/runtime/persistence.rb +0 -292
- data/lib/runtime/runtime.rb +0 -321
- data/lib/runtime/world_tree.rb +0 -69
- data/lib/runtime.rb +0 -35
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# lib/story_teller/library/bootstrap.rb
|
|
2
|
+
# encoding: utf-8
|
|
3
|
+
# frozen_string_literal: false
|
|
4
|
+
|
|
5
|
+
# Copyright Nels Nelson 2008-2025 but freely usable (see license)
|
|
6
|
+
#
|
|
7
|
+
# This file is part of the StoryTeller.
|
|
8
|
+
#
|
|
9
|
+
# The StoryTeller is free software: you can redistribute it and/or
|
|
10
|
+
# modify it under the terms of the GNU General Public License as published
|
|
11
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
|
12
|
+
# (at your option) any later version.
|
|
13
|
+
#
|
|
14
|
+
# The StoryTeller is distributed in the hope that it will be useful,
|
|
15
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
16
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
17
|
+
# GNU General Public License for more details.
|
|
18
|
+
#
|
|
19
|
+
# You should have received a copy of the GNU General Public License
|
|
20
|
+
# along with the StoryTeller. If not, see <http://www.gnu.org/licenses/>.
|
|
21
|
+
|
|
22
|
+
# The StoryTeller module
|
|
23
|
+
module StoryTeller
|
|
24
|
+
# The StoryTeller::Library module
|
|
25
|
+
module Library
|
|
26
|
+
# The StoryTeller::Library::Bootstrap module
|
|
27
|
+
module Bootstrap
|
|
28
|
+
module_function
|
|
29
|
+
|
|
30
|
+
def ensure_location(inflib)
|
|
31
|
+
return if inflib.nil?
|
|
32
|
+
return if inflib.location
|
|
33
|
+
|
|
34
|
+
player_obj = inflib.player
|
|
35
|
+
location = player_obj&.location
|
|
36
|
+
location ||= player_obj&.spawn_point if player_obj.respond_to?(:spawn_point)
|
|
37
|
+
inflib.instance_variable_set(:@location, location)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def set_selfobj(inflib, player)
|
|
41
|
+
inflib.selfobj = player unless player.nil?
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# rubocop: disable Metrics/MethodLength
|
|
45
|
+
def manage_inform_library(player: nil, key: StoryTeller::Engine, &block)
|
|
46
|
+
inflib = StoryTeller::Engine.libraries[key]
|
|
47
|
+
unless inflib.nil? || player.nil?
|
|
48
|
+
set_selfobj(inflib, player)
|
|
49
|
+
return inflib
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
inflib = block_given? ? block.call : InformLibrary.new
|
|
53
|
+
return nil if inflib.nil?
|
|
54
|
+
|
|
55
|
+
set_selfobj(inflib, player)
|
|
56
|
+
inflib.subscribe(inflib.selfobj)
|
|
57
|
+
ensure_location(inflib)
|
|
58
|
+
StoryTeller::Engine.libraries[key] = inflib
|
|
59
|
+
end
|
|
60
|
+
# rubocop: enable Metrics/MethodLength
|
|
61
|
+
end
|
|
62
|
+
# module Bootstrap
|
|
63
|
+
end
|
|
64
|
+
# module Library
|
|
65
|
+
end
|
|
66
|
+
# module StoryTeller
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# story/library/declarations.rb
|
|
2
|
+
# encoding: utf-8
|
|
3
|
+
# frozen_string_literal: false
|
|
4
|
+
|
|
5
|
+
# Copyright Nels Nelson 2008-2025 but freely usable (see license)
|
|
6
|
+
#
|
|
7
|
+
# This file is part of the StoryTeller.
|
|
8
|
+
#
|
|
9
|
+
# The StoryTeller is free software: you can redistribute it and/or
|
|
10
|
+
# modify it under the terms of the GNU General Public License as published
|
|
11
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
|
12
|
+
# (at your option) any later version.
|
|
13
|
+
#
|
|
14
|
+
# The StoryTeller is distributed in the hope that it will be useful,
|
|
15
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
16
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
17
|
+
# GNU General Public License for more details.
|
|
18
|
+
#
|
|
19
|
+
# You should have received a copy of the GNU General Public License
|
|
20
|
+
# along with the StoryTeller. If not, see <http://www.gnu.org/licenses/>.
|
|
21
|
+
|
|
22
|
+
# The StoryTeller module
|
|
23
|
+
module StoryTeller
|
|
24
|
+
# The StoryTeller::Library module
|
|
25
|
+
module Library
|
|
26
|
+
# The StoryTeller::Library::Declarations class
|
|
27
|
+
class Declarations
|
|
28
|
+
attr_reader :properties, :attributes, :globals
|
|
29
|
+
|
|
30
|
+
def initialize
|
|
31
|
+
reset!
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def reset!
|
|
35
|
+
@properties = Hash.new { |hash, key| hash[key] = [] }
|
|
36
|
+
@attributes = Set.new
|
|
37
|
+
@globals = []
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def add_attribute(attribute)
|
|
41
|
+
@attributes << attribute
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def add_property(property, value)
|
|
45
|
+
@properties[property] << value
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def add_global(symbol)
|
|
49
|
+
@globals << symbol
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# story/library/directives.rb
|
|
2
|
+
# encoding: utf-8
|
|
3
|
+
# frozen_string_literal: false
|
|
4
|
+
|
|
5
|
+
# Copyright Nels Nelson 2008-2025 but freely usable (see license)
|
|
6
|
+
#
|
|
7
|
+
# This file is part of the StoryTeller.
|
|
8
|
+
#
|
|
9
|
+
# The StoryTeller is free software: you can redistribute it and/or
|
|
10
|
+
# modify it under the terms of the GNU General Public License as published
|
|
11
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
|
12
|
+
# (at your option) any later version.
|
|
13
|
+
#
|
|
14
|
+
# The StoryTeller is distributed in the hope that it will be useful,
|
|
15
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
16
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
17
|
+
# GNU General Public License for more details.
|
|
18
|
+
#
|
|
19
|
+
# You should have received a copy of the GNU General Public License
|
|
20
|
+
# along with the StoryTeller. If not, see <http://www.gnu.org/licenses/>.
|
|
21
|
+
|
|
22
|
+
# The StoryTeller module
|
|
23
|
+
module StoryTeller
|
|
24
|
+
# The StoryTeller::Library module
|
|
25
|
+
module Library
|
|
26
|
+
# The StoryTeller::Library::Directives module
|
|
27
|
+
module Directives
|
|
28
|
+
InclusionGrammarGuessTemplate = '%<inclusion>s.h.inf.rb'.freeze
|
|
29
|
+
InclusionGuessesTemplate = '%<inclusion>s.h'.freeze
|
|
30
|
+
PropertyModifiers = %i[additive].freeze
|
|
31
|
+
|
|
32
|
+
module_function
|
|
33
|
+
|
|
34
|
+
def Link(link)
|
|
35
|
+
# TODO: Implement
|
|
36
|
+
# Not a high priority, because in the original Inform6 links were
|
|
37
|
+
# effectively just pointers to objects loaded in memory, and so
|
|
38
|
+
# were ephemeral in nature.
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def Include(inclusion)
|
|
42
|
+
# warn "StoryTeller::Engine.Include(#{inclusion}) from #{caller_locations(1, 5).map { |l|
|
|
43
|
+
# "#{l.path}:#{l.lineno}"
|
|
44
|
+
# }.join(' | ')}"
|
|
45
|
+
inclusion = StoryTeller::Engine.language_name if /^language__$/.match(inclusion)
|
|
46
|
+
grammar_guess = format(InclusionGrammarGuessTemplate, inclusion: inclusion)
|
|
47
|
+
guess = File.expand_path(
|
|
48
|
+
File.join(
|
|
49
|
+
StoryTeller::Library.inform_gem_lib_path,
|
|
50
|
+
StoryTeller::Engine.inform_code_prefix,
|
|
51
|
+
grammar_guess))
|
|
52
|
+
return StoryTeller::Library::Loader.load_grammar_by_path(guess) if File.exist?(guess)
|
|
53
|
+
StoryTeller::Library::Loader.require_first_existing(
|
|
54
|
+
format(InclusionGuessesTemplate, inclusion: inclusion).split)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def Attribute(attribute)
|
|
58
|
+
StoryTeller::Library.declarations.add_attribute(attribute)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def Property(*args)
|
|
62
|
+
if PropertyModifiers.include?(modifier_or_property = args.shift)
|
|
63
|
+
StoryTeller::Library.declarations.add_property(args.shift, args.shift)
|
|
64
|
+
else
|
|
65
|
+
StoryTeller::Library.declarations.add_property(modifier_or_property, args.shift)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def Default(property, value)
|
|
70
|
+
Constant(property, value)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def Constant(constant, value, target = ::Object)
|
|
74
|
+
return if constant.nil?
|
|
75
|
+
silence_warnings do
|
|
76
|
+
target.instance_eval { const_set(constant.to_sym, value) }
|
|
77
|
+
end
|
|
78
|
+
rescue StandardError => e
|
|
79
|
+
log.error "Unexpected error resetting constant #{constant}", e
|
|
80
|
+
nil
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def import_global(symbol)
|
|
84
|
+
StoryTeller::Library.declarations.add_global(symbol)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
# module Directives
|
|
88
|
+
end
|
|
89
|
+
# module Library
|
|
90
|
+
end
|
|
91
|
+
# module StoryTeller
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# lib/story_teller/library/loader.rb
|
|
2
|
+
# encoding: utf-8
|
|
3
|
+
# frozen_string_literal: false
|
|
4
|
+
|
|
5
|
+
# Copyright Nels Nelson 2008-2025 but freely usable (see license)
|
|
6
|
+
#
|
|
7
|
+
# This file is part of the StoryTeller.
|
|
8
|
+
#
|
|
9
|
+
# The StoryTeller is free software: you can redistribute it and/or
|
|
10
|
+
# modify it under the terms of the GNU General Public License as published
|
|
11
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
|
12
|
+
# (at your option) any later version.
|
|
13
|
+
#
|
|
14
|
+
# The StoryTeller is distributed in the hope that it will be useful,
|
|
15
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
16
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
17
|
+
# GNU General Public License for more details.
|
|
18
|
+
#
|
|
19
|
+
# You should have received a copy of the GNU General Public License
|
|
20
|
+
# along with the StoryTeller. If not, see <http://www.gnu.org/licenses/>.
|
|
21
|
+
|
|
22
|
+
# The StoryTeller module
|
|
23
|
+
module StoryTeller
|
|
24
|
+
# The StoryTeller::Library module
|
|
25
|
+
module Library
|
|
26
|
+
GEM_NAME = 'inform6lib'.freeze
|
|
27
|
+
GEM_PATH = Gem.loaded_specs[GEM_NAME]&.full_gem_path or raise "The #{GEM_NAME} gem is required"
|
|
28
|
+
|
|
29
|
+
class LibraryLoadError < StandardError; end
|
|
30
|
+
|
|
31
|
+
# The Library::Loader module provides methods for loading Library files.
|
|
32
|
+
module Loader
|
|
33
|
+
module_function
|
|
34
|
+
|
|
35
|
+
def augment_inform_library!
|
|
36
|
+
ensure_inform_object_model!
|
|
37
|
+
InformLibrary.extend(StoryTeller::Engine::Library)
|
|
38
|
+
InformLibrary.class_eval do
|
|
39
|
+
include Inform::Context unless include?(Inform::Context)
|
|
40
|
+
include Inform::StdLib unless include?(Inform::StdLib)
|
|
41
|
+
end
|
|
42
|
+
InformLibrary.prepend(StoryTeller::Library::Location)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def load_library
|
|
46
|
+
augment_inform_library!
|
|
47
|
+
StoryTeller::Library::Bootstrap.manage_inform_library
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def inform_object_model?
|
|
51
|
+
object_class = StoryTeller::ModelAdapter.object_class
|
|
52
|
+
return false if object_class.nil?
|
|
53
|
+
|
|
54
|
+
object_class.method_defined?(:<<) &&
|
|
55
|
+
object_class.method_defined?(:with)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def ensure_inform_object_model!
|
|
59
|
+
return if inform_object_model?
|
|
60
|
+
|
|
61
|
+
StoryTeller::EphemeralAdapter.register!
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# rubocop: disable Metrics/AbcSize
|
|
65
|
+
# rubocop: disable Metrics/MethodLength
|
|
66
|
+
def require_first_existing(guesses)
|
|
67
|
+
guessed_file_path = File.join(StoryTeller::Engine.inform_code_prefix, guesses.shift)
|
|
68
|
+
guessed_local_file_path = File.expand_path(guessed_file_path)
|
|
69
|
+
if File.exist?(guessed_local_file_path)
|
|
70
|
+
log.debug "Loading local library file: #{guessed_local_file_path}"
|
|
71
|
+
require_relative guessed_local_file_path
|
|
72
|
+
else
|
|
73
|
+
log.debug "Loading library: #{guessed_file_path}"
|
|
74
|
+
require guessed_file_path
|
|
75
|
+
end
|
|
76
|
+
rescue StandardError => e
|
|
77
|
+
log.error e.message
|
|
78
|
+
e.backtrace.each { |t| log.warn t }
|
|
79
|
+
raise e
|
|
80
|
+
rescue LoadError => e
|
|
81
|
+
log.warn e.message
|
|
82
|
+
e.backtrace.each { |t| log.warn t }
|
|
83
|
+
retry unless guesses.empty?
|
|
84
|
+
end
|
|
85
|
+
# rubocop: enable Metrics/AbcSize
|
|
86
|
+
# rubocop: enable Metrics/MethodLength
|
|
87
|
+
def load_grammar(module_name)
|
|
88
|
+
Inform::Grammar.load_by_name(module_name)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def load_grammar_by_path(module_path)
|
|
92
|
+
Inform::Grammar.load_by_path(module_path)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def unload_grammars!
|
|
96
|
+
log.debug "Unloading all grammars"
|
|
97
|
+
Inform::Grammar::Verbs.clear
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
# module Loader
|
|
101
|
+
end
|
|
102
|
+
# module Library
|
|
103
|
+
end
|
|
104
|
+
# module StoryTeller
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# lib/story_teller/library/location.rb
|
|
2
|
+
# encoding: utf-8
|
|
3
|
+
# frozen_string_literal: false
|
|
4
|
+
|
|
5
|
+
# Copyright Nels Nelson 2008-2025 but freely usable (see license)
|
|
6
|
+
#
|
|
7
|
+
# This file is part of the StoryTeller.
|
|
8
|
+
#
|
|
9
|
+
# The StoryTeller is free software: you can redistribute it and/or
|
|
10
|
+
# modify it under the terms of the GNU General Public License as published
|
|
11
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
|
12
|
+
# (at your option) any later version.
|
|
13
|
+
#
|
|
14
|
+
# The StoryTeller is distributed in the hope that it will be useful,
|
|
15
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
16
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
17
|
+
# GNU General Public License for more details.
|
|
18
|
+
#
|
|
19
|
+
# You should have received a copy of the GNU General Public License
|
|
20
|
+
# along with the StoryTeller. If not, see <http://www.gnu.org/licenses/>.
|
|
21
|
+
|
|
22
|
+
# module StoryTeller
|
|
23
|
+
module StoryTeller
|
|
24
|
+
# module Library
|
|
25
|
+
module Library
|
|
26
|
+
# module Location
|
|
27
|
+
module Location
|
|
28
|
+
def location
|
|
29
|
+
@player&.location
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def location=(obj)
|
|
33
|
+
@player.location = obj
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# module LocationInstaller
|
|
38
|
+
module LocationInstaller
|
|
39
|
+
module_function
|
|
40
|
+
|
|
41
|
+
def install!
|
|
42
|
+
return false unless defined?(InformLibrary)
|
|
43
|
+
return false if InformLibrary < StoryTeller::Library::Location
|
|
44
|
+
|
|
45
|
+
InformLibrary.prepend(StoryTeller::Library::Location)
|
|
46
|
+
true
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# module LocationTracePoint
|
|
51
|
+
module LocationTracePoint
|
|
52
|
+
module_function
|
|
53
|
+
|
|
54
|
+
def install_or_defer!
|
|
55
|
+
return true if StoryTeller::Library::LocationInstaller.install!
|
|
56
|
+
return false if defined?(@trace_point) && @trace_point&.enabled?
|
|
57
|
+
|
|
58
|
+
@trace_point = TracePoint.new(:class) do |_tp|
|
|
59
|
+
next unless defined?(InformLibrary)
|
|
60
|
+
next unless StoryTeller::Library::LocationInstaller.install!
|
|
61
|
+
|
|
62
|
+
@trace_point.disable
|
|
63
|
+
@trace_point = nil
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
@trace_point.enable
|
|
67
|
+
false
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
StoryTeller::Library::LocationTracePoint.install_or_defer!
|
|
@@ -1,31 +1,46 @@
|
|
|
1
|
+
# lib/story_teller/library.rb
|
|
1
2
|
# encoding: utf-8
|
|
2
3
|
# frozen_string_literal: false
|
|
3
4
|
|
|
4
|
-
# Copyright Nels Nelson 2008-
|
|
5
|
+
# Copyright Nels Nelson 2008-2025 but freely usable (see license)
|
|
5
6
|
#
|
|
6
|
-
# This file is part of the
|
|
7
|
+
# This file is part of the StoryTeller.
|
|
7
8
|
#
|
|
8
|
-
# The
|
|
9
|
+
# The StoryTeller is free software: you can redistribute it and/or
|
|
9
10
|
# modify it under the terms of the GNU General Public License as published
|
|
10
11
|
# by the Free Software Foundation, either version 3 of the License, or
|
|
11
12
|
# (at your option) any later version.
|
|
12
13
|
#
|
|
13
|
-
# The
|
|
14
|
+
# The StoryTeller is distributed in the hope that it will be useful,
|
|
14
15
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
15
16
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
16
17
|
# GNU General Public License for more details.
|
|
17
18
|
#
|
|
18
19
|
# You should have received a copy of the GNU General Public License
|
|
19
|
-
# along with the
|
|
20
|
+
# along with the StoryTeller. If not, see <http://www.gnu.org/licenses/>.
|
|
20
21
|
|
|
21
|
-
require_relative '
|
|
22
|
+
require_relative 'library/bootstrap'
|
|
23
|
+
require_relative 'library/declarations'
|
|
24
|
+
require_relative 'library/directives'
|
|
25
|
+
require_relative 'library/loader'
|
|
26
|
+
require_relative 'library/location'
|
|
22
27
|
|
|
23
|
-
# The
|
|
24
|
-
module
|
|
28
|
+
# The StoryTeller module
|
|
29
|
+
module StoryTeller
|
|
25
30
|
# The Library module
|
|
26
31
|
module Library
|
|
27
32
|
@methods_index = []
|
|
28
33
|
|
|
34
|
+
def inform_gem_lib_path
|
|
35
|
+
@inform_gem_lib_path ||= File.expand_path(File.join(StoryTeller::Library::GEM_PATH, 'lib'))
|
|
36
|
+
end
|
|
37
|
+
module_function :inform_gem_lib_path
|
|
38
|
+
|
|
39
|
+
def declarations
|
|
40
|
+
@declarations ||= Declarations.new
|
|
41
|
+
end
|
|
42
|
+
module_function :declarations
|
|
43
|
+
|
|
29
44
|
def methods_index
|
|
30
45
|
return @methods_index unless @methods_index.empty?
|
|
31
46
|
load_library_methods
|
|
@@ -39,9 +54,9 @@ module Inform
|
|
|
39
54
|
# rubocop: disable Metrics/MethodLength
|
|
40
55
|
def load_library_methods
|
|
41
56
|
library_methods = Set.new
|
|
42
|
-
library_methods.merge(StdLib.instance_methods(false))
|
|
43
|
-
library_methods.merge(
|
|
44
|
-
library_methods.merge(
|
|
57
|
+
library_methods.merge(Inform::StdLib.instance_methods(false))
|
|
58
|
+
library_methods.merge(StoryTeller::IO.instance_methods(false))
|
|
59
|
+
library_methods.merge(StoryTeller.instance_methods(false))
|
|
45
60
|
library_methods.merge(InformLibrary.instance_methods(false))
|
|
46
61
|
Inform.included_modules.each do |mod|
|
|
47
62
|
library_methods.merge(mod.instance_methods(false))
|
|
@@ -50,7 +65,7 @@ module Inform
|
|
|
50
65
|
library_methods.merge(mod.instance_methods(false))
|
|
51
66
|
end
|
|
52
67
|
@methods_index.concat(library_methods.to_a).sort
|
|
53
|
-
log.
|
|
68
|
+
log.trace "Loaded library methods: #{@methods_index}"
|
|
54
69
|
end
|
|
55
70
|
# rubocop: enable Metrics/AbcSize
|
|
56
71
|
# rubocop: enable Metrics/MethodLength
|
|
@@ -1,22 +1,23 @@
|
|
|
1
|
+
# lib/story_teller/logging.rb
|
|
1
2
|
# encoding: utf-8
|
|
2
3
|
# frozen_string_literal: false
|
|
3
4
|
|
|
4
|
-
# Copyright Nels Nelson 2008-
|
|
5
|
+
# Copyright Nels Nelson 2008-2025 but freely usable (see license)
|
|
5
6
|
#
|
|
6
|
-
# This file is part of
|
|
7
|
+
# This file is part of StoryTeller.
|
|
7
8
|
#
|
|
8
|
-
#
|
|
9
|
+
# StoryTeller is free software: you can redistribute it and/or
|
|
9
10
|
# modify it under the terms of the GNU General Public License as published
|
|
10
11
|
# by the Free Software Foundation, either version 3 of the License, or
|
|
11
12
|
# (at your option) any later version.
|
|
12
13
|
#
|
|
13
|
-
#
|
|
14
|
+
# StoryTeller is distributed in the hope that it will be useful,
|
|
14
15
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
15
16
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
16
17
|
# GNU General Public License for more details.
|
|
17
18
|
#
|
|
18
19
|
# You should have received a copy of the GNU General Public License
|
|
19
|
-
# along with
|
|
20
|
+
# along with StoryTeller. If not, see <http://www.gnu.org/licenses/>.
|
|
20
21
|
|
|
21
22
|
require 'fileutils'
|
|
22
23
|
require 'logger'
|
|
@@ -82,15 +83,26 @@ end
|
|
|
82
83
|
# implicit backtrace printing
|
|
83
84
|
# TODO: Figure out if this is actually useful.
|
|
84
85
|
class Logger
|
|
86
|
+
TRACE = DEBUG - 1 unless const_defined?(:TRACE)
|
|
87
|
+
|
|
85
88
|
include LoggerHelpers
|
|
86
89
|
|
|
87
90
|
alias original_error error
|
|
91
|
+
|
|
88
92
|
def error(error_or_message, error = nil)
|
|
89
93
|
warn error_or_message
|
|
90
94
|
return extract_backtrace(error_or_message) if error.nil?
|
|
91
95
|
original_error(generate_message(error_or_message, error))
|
|
92
96
|
extract_backtrace(original_error(error))
|
|
93
97
|
end
|
|
98
|
+
|
|
99
|
+
def trace(progname = nil, &block)
|
|
100
|
+
add(TRACE, nil, progname, &block)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def trace?
|
|
104
|
+
@level <= TRACE
|
|
105
|
+
end
|
|
94
106
|
end
|
|
95
107
|
|
|
96
108
|
# The Logging module
|
|
@@ -100,6 +112,18 @@ module Logging
|
|
|
100
112
|
java_import Java::org.apache.logging.log4j.LogManager
|
|
101
113
|
end
|
|
102
114
|
|
|
115
|
+
RubyLogLevels = {
|
|
116
|
+
all: -Float::INFINITY,
|
|
117
|
+
trace: Logger::TRACE,
|
|
118
|
+
debug: Logger::DEBUG,
|
|
119
|
+
info: Logger::INFO,
|
|
120
|
+
warn: Logger::WARN,
|
|
121
|
+
error: Logger::ERROR,
|
|
122
|
+
fatal: Logger::FATAL,
|
|
123
|
+
unknown: Logger::UNKNOWN,
|
|
124
|
+
off: Logger::UNKNOWN + 1
|
|
125
|
+
}.freeze
|
|
126
|
+
|
|
103
127
|
def init_logger(level = :info, logger_name = nil)
|
|
104
128
|
return init_java_logger(level, logger_name, caller[2]) if defined?(Java)
|
|
105
129
|
init_ruby_logger(level, logger_name, caller[2])
|
|
@@ -118,7 +142,7 @@ module Logging
|
|
|
118
142
|
logger_name = get_formatted_logger_name(logger_name)
|
|
119
143
|
logger_name = source_location.split(ForwardSlashPattern).last if logger_name.empty?
|
|
120
144
|
log = Logger.new($stdout, progname: logger_name)
|
|
121
|
-
log.level = level
|
|
145
|
+
log.level = normalize_ruby_log_level(level) unless level.nil?
|
|
122
146
|
log.formatter = method(:ruby_log_formatter)
|
|
123
147
|
log
|
|
124
148
|
end
|
|
@@ -131,6 +155,14 @@ module Logging
|
|
|
131
155
|
log
|
|
132
156
|
end
|
|
133
157
|
|
|
158
|
+
def normalize_ruby_log_level(level)
|
|
159
|
+
return level if level.is_a?(Integer)
|
|
160
|
+
|
|
161
|
+
RubyLogLevels.fetch(level.to_sym) do
|
|
162
|
+
raise ArgumentError, "Unknown Ruby log level: #{level.inspect}"
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
134
166
|
def get_formatted_logger_name(logger_name = nil)
|
|
135
167
|
return logger_name.to_s[/\w+$/] unless logger_name.nil?
|
|
136
168
|
return name[/\w+$/] if is_a?(Class) || is_a?(Module)
|
|
@@ -162,7 +194,10 @@ module Logging
|
|
|
162
194
|
# rubocop: enable Metrics/CyclomaticComplexity
|
|
163
195
|
|
|
164
196
|
def log_level=(level)
|
|
165
|
-
|
|
197
|
+
raise "Parameter level may not be nil" if level.nil?
|
|
198
|
+
normalized_level = symbolize_numeric_log_level(level)
|
|
199
|
+
|
|
200
|
+
Logging.config[:level] = normalized_level
|
|
166
201
|
end
|
|
167
202
|
module_function :log_level=
|
|
168
203
|
|
|
@@ -178,20 +213,8 @@ module Logging
|
|
|
178
213
|
end
|
|
179
214
|
# module Logging
|
|
180
215
|
|
|
181
|
-
#
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
# The Class class
|
|
188
|
-
class Class
|
|
189
|
-
# Universally include Logging
|
|
190
|
-
include ::Logging
|
|
191
|
-
end
|
|
192
|
-
|
|
193
|
-
# The Object class
|
|
194
|
-
class Object
|
|
195
|
-
# Universally include Logging
|
|
196
|
-
include ::Logging
|
|
197
|
-
end
|
|
216
|
+
# Make logging universally available
|
|
217
|
+
# Yeah, yeah, I know this is a "bad idea". Too bad.
|
|
218
|
+
# Logging should be a universal runtime facility, period.
|
|
219
|
+
# The fact that it isn't is an absurdity to me.
|
|
220
|
+
Object.include(Logging)
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
2
|
# frozen_string_literal: false
|
|
3
3
|
|
|
4
|
-
# Copyright Nels Nelson 2008-
|
|
4
|
+
# Copyright Nels Nelson 2008-2025 but freely usable (see license)
|
|
5
5
|
#
|
|
6
|
-
# This file is part of
|
|
6
|
+
# This file is part of StoryTeller.
|
|
7
7
|
#
|
|
8
|
-
#
|
|
8
|
+
# StoryTeller is free software: you can redistribute it and/or
|
|
9
9
|
# modify it under the terms of the GNU General Public License as published
|
|
10
10
|
# by the Free Software Foundation, either version 3 of the License, or
|
|
11
11
|
# (at your option) any later version.
|
|
12
12
|
#
|
|
13
|
-
#
|
|
13
|
+
# StoryTeller is distributed in the hope that it will be useful,
|
|
14
14
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
15
15
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
16
16
|
# GNU General Public License for more details.
|
|
17
17
|
#
|
|
18
18
|
# You should have received a copy of the GNU General Public License
|
|
19
|
-
# along with
|
|
19
|
+
# along with StoryTeller. If not, see <http://www.gnu.org/licenses/>.
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
JoinedTemplate = '%<str>s%<other>s'.freeze
|
|
@@ -501,7 +501,7 @@ class Array
|
|
|
501
501
|
def to_s(separator = CommaSpaceString)
|
|
502
502
|
# This will make it possible to print Lists nicely, but not screw up
|
|
503
503
|
# the behavior of the List.
|
|
504
|
-
|
|
504
|
+
self.join(separator)
|
|
505
505
|
end
|
|
506
506
|
|
|
507
507
|
alias random sample
|