glimmer 1.0.3 → 1.0.8

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.3
1
+ 1.0.8
@@ -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.3 ruby lib
5
+ # stub: glimmer 1.0.8 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "glimmer".freeze
9
- s.version = "1.0.3"
9
+ s.version = "1.0.8"
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-11-15"
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-19"
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,7 @@
22
22
  require 'logger'
23
23
  require 'set'
24
24
  require 'array_include_methods'
25
+ require 'concurrent-ruby'
25
26
 
26
27
  $LOAD_PATH.unshift(File.expand_path('..', __FILE__))
27
28
 
@@ -70,7 +71,7 @@ module Glimmer
70
71
  end
71
72
  Glimmer.loop_last_data = new_loop_data
72
73
  Glimmer::Config.logger.info {"Interpreting keyword: #{method_symbol}"}
73
- Glimmer::DSL::Engine.interpret(method_symbol, *args, &block)
74
+ Glimmer::DSL::Engine.interpret(method_symbol, *args, &block)
74
75
  end
75
76
  rescue InvalidKeywordError => e
76
77
  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
@@ -57,7 +57,26 @@ module Glimmer
57
57
  end
58
58
 
59
59
  def remove_observer(observer, property_name)
60
- property_observer_list(property_name).delete(observer)
60
+ if has_observer?(observer, property_name)
61
+ property_observer_list(property_name).delete(observer)
62
+ observer.unobserve(self, property_name)
63
+ end
64
+ end
65
+
66
+ def remove_observers(property_name)
67
+ property_observer_hash[property_name.to_sym].each do |observer|
68
+ remove_observer(observer, property_name)
69
+ end
70
+ property_observer_hash.delete(property_name.to_sym)
71
+ end
72
+
73
+ def remove_all_observers
74
+ all_observers = property_observer_hash.clone
75
+ property_observer_hash.keys.each do |property_name|
76
+ remove_observers(property_name)
77
+ end
78
+ property_observer_hash.clear
79
+ all_observers
61
80
  end
62
81
 
63
82
  def has_observer?(observer, property_name)
@@ -73,7 +92,7 @@ module Glimmer
73
92
  end
74
93
 
75
94
  def property_observer_list(property_name)
76
- 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]
77
96
  property_observer_hash[property_name.to_sym]
78
97
  end
79
98
 
@@ -86,9 +105,9 @@ module Glimmer
86
105
  method(property_writer_name)
87
106
  ensure_array_object_observer(property_name, send(property_name))
88
107
  begin
89
- singleton_method("__original_#{property_writer_name}")
108
+ method("__original__#{property_writer_name}")
90
109
  rescue
91
- 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))
92
111
  define_singleton_method(property_writer_name, &PROPERTY_WRITER_FACTORY.call(property_name))
93
112
  end
94
113
  rescue => e
@@ -107,7 +126,7 @@ module Glimmer
107
126
  end
108
127
 
109
128
  def ensure_array_object_observer(property_name, object, old_object = nil)
110
- return unless object.is_a?(Array)
129
+ return unless object&.is_a?(Array)
111
130
  array_object_observer = array_object_observer_for(property_name)
112
131
  array_observer_registration = array_object_observer.observe(object)
113
132
  property_observer_list(property_name).each do |observer|
@@ -118,7 +137,7 @@ module Glimmer
118
137
  end
119
138
 
120
139
  def array_object_observer_for(property_name)
121
- @array_object_observers ||= {}
140
+ @array_object_observers ||= Concurrent::Hash.new
122
141
  @array_object_observers[property_name] = ObservableModel::Notifier.new(self, property_name) unless @array_object_observers.has_key?(property_name)
123
142
  @array_object_observers[property_name]
124
143
  end
@@ -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
@@ -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)
@@ -99,13 +100,14 @@ module Glimmer
99
100
  def unregister(observable, property = nil)
100
101
  return unless observable.is_a?(Observable)
101
102
  # TODO optimize performance in the future via indexing and/or making a registration official object/class
102
- observable.remove_observer(*[self, property].compact)
103
103
  registration = registration_for(observable, property)
104
104
  dependents_for(registration).each do |dependent|
105
105
  dependent.unregister
106
106
  remove_dependent(registration => dependent)
107
107
  end
108
- registrations.delete(registration)
108
+ registrations.delete(registration).tap do |registration|
109
+ observable.remove_observer(*[self, property].compact)
110
+ end
109
111
  end
110
112
  alias unobserve unregister
111
113
 
@@ -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.
@@ -51,19 +51,19 @@ module Glimmer
51
51
  end
52
52
  if interpretation
53
53
  interpretation
54
- else
54
+ else
55
55
  raise Glimmer::Error, "Unsupported keyword: #{keyword}" unless static_expression_dsl || retrieved_static_expression
56
56
  Glimmer::DSL::Engine.dsl_stack.push(static_expression_dsl || Glimmer::DSL::Engine.dsl)
57
57
  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}"
58
+ if static_expression.nil? || !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.inspect}"
60
60
  else
61
61
  Glimmer::Config.logger.info {"#{static_expression.class.name} will handle expression keyword #{keyword}"}
