glimmer 1.0.5 → 1.0.10

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.5
1
+ 1.0.10
@@ -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 ruby lib
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.5"
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 = "2020-12-02"
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 Library), the Glimmer DSL for Tk (Ruby Desktop Development GUI Library), the Glimmer DSL for Opal (Web GUI Adapter for Desktop Apps), the Glimmer DSL for XML (& HTML), and the Glimmer DSL for CSS.".freeze
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, ["= 0.8.23"])
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, ["= 0.8.23"])
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"])
@@ -1,5 +1,5 @@
1
- # Copyright (c) 2007-2020 Andy Maleh
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}"}
@@ -1,5 +1,5 @@
1
- # Copyright (c) 2007-2020 Andy Maleh
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-2020 Andy Maleh
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({}) do |output, property_name|
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 evaluate_property == converted_value
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
- return if @binding_options[:read_only]
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-2020 Andy Maleh
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-2020 Andy Maleh
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-2020 Andy Maleh
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("__original_#{property_writer_name}", value)
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("__original_#{property_writer_name}")
108
+ method("__original__#{property_writer_name}")
109
109
  rescue
110
- define_singleton_method("__original_#{property_writer_name}", property_writer_method(property_writer_name))
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.is_a?(Array)
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-2020 Andy Maleh
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)
@@ -1,5 +1,5 @@
1
- # Copyright (c) 2007-2020 Andy Maleh
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 and Chain of Responsibility Design Patterns
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
- static_expression_dsl = (Glimmer::DSL::Engine.static_expressions[keyword].keys - Glimmer::DSL::Engine.disabled_dsls).first if retrieved_static_expression.nil?
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
- if !static_expression.can_interpret?(Glimmer::DSL::Engine.parent, keyword, *args, &block)
59
- raise Error, "Invalid use of Glimmer keyword #{keyword} with args #{args} under parent #{Glimmer::DSL::Engine.parent}"
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