wxruby3 0.9.3-x64-mingw-ucrt → 0.9.5-x64-mingw-ucrt
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/INSTALL.md +1 -1
- data/README.md +2 -2
- data/ext/wxbase32u_gcc_custom.dll +0 -0
- data/ext/wxbase32u_net_gcc_custom.dll +0 -0
- data/ext/wxbase32u_xml_gcc_custom.dll +0 -0
- data/ext/wxmsw32u_aui_gcc_custom.dll +0 -0
- data/ext/wxmsw32u_core_gcc_custom.dll +0 -0
- data/ext/wxmsw32u_gl_gcc_custom.dll +0 -0
- data/ext/wxmsw32u_html_gcc_custom.dll +0 -0
- data/ext/wxmsw32u_media_gcc_custom.dll +0 -0
- data/ext/wxmsw32u_propgrid_gcc_custom.dll +0 -0
- data/ext/wxmsw32u_qa_gcc_custom.dll +0 -0
- data/ext/wxmsw32u_ribbon_gcc_custom.dll +0 -0
- data/ext/wxmsw32u_richtext_gcc_custom.dll +0 -0
- data/ext/wxmsw32u_stc_gcc_custom.dll +0 -0
- data/ext/wxmsw32u_webview_gcc_custom.dll +0 -0
- data/ext/wxmsw32u_xrc_gcc_custom.dll +0 -0
- data/lib/wx/core/book_ctrl_base.rb +16 -0
- data/lib/wx/core/combo_ctrl.rb +171 -0
- data/lib/wx/core/config.rb +454 -83
- data/lib/wx/core/notebook.rb +10 -8
- data/lib/wx/core/peristent_object.rb +15 -0
- data/lib/wx/core/persistence_manager.rb +39 -0
- data/lib/wx/core/persistent_window.rb +16 -0
- data/lib/wx/core/top_level_window.rb +16 -0
- data/lib/wx/core/treebook.rb +18 -0
- data/lib/wx/core.rb +4 -0
- data/lib/wx/doc/book_ctrl_base.rb +19 -0
- data/lib/wx/doc/comboctrl.rb +128 -3
- data/lib/wx/doc/config.rb +101 -41
- data/lib/wx/doc/extra/14_config.md +101 -0
- data/lib/wx/doc/extra/15_persistence.md +148 -0
- data/lib/wx/doc/gen/app_traits.rb +2 -54
- data/lib/wx/doc/gen/art_provider.rb +0 -2
- data/lib/wx/doc/gen/aui/aui_dock_art.rb +77 -77
- data/lib/wx/doc/gen/aui/aui_manager.rb +0 -1
- data/lib/wx/doc/gen/aui/aui_manager_event.rb +1 -1
- data/lib/wx/doc/gen/aui/aui_mdi_client_window.rb +5 -4
- data/lib/wx/doc/gen/aui/aui_notebook_event.rb +1 -1
- data/lib/wx/doc/gen/aui/aui_tool_bar_event.rb +21 -21
- data/lib/wx/doc/gen/book_ctrl_event.rb +1 -1
- data/lib/wx/doc/gen/calendar_event.rb +1 -1
- data/lib/wx/doc/gen/colour.rb +0 -1
- data/lib/wx/doc/gen/colour_dialog.rb +1 -1
- data/lib/wx/doc/gen/combo_box.rb +3 -2
- data/lib/wx/doc/gen/combo_ctrl.rb +91 -227
- data/lib/wx/doc/gen/core.rb +2 -2
- data/lib/wx/doc/gen/date_event.rb +1 -1
- data/lib/wx/doc/gen/dc.rb +0 -3
- data/lib/wx/doc/gen/dialog.rb +0 -1
- data/lib/wx/doc/gen/event.rb +4 -4
- data/lib/wx/doc/gen/event_blocker.rb +1 -1
- data/lib/wx/doc/gen/event_filter.rb +0 -2
- data/lib/wx/doc/gen/events.rb +17 -39
- data/lib/wx/doc/gen/file_ctrl_event.rb +1 -1
- data/lib/wx/doc/gen/file_dialog.rb +0 -2
- data/lib/wx/doc/gen/file_dialog_customize_hook.rb +55 -63
- data/lib/wx/doc/gen/file_dir_picker_event.rb +1 -1
- data/lib/wx/doc/gen/file_system.rb +1 -58
- data/lib/wx/doc/gen/find_dialog_event.rb +1 -1
- data/lib/wx/doc/gen/frame.rb +0 -1
- data/lib/wx/doc/gen/gdi_common.rb +0 -8
- data/lib/wx/doc/gen/grid/grid_cell_activatable_editor.rb +0 -2
- data/lib/wx/doc/gen/grid/grid_cell_attr.rb +0 -2
- data/lib/wx/doc/gen/grid/grid_cell_auto_wrap_string_editor.rb +0 -2
- data/lib/wx/doc/gen/grid/grid_cell_auto_wrap_string_renderer.rb +0 -2
- data/lib/wx/doc/gen/grid/grid_cell_bool_editor.rb +0 -2
- data/lib/wx/doc/gen/grid/grid_cell_bool_renderer.rb +0 -2
- data/lib/wx/doc/gen/grid/grid_cell_choice_editor.rb +0 -2
- data/lib/wx/doc/gen/grid/grid_cell_date_editor.rb +0 -2
- data/lib/wx/doc/gen/grid/grid_cell_date_renderer.rb +0 -2
- data/lib/wx/doc/gen/grid/grid_cell_date_time_renderer.rb +0 -2
- data/lib/wx/doc/gen/grid/grid_cell_editor.rb +0 -2
- data/lib/wx/doc/gen/grid/grid_cell_enum_editor.rb +0 -2
- data/lib/wx/doc/gen/grid/grid_cell_enum_renderer.rb +0 -2
- data/lib/wx/doc/gen/grid/grid_cell_float_editor.rb +0 -2
- data/lib/wx/doc/gen/grid/grid_cell_float_renderer.rb +0 -2
- data/lib/wx/doc/gen/grid/grid_cell_number_editor.rb +0 -2
- data/lib/wx/doc/gen/grid/grid_cell_number_renderer.rb +0 -2
- data/lib/wx/doc/gen/grid/grid_cell_renderer.rb +0 -2
- data/lib/wx/doc/gen/grid/grid_cell_string_renderer.rb +0 -2
- data/lib/wx/doc/gen/grid/grid_cell_text_editor.rb +0 -2
- data/lib/wx/doc/gen/grid/grid_ctrl.rb +0 -12
- data/lib/wx/doc/gen/grid/grid_editor_created_event.rb +1 -1
- data/lib/wx/doc/gen/grid/grid_event.rb +1 -1
- data/lib/wx/doc/gen/grid/grid_range_select_event.rb +1 -1
- data/lib/wx/doc/gen/grid/grid_size_event.rb +1 -1
- data/lib/wx/doc/gen/gui_event_loop.rb +0 -2
- data/lib/wx/doc/gen/header_ctrl.rb +0 -7
- data/lib/wx/doc/gen/header_ctrl_event.rb +1 -1
- data/lib/wx/doc/gen/html/html_cell_event.rb +1 -1
- data/lib/wx/doc/gen/image.rb +0 -2
- data/lib/wx/doc/gen/list_ctrl.rb +0 -1
- data/lib/wx/doc/gen/list_event.rb +1 -1
- data/lib/wx/doc/gen/media_ctrl.rb +0 -6
- data/lib/wx/doc/gen/media_event.rb +1 -1
- data/lib/wx/doc/gen/menu.rb +0 -2
- data/lib/wx/doc/gen/notebook.rb +0 -1
- data/lib/wx/doc/gen/persistence_manager.rb +135 -0
- data/lib/wx/doc/gen/persistent_object.rb +52 -0
- data/lib/wx/doc/gen/persistent_window.rb +116 -0
- data/lib/wx/doc/gen/pg/pg_property.rb +0 -13
- data/lib/wx/doc/gen/pg/pg_validation_info.rb +0 -2
- data/lib/wx/doc/gen/pg/property_grid.rb +0 -2
- data/lib/wx/doc/gen/pg/property_grid_event.rb +1 -1
- data/lib/wx/doc/gen/pg/property_grid_interface.rb +2 -2
- data/lib/wx/doc/gen/pg/property_grid_manager.rb +0 -2
- data/lib/wx/doc/gen/pg/property_grid_page.rb +0 -2
- data/lib/wx/doc/gen/pg/property_grid_page_state.rb +0 -1
- data/lib/wx/doc/gen/prt/post_script_dc.rb +0 -1
- data/lib/wx/doc/gen/rbn/ribbon_bar_event.rb +1 -1
- data/lib/wx/doc/gen/rbn/ribbon_button_bar_event.rb +1 -1
- data/lib/wx/doc/gen/rbn/ribbon_gallery_event.rb +1 -1
- data/lib/wx/doc/gen/rbn/ribbon_panel_event.rb +1 -1
- data/lib/wx/doc/gen/rbn/ribbon_tool_bar_event.rb +1 -1
- data/lib/wx/doc/gen/rtc/rich_text_event.rb +1 -1
- data/lib/wx/doc/gen/rtc/rich_text_html_handler.rb +0 -1
- data/lib/wx/doc/gen/rtc/rich_text_style_list_box.rb +3 -0
- data/lib/wx/doc/gen/rtc/rich_text_xml_handler.rb +0 -1
- data/lib/wx/doc/gen/scroll_bar.rb +0 -1
- data/lib/wx/doc/gen/sizer.rb +0 -1
- data/lib/wx/doc/gen/slider.rb +0 -1
- data/lib/wx/doc/gen/spin_double_event.rb +1 -1
- data/lib/wx/doc/gen/spin_event.rb +1 -1
- data/lib/wx/doc/gen/splash_screen.rb +1 -1
- data/lib/wx/doc/gen/splitter_event.rb +1 -1
- data/lib/wx/doc/gen/stc/styled_text_ctrl.rb +0 -1
- data/lib/wx/doc/gen/stc/styled_text_event.rb +1 -2
- data/lib/wx/doc/gen/task_bar_icon.rb +0 -1
- data/lib/wx/doc/gen/task_bar_icon_event.rb +1 -1
- data/lib/wx/doc/gen/text_ctrl.rb +0 -5
- data/lib/wx/doc/gen/text_entry.rb +0 -4
- data/lib/wx/doc/gen/tree_ctrl.rb +0 -2
- data/lib/wx/doc/gen/tree_event.rb +1 -1
- data/lib/wx/doc/gen/utils.rb +0 -16
- data/lib/wx/doc/gen/v_scrolled_window.rb +0 -1
- data/lib/wx/doc/gen/wizard.rb +0 -1
- data/lib/wx/doc/gen/wizard_event.rb +1 -1
- data/lib/wx/doc/gen/wizard_page.rb +0 -1
- data/lib/wx/doc/owner_drawn_combobox.rb +5 -1
- data/lib/wx/doc/persistence_manager.rb +36 -0
- data/lib/wx/doc/persistent_object.rb +27 -0
- data/lib/wx/doc/top_level_window.rb +19 -0
- data/lib/wx/doc/treebook.rb +6 -1
- data/lib/wx/version.rb +1 -1
- data/lib/wxruby_aui.so +0 -0
- data/lib/wxruby_core.so +0 -0
- data/lib/wxruby_grid.so +0 -0
- data/lib/wxruby_html.so +0 -0
- data/lib/wxruby_pg.so +0 -0
- data/lib/wxruby_prt.so +0 -0
- data/lib/wxruby_rbn.so +0 -0
- data/lib/wxruby_rtc.so +0 -0
- data/lib/wxruby_stc.so +0 -0
- data/samples/widgets/widgets.rb +5 -9
- data/tests/test_combo_ctrl.rb +196 -0
- data/tests/test_config.rb +207 -42
- data/tests/test_persistence.rb +142 -0
- metadata +20 -2
data/lib/wx/core/config.rb
CHANGED
@@ -8,47 +8,353 @@
|
|
8
8
|
|
9
9
|
module Wx
|
10
10
|
|
11
|
-
class
|
11
|
+
class ConfigBase
|
12
12
|
|
13
13
|
SEPARATOR = '/'.freeze
|
14
14
|
|
15
15
|
module Interface
|
16
16
|
|
17
|
-
|
17
|
+
# provide auto-magic accessor support for config objects
|
18
|
+
def method_missing(sym, *args, &block)
|
19
|
+
unless block_given? || args.size>1
|
20
|
+
setter = false
|
21
|
+
key = sym.to_s.sub(/=\z/) { |_| setter = true; '' }
|
22
|
+
if (!setter && args.empty?) || (!has_group?(key) && setter && args.size==1)
|
23
|
+
if setter
|
24
|
+
return set(key, args.shift)
|
25
|
+
else
|
26
|
+
return get(key)
|
27
|
+
end
|
28
|
+
elsif setter && args.size == 1 && args.first.is_a?(::Hash) && has_group?(key)
|
29
|
+
return set(key, args.shift)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
super
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
class ConfigWx < ConfigBase
|
40
|
+
|
41
|
+
include ConfigBase::Interface
|
42
|
+
|
43
|
+
# add protection against exceptions raised in blocks
|
44
|
+
wx_for_path = instance_method :for_path
|
45
|
+
define_method :for_path do |path, &block|
|
46
|
+
if block
|
47
|
+
ex = nil
|
48
|
+
rc = wx_for_path.bind(self).call(path) do |cfg, key|
|
49
|
+
begin
|
50
|
+
block.call(cfg, key)
|
51
|
+
rescue Exception
|
52
|
+
ex = $!
|
53
|
+
nil
|
54
|
+
end
|
55
|
+
end
|
56
|
+
raise ex if ex
|
57
|
+
rc
|
58
|
+
else
|
59
|
+
nil
|
60
|
+
end
|
61
|
+
end
|
62
|
+
private :for_path # make this method private (internal use only)
|
63
|
+
|
64
|
+
# add Enumerator support
|
65
|
+
|
66
|
+
wx_each_entry = instance_method :each_entry
|
67
|
+
define_method :each_entry do |&block|
|
68
|
+
if block_given?
|
69
|
+
wx_each_entry.bind(self).call { |k| block.call(k, read(k)) }
|
70
|
+
else
|
71
|
+
::Enumerator.new { |y| wx_each_entry.bind(self).call { |k| y << [k, read_entry(k)] } }
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
wx_each_group = instance_method :each_group
|
76
|
+
define_method :each_group do |&block|
|
77
|
+
if block_given?
|
78
|
+
wx_each_group.bind(self).call { |k| block.call(k, Group.new(self, self.path.dup.push(k))) }
|
79
|
+
else
|
80
|
+
::Enumerator.new { |y| wx_each_group.bind(self).call { |k| y << [k, Group.new(self, self.path.dup.push(k))] } }
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# make this return a path array
|
85
|
+
wx_path = instance_method :path
|
86
|
+
define_method :path do
|
87
|
+
wx_path.bind(self).call.split(ConfigBase::SEPARATOR)
|
88
|
+
end
|
89
|
+
|
90
|
+
# protect against attempts to rename complete paths
|
91
|
+
wx_rename = instance_method :rename
|
92
|
+
define_method :rename do |old_key, new_key|
|
93
|
+
raise ArgumentError, 'No paths allowed' if old_key.index(ConfigBase::SEPARATOR) || new_key.index(ConfigBase::SEPARATOR)
|
94
|
+
wx_rename.bind(self).call(old_key, new_key)
|
95
|
+
end
|
96
|
+
|
97
|
+
# fix recursive number_of_xxx methods as wxRegConfig does not support this currently
|
98
|
+
wx_number_of_entries = instance_method :number_of_entries
|
99
|
+
define_method :number_of_entries do |recurse=false|
|
100
|
+
if recurse
|
101
|
+
each_group.inject(wx_number_of_entries.bind(self).call) { |c, (_, g)| c + g.number_of_entries(true) }
|
102
|
+
else
|
103
|
+
wx_number_of_entries.bind(self).call
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
wx_number_of_groups = instance_method :number_of_groups
|
108
|
+
define_method :number_of_groups do |recurse=false|
|
109
|
+
if recurse
|
110
|
+
each_group.inject(wx_number_of_groups.bind(self).call) { |c, (_, g)| c + g.number_of_groups(true) }
|
111
|
+
else
|
112
|
+
wx_number_of_groups.bind(self).call
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def root?
|
117
|
+
true
|
118
|
+
end
|
119
|
+
|
120
|
+
def root
|
121
|
+
self
|
122
|
+
end
|
123
|
+
|
124
|
+
def parent
|
125
|
+
nil
|
126
|
+
end
|
127
|
+
|
128
|
+
def read(path_str, output=nil)
|
129
|
+
if has_group?(path_str)
|
130
|
+
raise TypeError, "Cannot convert group" unless output.nil?
|
131
|
+
Group.new(self, get_path(path_str))
|
132
|
+
else
|
133
|
+
val = read_entry(path_str)
|
134
|
+
return val unless val && output
|
135
|
+
case
|
136
|
+
when ::String == output || ::String === output
|
137
|
+
val.to_s
|
138
|
+
when ::Integer == output || ::Integer === output
|
139
|
+
Kernel.Integer(val)
|
140
|
+
when ::Float == output || ::Float === output
|
141
|
+
Kernel.Float(val)
|
142
|
+
when ::TrueClass == output || ::FalseClass == output || output == true || output == false
|
143
|
+
val.is_a?(Integer) ? val != 0 : !!val
|
144
|
+
else
|
145
|
+
raise ArgumentError, "Unknown coercion type #{output.is_a?(::Class) ? output : output.class}" unless output.nil? || output.is_a?(::Proc)
|
146
|
+
output ? output.call(val) : val
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
alias :[] :read
|
151
|
+
|
152
|
+
def write(path_str, val)
|
153
|
+
if val.nil?
|
154
|
+
delete(path_str)
|
155
|
+
nil
|
156
|
+
elsif val.is_a?(::Hash)
|
157
|
+
raise ArgumentError, 'Cannot change existing value entry to group.' if has_entry?(path_str)
|
158
|
+
group = Group.new(self, get_path(path_str))
|
159
|
+
val.each_pair { |k, v| group.set(k, v) }
|
160
|
+
group
|
161
|
+
else
|
162
|
+
raise ArgumentError, 'Cannot change existing group to value entry.' if has_group?(path_str)
|
163
|
+
write_entry(path_str, val)
|
164
|
+
read_entry(path_str)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
alias :[]= :write
|
168
|
+
|
169
|
+
def get_path(path_str)
|
170
|
+
path_str = path_str.to_s
|
171
|
+
abs = path_str.start_with?(ConfigBase::SEPARATOR)
|
172
|
+
segs = path_str.split(ConfigBase::SEPARATOR)
|
173
|
+
segs.shift if abs
|
174
|
+
abs ? segs : (self.path+segs)
|
175
|
+
end
|
176
|
+
protected :get_path
|
177
|
+
|
178
|
+
def get(key)
|
179
|
+
raise ArgumentError, 'No paths allowed' if key.index(ConfigBase::SEPARATOR)
|
180
|
+
if has_entry?(key)
|
181
|
+
read_entry(key)
|
182
|
+
elsif has_group?(key)
|
183
|
+
Group.new(self, self.path.dup.push(key))
|
184
|
+
else
|
185
|
+
nil
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
def set(key, val)
|
190
|
+
raise ArgumentError, 'No paths allowed' if key.index(ConfigBase::SEPARATOR)
|
191
|
+
if val.nil?
|
192
|
+
delete(key)
|
193
|
+
nil
|
194
|
+
else
|
195
|
+
if (!val.is_a?(::Hash) && !has_group?(key)) || has_entry?(key)
|
196
|
+
raise ArgumentError, 'Cannot change existing value entry to group.' if val.is_a?(::Hash)
|
197
|
+
write_entry(key, val)
|
198
|
+
read_entry(key)
|
199
|
+
else
|
200
|
+
raise ArgumentError, 'Cannot change existing group to value entry.' if has_group?(key) && !val.is_a?(::Hash)
|
201
|
+
delete(key)
|
202
|
+
group = Group.new(self, self.path.dup.push(key))
|
203
|
+
val.each_pair { |k, v| group.set(k, v) }
|
204
|
+
group
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
def to_s
|
210
|
+
ConfigBase::SEPARATOR
|
211
|
+
end
|
212
|
+
|
213
|
+
def to_h
|
214
|
+
data = each_entry.inject({}) { |hash, pair| hash[pair.first] = pair.last; hash }
|
215
|
+
each_group.inject(data) { |hash, pair| hash[pair.first] = pair.last.to_h; hash }
|
216
|
+
end
|
217
|
+
|
218
|
+
def replace(hash)
|
219
|
+
raise ArgumentError, 'Expected Hash' unless hash.is_a?(::Hash)
|
220
|
+
clear
|
221
|
+
hash.each_pair { |k,v| self.set(k, v) }
|
222
|
+
self
|
223
|
+
end
|
224
|
+
|
225
|
+
class Group
|
226
|
+
|
227
|
+
include ConfigBase::Interface
|
228
|
+
|
229
|
+
def initialize(parent, path)
|
230
|
+
@parent = parent
|
231
|
+
@path = path.freeze
|
232
|
+
@path_str = ConfigBase::SEPARATOR + @path.join(ConfigBase::SEPARATOR) + ConfigBase::SEPARATOR
|
233
|
+
end
|
234
|
+
|
235
|
+
def root?
|
236
|
+
false
|
237
|
+
end
|
238
|
+
|
239
|
+
def root
|
240
|
+
@parent.root
|
241
|
+
end
|
242
|
+
|
243
|
+
def path
|
244
|
+
@path
|
245
|
+
end
|
246
|
+
|
247
|
+
def parent
|
248
|
+
@parent
|
249
|
+
end
|
250
|
+
|
251
|
+
def each_entry(&block)
|
252
|
+
if block_given?
|
253
|
+
root.__send__(:for_path, @path_str) do |cfg, _|
|
254
|
+
cfg.each_entry(&block)
|
255
|
+
end
|
256
|
+
else
|
257
|
+
::Enumerator.new { |y| root.__send__(:for_path, @path_str) { |cfg,_| cfg.each_entry { |k,v| y << [k, v] } } }
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
def each_group(&block)
|
18
262
|
if block_given?
|
19
|
-
|
263
|
+
root.__send__(:for_path, @path_str) do |cfg, _|
|
264
|
+
cfg.each_group(&block)
|
265
|
+
end
|
20
266
|
else
|
21
|
-
@
|
267
|
+
::Enumerator.new { |y| root.__send__(:for_path, @path_str) { |cfg,_| cfg.each_group { |k,g| y << [k, g] } } }
|
22
268
|
end
|
23
269
|
end
|
24
270
|
|
271
|
+
def number_of_entries(recurse=false)
|
272
|
+
root.__send__(:for_path, @path_str) { |cfg,_| cfg.number_of_entries(recurse) }
|
273
|
+
end
|
274
|
+
|
275
|
+
def number_of_groups(recurse=false)
|
276
|
+
root.__send__(:for_path, @path_str) { |cfg,_| cfg.number_of_groups(recurse) }
|
277
|
+
end
|
278
|
+
|
279
|
+
def get(key)
|
280
|
+
root.__send__(:for_path, @path_str) { |cfg,_| cfg.get(key) }
|
281
|
+
end
|
282
|
+
|
283
|
+
def set(key, val)
|
284
|
+
root.__send__(:for_path, @path_str) { |cfg,_| cfg.set(key, val) }
|
285
|
+
end
|
286
|
+
|
287
|
+
def delete(path_str)
|
288
|
+
root.__send__(:for_path, @path_str) { |cfg,_| cfg.delete(path_str) }
|
289
|
+
end
|
290
|
+
|
291
|
+
def rename(old_key, new_key)
|
292
|
+
root.__send__(:for_path, @path_str) { |cfg,_| cfg.rename(old_key, new_key) }
|
293
|
+
end
|
294
|
+
|
295
|
+
def has_entry?(path_str)
|
296
|
+
root.__send__(:for_path, @path_str) { |cfg,_| cfg.has_entry?(path_str) }
|
297
|
+
end
|
298
|
+
|
299
|
+
def has_group?(path_str)
|
300
|
+
root.__send__(:for_path, @path_str) { |cfg,_| cfg.has_group?(path_str) }
|
301
|
+
end
|
302
|
+
|
303
|
+
def read(path_str, output=nil)
|
304
|
+
root.__send__(:for_path, @path_str) { |cfg,_| cfg.read(path_str, output) }
|
305
|
+
end
|
306
|
+
alias :[] :read
|
307
|
+
|
308
|
+
def write(path_str, val)
|
309
|
+
root.__send__(:for_path, @path_str) { |cfg,_| cfg.write(path_str, val) }
|
310
|
+
end
|
311
|
+
alias :[]= :write
|
312
|
+
|
313
|
+
def to_s
|
314
|
+
@path_str
|
315
|
+
end
|
316
|
+
|
317
|
+
def to_h
|
318
|
+
root.__send__(:for_path, @path_str) { |cfg,_| cfg.to_h }
|
319
|
+
end
|
320
|
+
|
321
|
+
end
|
322
|
+
|
323
|
+
end
|
324
|
+
|
325
|
+
class Config < ConfigBase
|
326
|
+
|
327
|
+
include ConfigBase::Interface
|
328
|
+
|
329
|
+
module Interface
|
330
|
+
|
25
331
|
def each_entry(&block)
|
26
332
|
if block_given?
|
27
|
-
|
333
|
+
data.select { |_,v| !v.is_a?(::Hash) }.each(&block)
|
28
334
|
else
|
29
|
-
::Enumerator.new { |y|
|
335
|
+
::Enumerator.new { |y| data.each_pair { |k,v| y << [k, expand(v)] unless v.is_a?(::Hash) } }
|
30
336
|
end
|
31
337
|
end
|
32
338
|
|
33
339
|
def each_group(&block)
|
34
340
|
if block_given?
|
35
|
-
|
341
|
+
data.select { |_,g| g.is_a?(::Hash) }.each { |k,_| block.call(k, Group.new(self, self.path.dup.push(k))) }
|
36
342
|
else
|
37
|
-
::Enumerator.new { |y|
|
343
|
+
::Enumerator.new { |y| data.each_pair { |k,g| y << [k,Group.new(self, self.path.dup.push(k))] if g.is_a?(::Hash) } }
|
38
344
|
end
|
39
345
|
end
|
40
346
|
|
41
|
-
def number_of_entries(recurse
|
347
|
+
def number_of_entries(recurse=false)
|
42
348
|
if recurse
|
43
|
-
each_group.inject(each_entry.inject(0) { |c, _| c + 1 }) { |c, (_, g)| c + g.number_of_entries(
|
349
|
+
each_group.inject(each_entry.inject(0) { |c, _| c + 1 }) { |c, (_, g)| c + g.number_of_entries(true) }
|
44
350
|
else
|
45
351
|
each_entry.inject(0) { |c, _| c + 1 }
|
46
352
|
end
|
47
353
|
end
|
48
354
|
|
49
|
-
def number_of_groups(recurse
|
355
|
+
def number_of_groups(recurse=false)
|
50
356
|
if recurse
|
51
|
-
each_group.inject(0) { |c, (_,g)| c + 1 + g.number_of_groups(
|
357
|
+
each_group.inject(0) { |c, (_,g)| c + 1 + g.number_of_groups(true) }
|
52
358
|
else
|
53
359
|
each_group.inject(0) { |c, _| c + 1 }
|
54
360
|
end
|
@@ -59,11 +365,9 @@ module Wx
|
|
59
365
|
return false if segments.empty?
|
60
366
|
entry = segments.pop
|
61
367
|
group_data = if segments.empty?
|
62
|
-
|
368
|
+
data
|
63
369
|
else
|
64
|
-
unless abs || root?
|
65
|
-
segments = self.path + segments
|
66
|
-
end
|
370
|
+
segments = self.path + segments unless abs || root?
|
67
371
|
get_group_at(segments)
|
68
372
|
end
|
69
373
|
!!(group_data && group_data.has_key?(entry) && !group_data[entry].is_a?(::Hash))
|
@@ -72,87 +376,112 @@ module Wx
|
|
72
376
|
def has_group?(path_str)
|
73
377
|
segments, abs = get_path(path_str)
|
74
378
|
return root? if segments.empty?
|
75
|
-
unless abs || root?
|
76
|
-
segments = self.path + segments
|
77
|
-
end
|
379
|
+
segments = self.path + segments unless abs || root?
|
78
380
|
!!get_group_at(segments)
|
79
381
|
end
|
80
382
|
|
81
383
|
def get(key)
|
82
384
|
key = key.to_s
|
83
|
-
|
385
|
+
raise ArgumentError, 'No paths allowed' if key.index(ConfigBase::SEPARATOR)
|
386
|
+
elem = data[key]
|
84
387
|
if elem.is_a?(::Hash)
|
85
|
-
Group.new(self, self.path.dup.push(key)
|
388
|
+
Group.new(self, self.path.dup.push(key))
|
86
389
|
else
|
87
|
-
elem
|
390
|
+
expand(elem)
|
88
391
|
end
|
89
392
|
end
|
90
393
|
|
91
394
|
def set(key, val)
|
92
395
|
key = key.to_s
|
93
|
-
|
94
|
-
|
396
|
+
raise ArgumentError, 'No paths allowed' if key.index(ConfigBase::SEPARATOR)
|
397
|
+
hsh = data
|
398
|
+
exist = hsh.has_key?(key)
|
399
|
+
elem = exist ? hsh[key] : nil
|
95
400
|
if val.nil?
|
96
|
-
|
401
|
+
hsh.delete(key) if exist
|
97
402
|
nil
|
98
403
|
elsif val.is_a?(::Hash)
|
99
404
|
raise ArgumentError, 'Cannot change existing value entry to group.' if exist && !elem.is_a?(::Hash)
|
100
|
-
|
101
|
-
group = Group.new(self, self.path.dup.push(key)
|
405
|
+
hsh[key] = {} unless elem
|
406
|
+
group = Group.new(self, self.path.dup.push(key))
|
102
407
|
val.each_pair { |k, v| group.set(k, v) }
|
103
408
|
group
|
104
409
|
else
|
105
410
|
raise ArgumentError, 'Cannot change existing group to value entry.' if exist && elem.is_a?(::Hash)
|
106
|
-
|
411
|
+
hsh[key] = val
|
107
412
|
end
|
108
413
|
end
|
109
414
|
|
110
|
-
def delete(
|
111
|
-
|
415
|
+
def delete(path_str)
|
416
|
+
segments, abs = get_path(path_str)
|
417
|
+
return nil if segments.empty?
|
418
|
+
last = segments.pop
|
419
|
+
group_data = if segments.empty?
|
420
|
+
data
|
421
|
+
else
|
422
|
+
segments = self.path + segments unless abs || root?
|
423
|
+
get_group_at(segments, create_missing_groups: false)
|
424
|
+
end
|
425
|
+
group_data ? group_data.delete(last) : nil
|
112
426
|
end
|
113
427
|
|
114
428
|
def rename(old_key, new_key)
|
115
429
|
old_key = old_key.to_s
|
116
430
|
new_key = new_key.to_s
|
117
|
-
if
|
118
|
-
|
431
|
+
raise ArgumentError, 'No paths allowed' if old_key.index(ConfigBase::SEPARATOR) || new_key.index(ConfigBase::SEPARATOR)
|
432
|
+
hsh = data
|
433
|
+
if hsh.has_key?(old_key) && !hsh.has_key?(new_key)
|
434
|
+
hsh[new_key] = hsh.delete(old_key)
|
119
435
|
true
|
120
436
|
else
|
121
437
|
false
|
122
438
|
end
|
123
439
|
end
|
124
440
|
|
125
|
-
def
|
441
|
+
def read(path_str, output=nil)
|
126
442
|
segments, abs = get_path(path_str)
|
127
443
|
return nil if segments.empty?
|
128
444
|
last = segments.pop
|
129
445
|
group_data = if segments.empty?
|
130
|
-
|
446
|
+
segments = self.path.dup unless abs || root?
|
447
|
+
data
|
131
448
|
else
|
132
|
-
unless abs || root?
|
133
|
-
|
134
|
-
end
|
135
|
-
get_group_at(segments, create_missing_groups: true)
|
449
|
+
segments = self.path + segments unless abs || root?
|
450
|
+
get_group_at(segments)
|
136
451
|
end
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
Group.new(self, segments.dup.push(last)
|
452
|
+
val = group_data ? group_data[last] : nil
|
453
|
+
if val.is_a?(::Hash)
|
454
|
+
raise TypeError, "Cannot convert group" unless output.nil?
|
455
|
+
Group.new(self, segments.dup.push(last))
|
141
456
|
else
|
142
|
-
|
457
|
+
val = expand(val)
|
458
|
+
return val unless val && output
|
459
|
+
case
|
460
|
+
when ::String == output || ::String === output
|
461
|
+
val.to_s
|
462
|
+
when ::Integer == output || ::Integer === output
|
463
|
+
Kernel.Integer(val)
|
464
|
+
when ::Float == output || ::Float === output
|
465
|
+
Kernel.Float(val)
|
466
|
+
when ::TrueClass == output || ::FalseClass == output || output == true || output == false
|
467
|
+
val.is_a?(::Integer) ? val != 0 : !!val
|
468
|
+
else
|
469
|
+
raise ArgumentError, "Unknown coercion type #{output.is_a?(::Class) ? output : output.class}" unless output.nil? || output.is_a?(::Proc)
|
470
|
+
output ? output.call(val) : val
|
471
|
+
end
|
143
472
|
end
|
144
473
|
end
|
474
|
+
alias :[] :read
|
145
475
|
|
146
|
-
def
|
476
|
+
def write(path_str, val)
|
147
477
|
segments, abs = get_path(path_str)
|
148
478
|
return false if segments.empty?
|
149
479
|
last = segments.pop
|
150
480
|
group_data = if segments.empty?
|
151
|
-
|
481
|
+
segments = self.path.dup unless abs || root?
|
482
|
+
data
|
152
483
|
else
|
153
|
-
unless abs || root?
|
154
|
-
segments = self.path + segments
|
155
|
-
end
|
484
|
+
segments = self.path + segments unless abs || root?
|
156
485
|
get_group_at(segments, create_missing_groups: true)
|
157
486
|
end
|
158
487
|
raise ArgumentError, "Unable to resolve path #{segments+[last]}" unless group_data
|
@@ -163,61 +492,80 @@ module Wx
|
|
163
492
|
nil
|
164
493
|
elsif val.is_a?(::Hash)
|
165
494
|
raise ArgumentError, 'Cannot change existing value entry to group.' if exist && !elem.is_a?(::Hash)
|
166
|
-
|
167
|
-
group = Group.new(self, segments.dup.push(last)
|
168
|
-
val.each_pair { |
|
495
|
+
group_data[last] = {} unless elem
|
496
|
+
group = Group.new(self, segments.dup.push(last))
|
497
|
+
val.each_pair { |k, v| group.set(k, v) }
|
169
498
|
group
|
170
499
|
else
|
171
500
|
raise ArgumentError, 'Cannot change existing group to value entry.' if exist && elem.is_a?(::Hash)
|
172
|
-
group_data[last] =
|
501
|
+
group_data[last] = val
|
173
502
|
end
|
174
503
|
end
|
504
|
+
alias :[]= :write
|
175
505
|
|
176
506
|
def to_s
|
177
|
-
SEPARATOR+self.path.join(SEPARATOR)
|
507
|
+
ConfigBase::SEPARATOR+self.path.join(ConfigBase::SEPARATOR)
|
178
508
|
end
|
179
509
|
|
180
510
|
def to_h
|
181
|
-
|
511
|
+
data
|
182
512
|
end
|
183
513
|
|
184
514
|
def get_path(path_str)
|
185
515
|
path_str = path_str.to_s
|
186
|
-
abs = path_str.start_with?(SEPARATOR)
|
187
|
-
segs = path_str.split(SEPARATOR)
|
516
|
+
abs = path_str.start_with?(ConfigBase::SEPARATOR)
|
517
|
+
segs = path_str.split(ConfigBase::SEPARATOR)
|
188
518
|
segs.shift if abs
|
189
519
|
[segs, abs]
|
190
520
|
end
|
191
521
|
protected :get_path
|
192
522
|
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
523
|
+
EXPAND_RE = if Wx::PLATFORM == 'WXMSW'
|
524
|
+
/(\\)?([$][{(]?|%)(\w+)([})%])?/
|
525
|
+
else
|
526
|
+
/(\\)?([$][{(]?)(\w+)([})])?/
|
527
|
+
end
|
528
|
+
private_constant :EXPAND_RE
|
529
|
+
|
530
|
+
def expand(val)
|
531
|
+
if root.expanding_env_vars? && ::String === val
|
532
|
+
val.gsub(EXPAND_RE) do |s|
|
533
|
+
if $1.nil? &&
|
534
|
+
(($2[0] == '$' &&
|
535
|
+
($2.size == 1 && $4.nil?) ||
|
536
|
+
($2[1] == '(' && $4 == ')') ||
|
537
|
+
($2[1] == '{' && $4 == '}'))||
|
538
|
+
($2[0] == '%' && $4 == '%')) &&
|
539
|
+
ENV[$3]
|
540
|
+
$1 ? $1+ENV[$3] : ENV[$3]
|
541
|
+
else
|
542
|
+
$1 ? s[1,s.size] : s
|
543
|
+
end
|
204
544
|
end
|
545
|
+
else
|
546
|
+
val
|
205
547
|
end
|
206
548
|
end
|
207
|
-
protected :
|
549
|
+
protected :expand
|
208
550
|
|
209
551
|
end
|
210
552
|
|
211
553
|
class Group
|
212
554
|
|
555
|
+
include ConfigBase::Interface
|
556
|
+
|
213
557
|
include Interface
|
214
558
|
|
215
|
-
def initialize(parent, path
|
559
|
+
def initialize(parent, path)
|
216
560
|
@parent = parent
|
217
561
|
@path = path.freeze
|
218
|
-
@data = data
|
219
562
|
end
|
220
563
|
|
564
|
+
def data
|
565
|
+
self.root.__send__(:get_group_at, @path, create_missing_groups: true, is_pruned: true)
|
566
|
+
end
|
567
|
+
protected :data
|
568
|
+
|
221
569
|
def root?
|
222
570
|
false
|
223
571
|
end
|
@@ -235,7 +583,7 @@ module Wx
|
|
235
583
|
end
|
236
584
|
|
237
585
|
def get_group_at(segments, create_missing_groups: false)
|
238
|
-
root.__send__(:get_group_at, segments)
|
586
|
+
root.__send__(:get_group_at, segments, create_missing_groups: create_missing_groups)
|
239
587
|
end
|
240
588
|
protected :get_group_at
|
241
589
|
|
@@ -244,10 +592,16 @@ module Wx
|
|
244
592
|
include Interface
|
245
593
|
|
246
594
|
def initialize(hash = nil)
|
595
|
+
@expand_env_vars = true
|
247
596
|
@data = {}
|
248
597
|
replace(hash) if hash
|
249
598
|
end
|
250
599
|
|
600
|
+
def data
|
601
|
+
@data
|
602
|
+
end
|
603
|
+
protected :data
|
604
|
+
|
251
605
|
def root?
|
252
606
|
true
|
253
607
|
end
|
@@ -264,6 +618,11 @@ module Wx
|
|
264
618
|
nil
|
265
619
|
end
|
266
620
|
|
621
|
+
def clear
|
622
|
+
@data.clear
|
623
|
+
true
|
624
|
+
end
|
625
|
+
|
267
626
|
def replace(hash)
|
268
627
|
raise ArgumentError, 'Expected Hash' unless hash.is_a?(::Hash)
|
269
628
|
@data.clear
|
@@ -271,19 +630,31 @@ module Wx
|
|
271
630
|
self
|
272
631
|
end
|
273
632
|
|
274
|
-
def
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
633
|
+
def is_expanding_env_vars
|
634
|
+
@expand_env_vars
|
635
|
+
end
|
636
|
+
alias :expanding_env_vars? :is_expanding_env_vars
|
637
|
+
|
638
|
+
def set_expand_env_vars(flag)
|
639
|
+
@expand_env_vars = !!flag
|
640
|
+
end
|
641
|
+
alias :expand_env_vars :set_expand_env_vars
|
642
|
+
|
643
|
+
def get_group_at(segments, create_missing_groups: false, is_pruned: false)
|
644
|
+
unless is_pruned
|
645
|
+
# prune segments (process relative segments)
|
646
|
+
segments = segments.inject([]) do |lst, seg|
|
647
|
+
case seg
|
648
|
+
when '..'
|
649
|
+
lst.pop # remove previous
|
650
|
+
# forget ..
|
651
|
+
when '.'
|
652
|
+
# forget
|
653
|
+
else
|
654
|
+
lst << seg
|
655
|
+
end
|
656
|
+
lst
|
285
657
|
end
|
286
|
-
lst
|
287
658
|
end
|
288
659
|
# find group matching segments
|
289
660
|
segments.inject(@data) do |hsh, seg|
|