62
62
  Glimmer::DSL::Engine.interpret_expression(static_expression, keyword, *args, &block)
63
63
  end
64
64
  end
65
- end
66
- end
65
+ end
66
+ end
67
67
  end
68
68
 
69
69
  class << self
@@ -86,7 +86,7 @@ module Glimmer
86
86
  end
87
87
 
88
88
  def disabled_dsls
89
- @disabled_dsls ||= []
89
+ @disabled_dsls ||= Concurrent::Array.new
90
90
  end
91
91
 
92
92
  def enabled_dsls=(dsl_names)
@@ -109,13 +109,13 @@ module Glimmer
109
109
 
110
110
  # Dynamic expression chains of responsibility indexed by dsl
111
111
  def dynamic_expression_chains_of_responsibility
112
- @dynamic_expression_chains_of_responsibility ||= {}
112
+ @dynamic_expression_chains_of_responsibility ||= Concurrent::Hash.new
113
113
  end
114
114
 
115
115
  # Static expressions indexed by keyword and dsl
116
116
  def static_expressions
117
- @static_expressions ||= {}
118
- end
117
+ @static_expressions ||= Concurrent::Hash.new
118
+ end
119
119
 
120
120
  # Sets dynamic expression chains of responsibility. Useful for internal testing
121
121
  attr_writer :dynamic_expression_chains_of_responsibility
@@ -132,7 +132,7 @@ module Glimmer
132
132
  # Pattern when interpretting a DSL expression
133
133
  def add_dynamic_expressions(dsl_namespace, *expression_names)
134
134
  expression_names = expression_names.flatten
135
- dsl = dsl_namespace.name.split("::").last.downcase.to_sym
135
+ dsl = dsl_namespace.name.split("::").last.downcase.to_sym
136
136
  dynamic_expression_chains_of_responsibility[dsl] = expression_names.reverse.map do |expression_name|
137
137
  expression_class(dsl_namespace, expression_name).new
138
138
  end.reduce(nil) do |last_expresion_handler, expression|
@@ -140,14 +140,14 @@ module Glimmer
140
140
  expression_handler = ExpressionHandler.new(expression)
141
141
  expression_handler.next = last_expresion_handler if last_expresion_handler
142
142
  expression_handler
143
- end
143
+ end
144
144
  end
145
145
 
146
146
  def add_static_expression(static_expression)
147
147
  Glimmer::Config.logger.info {"Adding static expression: #{static_expression.class.name}"}
148
148
  keyword = static_expression.class.keyword
149
149
  static_expression_dsl = static_expression.class.dsl
150
- static_expressions[keyword] ||= {}
150
+ static_expressions[keyword] ||= Concurrent::Hash.new
151
151
  static_expressions[keyword][static_expression_dsl] = static_expression
152
152
  Glimmer.send(:define_method, keyword, &STATIC_EXPRESSION_METHOD_FACTORY.call(keyword))
153
153
  end
@@ -161,10 +161,11 @@ module Glimmer
161
161
  end
162
162
 
163
163
  # Interprets Glimmer dynamic DSL expression consisting of keyword, args, and block (e.g. shell(:no_resize) { ... })
164
- def interpret(keyword, *args, &block)
164
+ def interpret(keyword, *args, &block)
165
165
  return puts(MESSAGE_NO_DSLS) if no_dsls?
166
166
  keyword = keyword.to_s
167
167
  dynamic_expression_dsl = (dynamic_expression_chains_of_responsibility.keys - disabled_dsls).first if dsl.nil?
168
+ # TODO consider pushing this code into interpret_expresion to provide hooks that work around it regardless of static vs dynamic
168
169
  dsl_stack.push(dynamic_expression_dsl || dsl)
169
170
  expression = dynamic_expression_chains_of_responsibility[dsl].handle(parent, keyword, *args, &block)
170
171
  interpret_expression(expression, keyword, *args, &block)
@@ -185,7 +186,7 @@ module Glimmer
185
186
  def add_content(parent, expression, &block)
186
187
  if block_given? && expression.is_a?(ParentExpression)
187
188
  dsl_stack.push(expression.class.dsl)
188
- parent_stack.push(parent)
189
+ parent_stack.push(parent)
189
190
  begin
190
191
  expression.add_content(parent, &block)
191
192
  ensure
@@ -202,16 +203,16 @@ module Glimmer
202
203
  def_delegator :parent_stack, :last, :parent
203
204
 
204
205
  def parent_stack
205
- parent_stacks[dsl] ||= []
206
+ parent_stacks[dsl] ||= Concurrent::Array.new
206
207
  end
207
208
 
208
209
  def parent_stacks
209
- @parent_stacks ||= {}
210
+ @parent_stacks ||= Concurrent::Hash.new
210
211
  end
211
212
 
212
213
  # Enables multiple DSLs to play well with each other when mixing together
213
214
  def dsl_stack
214
- @dsl_stack ||= []
215
+ @dsl_stack ||= Concurrent::Array.new
215
216
  end
216
217
  end
217
218
  end