Skip to content

Commit

Permalink
Merge pull request #234 from mcorino/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
mcorino authored Jan 6, 2024
2 parents af7a4df + 3f481f8 commit 6de4a56
Show file tree
Hide file tree
Showing 6 changed files with 316 additions and 88 deletions.
180 changes: 104 additions & 76 deletions lib/wx/core/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ module Interface
def method_missing(sym, *args, &block)
unless block_given? || args.size>1
setter = false
key = sym.to_s.sub(/=\z/) { |s| setter = true; '' }
key = sym.to_s.sub(/=\z/) { |_| setter = true; '' }
if (!setter && args.empty?) || (!has_group?(key) && setter && args.size==1)
if setter
return set(key, args.shift)
Expand Down Expand Up @@ -142,8 +142,8 @@ def read(path_str, output=nil)
when ::TrueClass == output || ::FalseClass == output || output == true || output == false
val.is_a?(Integer) ? val != 0 : !!val
else
raise ArgumentError, "Unknown coercion type #{output.is_a?(::Class) ? output : output.class}" if output
val
raise ArgumentError, "Unknown coercion type #{output.is_a?(::Class) ? output : output.class}" unless output.nil? || output.is_a?(::Proc)
output ? output.call(val) : val
end
end
end
Expand Down Expand Up @@ -330,17 +330,17 @@ module Interface

def each_entry(&block)
if block_given?
@data.select { |_,v| !v.is_a?(::Hash) }.each(&block)
data.select { |_,v| !v.is_a?(::Hash) }.each(&block)
else
::Enumerator.new { |y| @data.each_pair { |k,v| y << [k,v] if !v.is_a?(::Hash) } }
::Enumerator.new { |y| data.each_pair { |k,v| y << [k, expand(v)] unless v.is_a?(::Hash) } }
end
end

def each_group(&block)
if block_given?
@data.select { |_,g| g.is_a?(::Hash) }.each { |k,g| block.call(k, Group.new(self, self.path.dup.push(k), g)) }
data.select { |_,g| g.is_a?(::Hash) }.each { |k,_| block.call(k, Group.new(self, self.path.dup.push(k))) }
else
::Enumerator.new { |y| @data.each_pair { |k,g| y << [k,Group.new(self, self.path.dup.push(k), g)] if g.is_a?(::Hash) } }
::Enumerator.new { |y| data.each_pair { |k,g| y << [k,Group.new(self, self.path.dup.push(k))] if g.is_a?(::Hash) } }
end
end

Expand All @@ -365,11 +365,9 @@ def has_entry?(path_str)
return false if segments.empty?
entry = segments.pop
group_data = if segments.empty?
@data
data
else
unless abs || root?
segments = self.path + segments
end
segments = self.path + segments unless abs || root?
get_group_at(segments)
end
!!(group_data && group_data.has_key?(entry) && !group_data[entry].is_a?(::Hash))
Expand All @@ -378,40 +376,39 @@ def has_entry?(path_str)
def has_group?(path_str)
segments, abs = get_path(path_str)
return root? if segments.empty?
unless abs || root?
segments = self.path + segments
end
segments = self.path + segments unless abs || root?
!!get_group_at(segments)
end

def get(key)
key = key.to_s
raise ArgumentError, 'No paths allowed' if key.index(ConfigBase::SEPARATOR)
elem = @data[key]
elem = data[key]
if elem.is_a?(::Hash)
Group.new(self, self.path.dup.push(key), elem)
Group.new(self, self.path.dup.push(key))
else
elem
expand(elem)
end
end

def set(key, val)
key = key.to_s
raise ArgumentError, 'No paths allowed' if key.index(ConfigBase::SEPARATOR)
exist = @data.has_key?(key)
elem = exist ? @data[key] : nil
hsh = data
exist = hsh.has_key?(key)
elem = exist ? hsh[key] : nil
if val.nil?
@data.delete(key) if exist
hsh.delete(key) if exist
nil
elsif val.is_a?(::Hash)
raise ArgumentError, 'Cannot change existing value entry to group.' if exist && !elem.is_a?(::Hash)
elem = @data[key] = {} unless elem
group = Group.new(self, self.path.dup.push(key), elem)
hsh[key] = {} unless elem
group = Group.new(self, self.path.dup.push(key))
val.each_pair { |k, v| group.set(k, v) }
group
else
raise ArgumentError, 'Cannot change existing group to value entry.' if exist && elem.is_a?(::Hash)
@data[key] = sanitize_value(val)
hsh[key] = val
end
end

