glimmer 1.0.5 → 1.0.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +22 -0
- data/LICENSE.txt +1 -1
- data/PROCESS.md +2 -2
- data/README.md +381 -224
- data/VERSION +1 -1
- data/glimmer.gemspec +8 -7
- data/lib/glimmer.rb +14 -5
- data/lib/glimmer/config.rb +6 -6
- data/lib/glimmer/data_binding/model_binding.rb +7 -7
- data/lib/glimmer/data_binding/observable.rb +4 -4
- data/lib/glimmer/data_binding/observable_array.rb +6 -6
- data/lib/glimmer/data_binding/observable_model.rb +7 -7
- data/lib/glimmer/data_binding/observer.rb +4 -3
- data/lib/glimmer/dsl/engine.rb +28 -25
- data/lib/glimmer/dsl/expression.rb +1 -1
- data/lib/glimmer/dsl/expression_handler.rb +4 -4
- data/lib/glimmer/dsl/parent_expression.rb +4 -4
- data/lib/glimmer/dsl/static_expression.rb +6 -6
- data/lib/glimmer/dsl/top_level_expression.rb +4 -4
- data/lib/glimmer/error.rb +4 -4
- data/lib/glimmer/invalid_keyword_error.rb +4 -4
- metadata +30 -11
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0.
|
1
|
+
1.0.10
|
data/glimmer.gemspec
CHANGED
@@ -2,20 +2,19 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: glimmer 1.0.
|
5
|
+
# stub: glimmer 1.0.10 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "glimmer".freeze
|
9
|
-
s.version = "1.0.
|
9
|
+
s.version = "1.0.10"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib".freeze]
|
13
13
|
s.authors = ["AndyMaleh".freeze]
|
14
|
-
s.date = "
|
15
|
-
s.description = "Glimmer is a Ruby DSL Framework consisting of a DSL Engine and Observable/Observer/Data-Binding Library. Used in the Glimmer DSL for SWT (JRuby Desktop Development GUI
|
14
|
+
s.date = "2021-01-25"
|
15
|
+
s.description = "Glimmer is a Ruby DSL Framework consisting of a DSL Engine and an Observable/Observer/Data-Binding Library. Used in the Glimmer DSL for SWT (JRuby Desktop Development GUI Framework), the Glimmer DSL for Tk (Ruby Desktop Development GUI Library), the Glimmer DSL for Opal (Pure Ruby Web GUI and Auto-Webifier of Desktop Apps), the Glimmer DSL for XML (& HTML), and the Glimmer DSL for CSS.".freeze
|
16
16
|
s.email = "andy.am@gmail.com".freeze
|
17
17
|
s.extra_rdoc_files = [
|
18
|
-
"CHANGELOG.md",
|
19
18
|
"LICENSE.txt",
|
20
19
|
"README.md"
|
21
20
|
]
|
@@ -55,26 +54,28 @@ Gem::Specification.new do |s|
|
|
55
54
|
if s.respond_to? :add_runtime_dependency then
|
56
55
|
s.add_runtime_dependency(%q<array_include_methods>.freeze, [">= 1.0.4", "< 2.0.0"])
|
57
56
|
s.add_runtime_dependency(%q<facets>.freeze, [">= 3.1.0", "< 4.0.0"])
|
57
|
+
s.add_runtime_dependency(%q<concurrent-ruby>.freeze, [">= 1.1.7", "< 2.0.0"])
|
58
58
|
s.add_development_dependency(%q<rspec-mocks>.freeze, ["~> 3.5.0"])
|
59
59
|
s.add_development_dependency(%q<rspec>.freeze, ["~> 3.5.0"])
|
60
60
|
s.add_development_dependency(%q<puts_debuggerer>.freeze, ["~> 0.10.0"])
|
61
61
|
s.add_development_dependency(%q<rake>.freeze, [">= 10.1.0", "< 14.0.0"])
|
62
62
|
s.add_development_dependency(%q<jeweler>.freeze, [">= 2.0.0", "< 3.0.0"])
|
63
63
|
s.add_development_dependency(%q<rdoc>.freeze, [">= 6.2.1", "< 7.0.0"])
|
64
|
-
s.add_development_dependency(%q<coveralls>.freeze, ["
|
64
|
+
s.add_development_dependency(%q<coveralls>.freeze, [">= 0"])
|
65
65
|
s.add_development_dependency(%q<simplecov>.freeze, ["~> 0.16.1"])
|
66
66
|
s.add_development_dependency(%q<simplecov-lcov>.freeze, ["~> 0.7.0"])
|
67
67
|
s.add_development_dependency(%q<rake-tui>.freeze, [">= 0"])
|
68
68
|
else
|
69
69
|
s.add_dependency(%q<array_include_methods>.freeze, [">= 1.0.4", "< 2.0.0"])
|
70
70
|
s.add_dependency(%q<facets>.freeze, [">= 3.1.0", "< 4.0.0"])
|
71
|
+
s.add_dependency(%q<concurrent-ruby>.freeze, [">= 1.1.7", "< 2.0.0"])
|
71
72
|
s.add_dependency(%q<rspec-mocks>.freeze, ["~> 3.5.0"])
|
72
73
|
s.add_dependency(%q<rspec>.freeze, ["~> 3.5.0"])
|
73
74
|
s.add_dependency(%q<puts_debuggerer>.freeze, ["~> 0.10.0"])
|
74
75
|
s.add_dependency(%q<rake>.freeze, [">= 10.1.0", "< 14.0.0"])
|
75
76
|
s.add_dependency(%q<jeweler>.freeze, [">= 2.0.0", "< 3.0.0"])
|
76
77
|
s.add_dependency(%q<rdoc>.freeze, [">= 6.2.1", "< 7.0.0"])
|
77
|
-
s.add_dependency(%q<coveralls>.freeze, ["
|
78
|
+
s.add_dependency(%q<coveralls>.freeze, [">= 0"])
|
78
79
|
s.add_dependency(%q<simplecov>.freeze, ["~> 0.16.1"])
|
79
80
|
s.add_dependency(%q<simplecov-lcov>.freeze, ["~> 0.7.0"])
|
80
81
|
s.add_dependency(%q<rake-tui>.freeze, [">= 0"])
|
data/lib/glimmer.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
# Copyright (c) 2007-
|
2
|
-
#
|
1
|
+
# Copyright (c) 2007-2021 Andy Maleh
|
2
|
+
#
|
3
3
|
# Permission is hereby granted, free of charge, to any person obtaining
|
4
4
|
# a copy of this software and associated documentation files (the
|
5
5
|
# "Software"), to deal in the Software without restriction, including
|
@@ -7,10 +7,10 @@
|
|
7
7
|
# distribute, sublicense, and/or sell copies of the Software, and to
|
8
8
|
# permit persons to whom the Software is furnished to do so, subject to
|
9
9
|
# the following conditions:
|
10
|
-
#
|
10
|
+
#
|
11
11
|
# The above copyright notice and this permission notice shall be
|
12
12
|
# included in all copies or substantial portions of the Software.
|
13
|
-
#
|
13
|
+
#
|
14
14
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
15
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
16
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
@@ -22,6 +22,15 @@
|
|
22
22
|
require 'logger'
|
23
23
|
require 'set'
|
24
24
|
require 'array_include_methods'
|
25
|
+
if RUBY_ENGINE == 'opal'
|
26
|
+
module Concurrent
|
27
|
+
Array = ::Array
|
28
|
+
Hash = ::Hash
|
29
|
+
Set = ::Set
|
30
|
+
end
|
31
|
+
else
|
32
|
+
require 'concurrent-ruby'
|
33
|
+
end
|
25
34
|
|
26
35
|
$LOAD_PATH.unshift(File.expand_path('..', __FILE__))
|
27
36
|
|
@@ -70,7 +79,7 @@ module Glimmer
|
|
70
79
|
end
|
71
80
|
Glimmer.loop_last_data = new_loop_data
|
72
81
|
Glimmer::Config.logger.info {"Interpreting keyword: #{method_symbol}"}
|
73
|
-
Glimmer::DSL::Engine.interpret(method_symbol, *args, &block)
|
82
|
+
Glimmer::DSL::Engine.interpret(method_symbol, *args, &block)
|
74
83
|
end
|
75
84
|
rescue InvalidKeywordError => e
|
76
85
|
Glimmer::Config.logger.error {"Encountered an invalid keyword at this object: #{self}"}
|
data/lib/glimmer/config.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
# Copyright (c) 2007-
|
2
|
-
#
|
1
|
+
# Copyright (c) 2007-2021 Andy Maleh
|
2
|
+
#
|
3
3
|
# Permission is hereby granted, free of charge, to any person obtaining
|
4
4
|
# a copy of this software and associated documentation files (the
|
5
5
|
# "Software"), to deal in the Software without restriction, including
|
@@ -7,10 +7,10 @@
|
|
7
7
|
# distribute, sublicense, and/or sell copies of the Software, and to
|
8
8
|
# permit persons to whom the Software is furnished to do so, subject to
|
9
9
|
# the following conditions:
|
10
|
-
#
|
10
|
+
#
|
11
11
|
# The above copyright notice and this permission notice shall be
|
12
12
|
# included in all copies or substantial portions of the Software.
|
13
|
-
#
|
13
|
+
#
|
14
14
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
15
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
16
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
@@ -46,7 +46,7 @@ module Glimmer
|
|
46
46
|
end
|
47
47
|
|
48
48
|
# Returns Glimmer logger (standard Ruby logger)
|
49
|
-
def logger
|
49
|
+
def logger
|
50
50
|
reset_logger! unless defined? @@logger
|
51
51
|
@@logger
|
52
52
|
end
|
@@ -56,7 +56,7 @@ module Glimmer
|
|
56
56
|
end
|
57
57
|
|
58
58
|
def reset_logger!
|
59
|
-
self.logger = Logger.new(STDOUT).tap do |logger|
|
59
|
+
self.logger = Logger.new(STDOUT).tap do |logger|
|
60
60
|
logger.level = Logger::ERROR
|
61
61
|
begin
|
62
62
|
logger.level = ENV['GLIMMER_LOGGER_LEVEL'].strip.downcase if ENV['GLIMMER_LOGGER_LEVEL']
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (c) 2007-
|
1
|
+
# Copyright (c) 2007-2021 Andy Maleh
|
2
2
|
#
|
3
3
|
# Permission is hereby granted, free of charge, to any person obtaining
|
4
4
|
# a copy of this software and associated documentation files (the
|
@@ -33,7 +33,7 @@ module Glimmer
|
|
33
33
|
def initialize(base_model, property_name_expression, binding_options = nil)
|
34
34
|
@base_model = base_model
|
35
35
|
@property_name_expression = property_name_expression
|
36
|
-
@binding_options = binding_options ||
|
36
|
+
@binding_options = binding_options || Concurrent::Hash.new
|
37
37
|
if computed?
|
38
38
|
@computed_model_bindings = computed_by.map do |computed_by_property_expression|
|
39
39
|
self.class.new(base_model, computed_by_property_expression)
|
@@ -120,9 +120,9 @@ module Glimmer
|
|
120
120
|
end
|
121
121
|
|
122
122
|
def nested_property_observers_for(observer)
|
123
|
-
@nested_property_observers_collection ||=
|
123
|
+
@nested_property_observers_collection ||= Concurrent::Hash.new
|
124
124
|
unless @nested_property_observers_collection.has_key?(observer)
|
125
|
-
@nested_property_observers_collection[observer] = nested_property_names.reduce(
|
125
|
+
@nested_property_observers_collection[observer] = nested_property_names.reduce(Concurrent::Hash.new) do |output, property_name|
|
126
126
|
output.merge(
|
127
127
|
property_name => Observer.proc do |new_value|
|
128
128
|
# Ensure reattaching observers when a higher level nested property is updated (e.g. person.address changes reattaches person.address.street observer)
|
@@ -164,7 +164,7 @@ module Glimmer
|
|
164
164
|
end
|
165
165
|
|
166
166
|
def computed_observer_for(observer)
|
167
|
-
@computed_observer_collection ||=
|
167
|
+
@computed_observer_collection ||= Concurrent::Hash.new
|
168
168
|
unless @computed_observer_collection.has_key?(observer)
|
169
169
|
@computed_observer_collection[observer] = Observer.proc do |new_value|
|
170
170
|
observer.call(evaluate_property)
|
@@ -209,7 +209,7 @@ module Glimmer
|
|
209
209
|
def call(value)
|
210
210
|
return if model.nil?
|
211
211
|
converted_value = value
|
212
|
-
invoke_property_writer(model, "#{property_name}=", converted_value) unless
|
212
|
+
invoke_property_writer(model, "#{property_name}=", converted_value) unless converted_value == evaluate_property
|
213
213
|
end
|
214
214
|
|
215
215
|
def evaluate_property
|
@@ -242,7 +242,7 @@ module Glimmer
|
|
242
242
|
end
|
243
243
|
|
244
244
|
def invoke_property_writer(object, property_expression, value)
|
245
|
-
|
245
|
+
raise "Cannot invoke `#{property_expression}` because ModelBinding#binding_options[:read_only]=true" if @binding_options[:read_only]
|
246
246
|
value = convert_on_write(value)
|
247
247
|
if property_indexed?(property_expression)
|
248
248
|
property_method = '[]='
|
@@ -1,5 +1,5 @@
|
|
1
|
-
# Copyright (c) 2007-
|
2
|
-
#
|
1
|
+
# Copyright (c) 2007-2021 Andy Maleh
|
2
|
+
#
|
3
3
|
# Permission is hereby granted, free of charge, to any person obtaining
|
4
4
|
# a copy of this software and associated documentation files (the
|
5
5
|
# "Software"), to deal in the Software without restriction, including
|
@@ -7,10 +7,10 @@
|
|
7
7
|
# distribute, sublicense, and/or sell copies of the Software, and to
|
8
8
|
# permit persons to whom the Software is furnished to do so, subject to
|
9
9
|
# the following conditions:
|
10
|
-
#
|
10
|
+
#
|
11
11
|
# The above copyright notice and this permission notice shall be
|
12
12
|
# included in all copies or substantial portions of the Software.
|
13
|
-
#
|
13
|
+
#
|
14
14
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
15
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
16
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (c) 2007-
|
1
|
+
# Copyright (c) 2007-2021 Andy Maleh
|
2
2
|
#
|
3
3
|
# Permission is hereby granted, free of charge, to any person obtaining
|
4
4
|
# a copy of this software and associated documentation files (the
|
@@ -34,7 +34,7 @@ module Glimmer
|
|
34
34
|
element_properties = element_properties.flatten.compact.uniq
|
35
35
|
return observer if has_observer?(observer) && has_observer_element_properties?(observer, element_properties)
|
36
36
|
property_observer_list << observer
|
37
|
-
observer_element_properties[observer] = element_properties_for(observer) + Set.new(element_properties)
|
37
|
+
observer_element_properties[observer] = element_properties_for(observer) + Concurrent::Set.new(element_properties)
|
38
38
|
each { |element| add_element_observer(element, observer) }
|
39
39
|
observer
|
40
40
|
end
|
@@ -55,7 +55,7 @@ module Glimmer
|
|
55
55
|
element_properties = element_properties.flatten.compact.uniq
|
56
56
|
if !element_properties.empty?
|
57
57
|
old_element_properties = element_properties_for(observer)
|
58
|
-
observer_element_properties[observer] = element_properties_for(observer) - Set.new(element_properties)
|
58
|
+
observer_element_properties[observer] = element_properties_for(observer) - Concurrent::Set.new(element_properties)
|
59
59
|
each { |element| element_properties.each { |property| observer.unobserve(element, property) } }
|
60
60
|
end
|
61
61
|
if element_properties_for(observer).empty?
|
@@ -87,15 +87,15 @@ module Glimmer
|
|
87
87
|
end
|
88
88
|
|
89
89
|
def property_observer_list
|
90
|
-
@property_observer_list ||= Set.new
|
90
|
+
@property_observer_list ||= Concurrent::Set.new
|
91
91
|
end
|
92
92
|
|
93
93
|
def observer_element_properties
|
94
|
-
@observer_element_properties ||=
|
94
|
+
@observer_element_properties ||= Concurrent::Hash.new
|
95
95
|
end
|
96
96
|
|
97
97
|
def element_properties_for(observer)
|
98
|
-
observer_element_properties[observer] ||= Set.new
|
98
|
+
observer_element_properties[observer] ||= Concurrent::Set.new
|
99
99
|
end
|
100
100
|
|
101
101
|
def notify_observers
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (c) 2007-
|
1
|
+
# Copyright (c) 2007-2021 Andy Maleh
|
2
2
|
#
|
3
3
|
# Permission is hereby granted, free of charge, to any person obtaining
|
4
4
|
# a copy of this software and associated documentation files (the
|
@@ -43,7 +43,7 @@ module Glimmer
|
|
43
43
|
lambda do |value|
|
44
44
|
old_value = self.send(property_name)
|
45
45
|
unregister_dependent_observers(property_name, old_value)
|
46
|
-
self.send("
|
46
|
+
self.send("__original__#{property_writer_name}", value)
|
47
47
|
notify_observers(property_name)
|
48
48
|
ensure_array_object_observer(property_name, value, old_value)
|
49
49
|
end
|
@@ -92,7 +92,7 @@ module Glimmer
|
|
92
92
|
end
|
93
93
|
|
94
94
|
def property_observer_list(property_name)
|
95
|
-
property_observer_hash[property_name.to_sym] = Set.new unless property_observer_hash[property_name.to_sym]
|
95
|
+
property_observer_hash[property_name.to_sym] = Concurrent::Set.new unless property_observer_hash[property_name.to_sym]
|
96
96
|
property_observer_hash[property_name.to_sym]
|
97
97
|
end
|
98
98
|
|
@@ -105,9 +105,9 @@ module Glimmer
|
|
105
105
|
method(property_writer_name)
|
106
106
|
ensure_array_object_observer(property_name, send(property_name))
|
107
107
|
begin
|
108
|
-
method("
|
108
|
+
method("__original__#{property_writer_name}")
|
109
109
|
rescue
|
110
|
-
define_singleton_method("
|
110
|
+
define_singleton_method("__original__#{property_writer_name}", property_writer_method(property_writer_name))
|
111
111
|
define_singleton_method(property_writer_name, &PROPERTY_WRITER_FACTORY.call(property_name))
|
112
112
|
end
|
113
113
|
rescue => e
|
@@ -126,7 +126,7 @@ module Glimmer
|
|
126
126
|
end
|
127
127
|
|
128
128
|
def ensure_array_object_observer(property_name, object, old_object = nil)
|
129
|
-
return unless object
|
129
|
+
return unless object&.is_a?(Array)
|
130
130
|
array_object_observer = array_object_observer_for(property_name)
|
131
131
|
array_observer_registration = array_object_observer.observe(object)
|
132
132
|
property_observer_list(property_name).each do |observer|
|
@@ -137,7 +137,7 @@ module Glimmer
|
|
137
137
|
end
|
138
138
|
|
139
139
|
def array_object_observer_for(property_name)
|
140
|
-
@array_object_observers ||=
|
140
|
+
@array_object_observers ||= Concurrent::Hash.new
|
141
141
|
@array_object_observers[property_name] = ObservableModel::Notifier.new(self, property_name) unless @array_object_observers.has_key?(property_name)
|
142
142
|
@array_object_observers[property_name]
|
143
143
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (c) 2007-
|
1
|
+
# Copyright (c) 2007-2021 Andy Maleh
|
2
2
|
#
|
3
3
|
# Permission is hereby granted, free of charge, to any person obtaining
|
4
4
|
# a copy of this software and associated documentation files (the
|
@@ -51,6 +51,7 @@ module Glimmer
|
|
51
51
|
observer.unobserve(observable, property)
|
52
52
|
end
|
53
53
|
alias unobserve unregister
|
54
|
+
alias deregister unregister
|
54
55
|
end
|
55
56
|
|
56
57
|
class << self
|
@@ -60,7 +61,7 @@ module Glimmer
|
|
60
61
|
end
|
61
62
|
|
62
63
|
def registrations
|
63
|
-
@registrations ||= Set.new
|
64
|
+
@registrations ||= Concurrent::Set.new
|
64
65
|
end
|
65
66
|
|
66
67
|
def registration_for(observable, property = nil)
|
@@ -74,7 +75,7 @@ module Glimmer
|
|
74
75
|
end
|
75
76
|
|
76
77
|
def dependents_for(registration)
|
77
|
-
dependents[registration] ||= Set.new
|
78
|
+
dependents[registration] ||= Concurrent::Set.new
|
78
79
|
end
|
79
80
|
|
80
81
|
# registers observer in an observable on a property (optional)
|
data/lib/glimmer/dsl/engine.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
# Copyright (c) 2007-
|
2
|
-
#
|
1
|
+
# Copyright (c) 2007-2021 Andy Maleh
|
2
|
+
#
|
3
3
|
# Permission is hereby granted, free of charge, to any person obtaining
|
4
4
|
# a copy of this software and associated documentation files (the
|
5
5
|
# "Software"), to deal in the Software without restriction, including
|
@@ -7,10 +7,10 @@
|
|
7
7
|
# distribute, sublicense, and/or sell copies of the Software, and to
|
8
8
|
# permit persons to whom the Software is furnished to do so, subject to
|
9
9
|
# the following conditions:
|
10
|
-
#
|
10
|
+
#
|
11
11
|
# The above copyright notice and this permission notice shall be
|
12
12
|
# included in all copies or substantial portions of the Software.
|
13
|
-
#
|
13
|
+
#
|
14
14
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
15
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
16
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
@@ -28,7 +28,7 @@ module Glimmer
|
|
28
28
|
module DSL
|
29
29
|
# Glimmer DSL Engine
|
30
30
|
#
|
31
|
-
# Follows Interpreter
|
31
|
+
# Follows Interpreter, Chain of Responsibility, and Singleton Design Patterns
|
32
32
|
#
|
33
33
|
# When DSL engine interprets an expression, it attempts to handle
|
34
34
|
# with ordered expression array specified via `.expressions=` method.
|
@@ -37,10 +37,11 @@ module Glimmer
|
|
37
37
|
STATIC_EXPRESSION_METHOD_FACTORY = lambda do |keyword|
|
38
38
|
lambda do |*args, &block|
|
39
39
|
if Glimmer::DSL::Engine.no_dsls?
|
40
|
-
puts Glimmer::DSL::Engine::MESSAGE_NO_DSLS
|
40
|
+
puts Glimmer::DSL::Engine::MESSAGE_NO_DSLS # TODO consider switching to an error log statement
|
41
41
|
else
|
42
42
|
retrieved_static_expression = Glimmer::DSL::Engine.static_expressions[keyword][Glimmer::DSL::Engine.dsl]
|
43
|
-
|
43
|
+
# TODO consider replacing Glimmer::DSL::Engine.static_expressions[keyword].keys - Glimmer::DSL::Engine.disabled_dsls with Glimmer::DSL::Engine.enabled_static_expression_dsls(keyword)
|
44
|
+
static_expression_dsl = (Glimmer::DSL::Engine.static_expressions[keyword].keys - Glimmer::DSL::Engine.disabled_dsls).first
|
44
45
|
interpretation = nil
|
45
46
|
if retrieved_static_expression.nil? && Glimmer::DSL::Engine.dsl && (static_expression_dsl.nil? || !Glimmer::DSL::Engine.static_expressions[keyword][static_expression_dsl].is_a?(TopLevelExpression))
|
46
47
|
begin
|
@@ -51,19 +52,20 @@ module Glimmer
|
|
51
52
|
end
|
52
53
|
if interpretation
|
53
54
|
interpretation
|
54
|
-
else
|
55
|
+
else
|
55
56
|
raise Glimmer::Error, "Unsupported keyword: #{keyword}" unless static_expression_dsl || retrieved_static_expression
|
56
57
|
Glimmer::DSL::Engine.dsl_stack.push(static_expression_dsl || Glimmer::DSL::Engine.dsl)
|
57
58
|
static_expression = Glimmer::DSL::Engine.static_expressions[keyword][Glimmer::DSL::Engine.dsl]
|
58
|
-
|
59
|
-
|
59
|
+
static_expression_can_interpret = nil
|
60
|
+
if static_expression.nil? || !(static_expression_can_interpret = static_expression.can_interpret?(Glimmer::DSL::Engine.parent, keyword, *args, &block))
|
61
|
+
raise Error, "Invalid use of Glimmer keyword #{keyword} with args #{args} under parent #{Glimmer::DSL::Engine.parent.inspect} with DSL #{Glimmer::DSL::Engine.dsl.inspect} and static expression #{static_expression.inspect} having can_interpret? as #{static_expression_can_interpret.inspect}"
|
60
62
|
else
|
61
63
|
Glimmer::Config.logger.info {"#{static_expression.class.name} will handle expression keyword #{keyword}"}
|
62
64
|
Glimmer::DSL::Engine.interpret_expression(static_expression, keyword, *args, &block)
|
63
65
|
end
|
64
66
|
end
|
65
|
-
end
|
66
|
-
end
|
67
|
+
end
|
68
|
+
end
|
67
69
|
end
|
68
70
|
|
69
71
|
class << self
|
@@ -86,7 +88,7 @@ module Glimmer
|
|
86
88
|
end
|
87
89
|
|
88
90
|
def disabled_dsls
|
89
|
-
@disabled_dsls ||=
|
91
|
+
@disabled_dsls ||= Concurrent::Array.new
|
90
92
|
end
|
91
93
|
|
92
94
|
def enabled_dsls=(dsl_names)
|
@@ -109,13 +111,13 @@ module Glimmer
|
|
109
111
|
|
110
112
|
# Dynamic expression chains of responsibility indexed by dsl
|
111
113
|
def dynamic_expression_chains_of_responsibility
|
112
|
-
@dynamic_expression_chains_of_responsibility ||=
|
114
|
+
@dynamic_expression_chains_of_responsibility ||= Concurrent::Hash.new
|
113
115
|
end
|
114
116
|
|
115
117
|
# Static expressions indexed by keyword and dsl
|
116
118
|
def static_expressions
|
117
|
-
@static_expressions ||=
|
118
|
-
end
|
119
|
+
@static_expressions ||= Concurrent::Hash.new
|
120
|
+
end
|
119
121
|
|
120
122
|
# Sets dynamic expression chains of responsibility. Useful for internal testing
|
121
123
|
attr_writer :dynamic_expression_chains_of_responsibility
|
@@ -132,7 +134,7 @@ module Glimmer
|
|
132
134
|
# Pattern when interpretting a DSL expression
|
133
135
|
def add_dynamic_expressions(dsl_namespace, *expression_names)
|
134
136
|
expression_names = expression_names.flatten
|
135
|
-
dsl = dsl_namespace.name.split("::").last.downcase.to_sym
|
137
|
+
dsl = dsl_namespace.name.split("::").last.downcase.to_sym
|
136
138
|
dynamic_expression_chains_of_responsibility[dsl] = expression_names.reverse.map do |expression_name|
|
137
139
|
expression_class(dsl_namespace, expression_name).new
|
138
140
|
end.reduce(nil) do |last_expresion_handler, expression|
|
@@ -140,14 +142,14 @@ module Glimmer
|
|
140
142
|
expression_handler = ExpressionHandler.new(expression)
|
141
143
|
expression_handler.next = last_expresion_handler if last_expresion_handler
|
142
144
|
expression_handler
|
143
|
-
end
|
145
|
+
end
|
144
146
|
end
|
145
147
|
|
146
148
|
def add_static_expression(static_expression)
|
147
149
|
Glimmer::Config.logger.info {"Adding static expression: #{static_expression.class.name}"}
|
148
150
|
keyword = static_expression.class.keyword
|
149
151
|
static_expression_dsl = static_expression.class.dsl
|
150
|
-
static_expressions[keyword] ||=
|
152
|
+
static_expressions[keyword] ||= Concurrent::Hash.new
|
151
153
|
static_expressions[keyword][static_expression_dsl] = static_expression
|
152
154
|
Glimmer.send(:define_method, keyword, &STATIC_EXPRESSION_METHOD_FACTORY.call(keyword))
|
153
155
|
end
|
@@ -161,10 +163,11 @@ module Glimmer
|
|
161
163
|
end
|
162
164
|
|
163
165
|
# Interprets Glimmer dynamic DSL expression consisting of keyword, args, and block (e.g. shell(:no_resize) { ... })
|
164
|
-
def interpret(keyword, *args, &block)
|
165
|
-
return puts(MESSAGE_NO_DSLS) if no_dsls?
|
166
|
+
def interpret(keyword, *args, &block)
|
167
|
+
return puts(MESSAGE_NO_DSLS) if no_dsls? # TODO consider switching to an error log statement
|
166
168
|
keyword = keyword.to_s
|
167
169
|
dynamic_expression_dsl = (dynamic_expression_chains_of_responsibility.keys - disabled_dsls).first if dsl.nil?
|
170
|
+
# TODO consider pushing this code into interpret_expresion to provide hooks that work around it regardless of static vs dynamic
|
168
171
|
dsl_stack.push(dynamic_expression_dsl || dsl)
|
169
172
|
expression = dynamic_expression_chains_of_responsibility[dsl].handle(parent, keyword, *args, &block)
|
170
173
|
interpret_expression(expression, keyword, *args, &block)
|
@@ -185,7 +188,7 @@ module Glimmer
|
|
185
188
|
def add_content(parent, expression, &block)
|
186
189
|
if block_given? && expression.is_a?(ParentExpression)
|
187
190
|
dsl_stack.push(expression.class.dsl)
|
188
|
-
parent_stack.push(parent)
|
191
|
+
parent_stack.push(parent)
|
189
192
|
begin
|
190
193
|
expression.add_content(parent, &block)
|
191
194
|
ensure
|
@@ -202,16 +205,16 @@ module Glimmer
|
|
202
205
|
def_delegator :parent_stack, :last, :parent
|
203
206
|
|
204
207
|
def parent_stack
|
205
|
-
parent_stacks[dsl] ||=
|
208
|
+
parent_stacks[dsl] ||= Concurrent::Array.new
|
206
209
|
end
|
207
210
|
|
208
211
|
def parent_stacks
|
209
|
-
@parent_stacks ||=
|
212
|
+
@parent_stacks ||= Concurrent::Hash.new
|
210
213
|
end
|
211
214
|
|
212
215
|
# Enables multiple DSLs to play well with each other when mixing together
|
213
216
|
def dsl_stack
|
214
|
-
@dsl_stack ||=
|
217
|
+
@dsl_stack ||= Concurrent::Array.new
|
215
218
|
end
|
216
219
|
end
|
217
220
|
end
|