Expand All @@ -420,23 +417,21 @@ def delete(path_str)
return nil if segments.empty?
last = segments.pop
group_data = if segments.empty?
@data
data
else
unless abs || root?
segments = self.path + segments
end
segments = self.path + segments unless abs || root?
get_group_at(segments, create_missing_groups: false)
end
raise ArgumentError, "Unable to resolve path #{segments+[last]}" unless group_data
group_data.delete(last)
group_data ? group_data.delete(last) : nil
end

def rename(old_key, new_key)
old_key = old_key.to_s
new_key = new_key.to_s
raise ArgumentError, 'No paths allowed' if old_key.index(ConfigBase::SEPARATOR) || new_key.index(ConfigBase::SEPARATOR)
if @data.has_key?(old_key) && !@data.has_key?(new_key)
@data[new_key] = @data.delete(old_key)
hsh = data
if hsh.has_key?(old_key) && !hsh.has_key?(new_key)
hsh[new_key] = hsh.delete(old_key)
true
else
false
Expand All @@ -448,19 +443,19 @@ def read(path_str, output=nil)
return nil if segments.empty?
last = segments.pop
group_data = if segments.empty?
@data
segments = self.path.dup unless abs || root?
data
else
unless abs || root?
segments = self.path + segments
end
get_group_at(segments, create_missing_groups: true)
segments = self.path + segments unless abs || root?
get_group_at(segments)
end
raise ArgumentError, "Unable to resolve path #{segments+[last]}" unless group_data
val = group_data[last]
val = group_data ? group_data[last] : nil
if val.is_a?(::Hash)
raise TypeError, "Cannot convert group" unless output.nil?
Group.new(self, segments.dup.push(last), val)
Group.new(self, segments.dup.push(last))
else
val = expand(val)
return val unless val && output
case
when ::String == output || ::String === output
val.to_s
Expand All @@ -471,8 +466,8 @@ def read(path_str, output=nil)
when ::TrueClass == output || ::FalseClass == output || output == true || output == false
val.is_a?(::Integer) ? val != 0 : !!val
else
raise ArgumentError, "Unknown coercion type #{output.is_a?(::Class) ? output : output.class}" if output
val
raise ArgumentError, "Unknown coercion type #{output.is_a?(::Class) ? output : output.class}" unless output.nil? || output.is_a?(::Proc)
output ? output.call(val) : val
end
end
end
Expand All @@ -483,11 +478,10 @@ def write(path_str, val)
return false if segments.empty?
last = segments.pop
group_data = if segments.empty?
@data
segments = self.path.dup unless abs || root?
data
else
unless abs || root?
segments = self.path + segments
end
segments = self.path + segments unless abs || root?
get_group_at(segments, create_missing_groups: true)
end
raise ArgumentError, "Unable to resolve path #{segments+[last]}" unless group_data
Expand All @@ -498,13 +492,13 @@ def write(path_str, val)
nil
elsif val.is_a?(::Hash)
raise ArgumentError, 'Cannot change existing value entry to group.' if exist && !elem.is_a?(::Hash)
elem = group_data[last] = {} unless elem
group = Group.new(self, segments.dup.push(last), elem)
group_data[last] = {} unless elem
group = Group.new(self, segments.dup.push(last))
val.each_pair { |k, v| group.set(k, v) }
group
else
raise ArgumentError, 'Cannot change existing group to value entry.' if exist && elem.is_a?(::Hash)
group_data[last] = sanitize_value(val)
group_data[last] = val
end
end
alias :[]= :write
Expand All @@ -514,7 +508,7 @@ def to_s
end

def to_h
@data
data
end

def get_path(path_str)
Expand All @@ -526,21 +520,33 @@ def get_path(path_str)
end
protected :get_path

def sanitize_value(val)
case val
when TrueClass, FalseClass, Numeric, String
val
else
if val.respond_to?(:to_int)
val.to_int
elsif val.respond_to?(:to_f)
val.to_f
else
val.to_s
EXPAND_RE = if Wx::PLATFORM == 'WXMSW'
/(\\)?([$][{(]?|%)(\w+)([})%])?/
else
/(\\)?([$][{(]?)(\w+)([})])?/
end
private_constant :EXPAND_RE

def expand(val)
if root.expanding_env_vars? && ::String === val
val.gsub(EXPAND_RE) do |s|
if $1.nil? &&
(($2[0] == '$' &&
($2.size == 1 && $4.nil?) ||
($2[1] == '(' && $4 == ')') ||
($2[1] == '{' && $4 == '}'))||
($2[0] == '%' && $4 == '%')) &&
ENV[$3]
$1 ? $1+ENV[$3] : ENV[$3]
else
$1 ? s[1,s.size] : s
end
end
else
val
end
end
protected :sanitize_value
protected :expand

end

Expand All @@ -550,12 +556,16 @@ class Group

include Interface

def initialize(parent, path, data)
def initialize(parent, path)
@parent = parent
@path = path.freeze
@data = data
end

def data
self.root.__send__(:get_group_at, @path, create_missing_groups: true, is_pruned: true)
end
protected :data

def root?
false
end
Expand All @@ -573,7 +583,7 @@ def parent
end

def get_group_at(segments, create_missing_groups: false)
root.__send__(:get_group_at, segments)
root.__send__(:get_group_at, segments, create_missing_groups: create_missing_groups)
end
protected :get_group_at

Expand All @@ -582,10 +592,16 @@ def get_group_at(segments, create_missing_groups: false)
include Interface

def initialize(hash = nil)
@expand_env_vars = true
@data = {}
replace(hash) if hash
end

def data
@data
end
protected :data

def root?
true
end
Expand Down Expand Up @@ -614,19 +630,31 @@ def replace(hash)
self
end

def get_group_at(segments, create_missing_groups: false)
# prune segments (process relative segments)
segments = segments.inject([]) do |lst, seg|
case seg
when '..'
lst.pop # remove previous
# forget ..
when '.'
# forget
else
lst << seg
def is_expanding_env_vars
@expand_env_vars
end
alias :expanding_env_vars? :is_expanding_env_vars

def set_expand_env_vars(flag)
@expand_env_vars = !!flag
end
alias :expand_env_vars :set_expand_env_vars

def get_group_at(segments, create_missing_groups: false, is_pruned: false)
unless is_pruned
# prune segments (process relative segments)
segments = segments.inject([]) do |lst, seg|
case seg
when '..'
lst.pop # remove previous
# forget ..
when '.'
# forget
else
lst << seg
end
lst
end
lst
end
# find group matching segments
segments.inject(@data) do |hsh, seg|
Expand Down
22 changes: 21 additions & 1 deletion lib/wx/doc/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ def rename(old_key, new_key) end
# By default returns un-coerced value.
# Raises exception if incompatible coercion is specified.
# @param [String] path_str
# @param [Class,nil] output output type to convert to
# @param [Class,Proc,nil] output output type (or converter proc) to convert to (with)
# @return [Boolean,String,Integer,Float,Wx::Config::Group,nil] value entry value
def read(path_str, output=nil) end

Expand Down Expand Up @@ -186,6 +186,16 @@ def clear; end
# @return [self]
def replace(hash) end

# Returns true if we are expanding environment variables in string values, false otherwise.
# @return [Boolean]
def is_expanding_env_vars; end
alias :expanding_env_vars? :is_expanding_env_vars

# Determine whether we wish to expand environment variables in string values.
# @param [Boolean] flag enables expanding environment variables if true, disables otherwise
def set_expand_env_vars(flag) end
alias :expand_env_vars :set_expand_env_vars

end

# Configuration class for wxRuby which stores it's settings in a (possibly nested) Hash.
Expand Down Expand Up @@ -225,6 +235,16 @@ def clear; end
# @return [self]
def replace(hash) end

# Returns true if we are expanding environment variables in string values, false otherwise.
# @return [Boolean]
def is_expanding_env_vars; end
alias :expanding_env_vars? :is_expanding_env_vars

# Determine whether we wish to expand environment variables in string values.
# @param [Boolean] flag enables expanding environment variables if true, disables otherwise
def set_expand_env_vars(flag) end
alias :expand_env_vars :set_expand_env_vars

end

end
Loading

0 comments on commit 6de4a56

Please sign in to comment.