rdoba 0.9.1 → 0.9.4
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 +7 -7
- data/.gitignore +4 -0
- data/.travis.yml +28 -0
- data/CHANGES.md +6 -0
- data/Gemfile +5 -0
- data/README.md +87 -108
- data/Rakefile +62 -54
- data/TODO +6 -0
- data/features/mixin.feature +85 -0
- data/features/step_definitions/mixin_steps.rb +305 -0
- data/features/support/env.rb +35 -145
- data/features/support/mixin_support.rb +17 -0
- data/html/.keep +0 -0
- data/lib/rdoba/_version_.rb +3 -1
- data/lib/rdoba/a.rb +44 -42
- data/lib/rdoba/bcd.rb +43 -26
- data/lib/rdoba/blank.rb +14 -0
- data/lib/rdoba/combinations.rb +17 -15
- data/lib/rdoba/common.rb +53 -68
- data/lib/rdoba/debug.rb +9 -3
- data/lib/rdoba/deploy.rb +55 -50
- data/lib/rdoba/dup.rb +31 -31
- data/lib/rdoba/fe.rb +6 -5
- data/lib/rdoba/gem.rb +33 -29
- data/lib/rdoba/hashorder.rb +24 -24
- data/lib/rdoba/io.rb +81 -74
- data/lib/rdoba/merge.rb +21 -0
- data/lib/rdoba/mixin/time.rb +17 -0
- data/lib/rdoba/mixin/try.rb +11 -0
- data/lib/rdoba/mixin/try_1_9_0.rb +9 -0
- data/lib/rdoba/mixin/wait_if.rb +27 -0
- data/lib/rdoba/mixin.rb +373 -52
- data/lib/rdoba/numeric.rb +19 -17
- data/lib/rdoba/os.rb +127 -0
- data/lib/rdoba/re.rb +4 -4
- data/lib/rdoba/require.rb +24 -19
- data/lib/rdoba/roman.rb +32 -22
- data/lib/rdoba/strings.rb +6 -144
- data/lib/rdoba/yaml.rb +20 -18
- data/lib/rdoba.rb +50 -47
- data/rdoba.gemspec +33 -26
- data/tddium.yml +11 -0
- metadata +184 -77
- data/features/bcd.feature +0 -29
- data/features/log.feature +0 -206
- data/features/step_definitions/bcd_steps.rb +0 -69
- data/features/step_definitions/log_steps.rb +0 -164
- data/lib/rdoba/log.rb +0 -248
- data/test/helper.rb +0 -18
- data/test/rdoba_test.rb.stub +0 -59
- data/test/test_rdoba.rb +0 -7
data/lib/rdoba/mixin.rb
CHANGED
@@ -1,57 +1,378 @@
|
|
1
1
|
#!/usr/bin/ruby -KU
|
2
|
-
#
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
class String
|
5
|
+
# TODO: obsolete
|
6
|
+
ByteByByte = 0
|
7
|
+
FirstChar = 1
|
8
|
+
end
|
3
9
|
|
4
10
|
module Rdoba
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
11
|
+
module Mixin
|
12
|
+
class InvalidOption < StandardError
|
13
|
+
end
|
14
|
+
|
15
|
+
module CompareString
|
16
|
+
def compare_to(value, opts = {})
|
17
|
+
if opts == :ignore_diacritics || opts.instance_of?(Hash) && opts.key?(:ignore_diacritics)
|
18
|
+
# TODO: verify composite range
|
19
|
+
def crop_diacritics(x)
|
20
|
+
(x < 0x300 || x > 0x36f && x < 0x483 || x > 0x487 && x < 0xa67c || x > 0xa67d) && x || nil
|
21
|
+
end
|
22
|
+
|
23
|
+
(unpack('U*').map do |x| crop_diacritics(x)end.compact) <=>
|
24
|
+
(value.unpack('U*').map do |x| crop_diacritics(x)end.compact)
|
25
|
+
else
|
26
|
+
self <=> value
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
module ReverseString
|
32
|
+
Fixups = [:reverse]
|
33
|
+
|
34
|
+
Aliases = { __rdoba_mixin_reverse_orig__: :reverse }
|
35
|
+
|
36
|
+
def __rdoba_mixin_reverse__(step = 1)
|
37
|
+
if (!step.is_a?(Numeric) || step < 0) && step != :byte_by_byte
|
38
|
+
raise "Invalid step value #{step.inspect}"
|
39
|
+
end
|
40
|
+
|
41
|
+
if [:byte_by_byte, String::ByteByByte].include?(step)
|
42
|
+
arr = []
|
43
|
+
each_byte do |byte|
|
44
|
+
arr << byte.chr
|
45
|
+
end
|
46
|
+
arr.reverse.join.force_encoding(encoding)
|
47
|
+
elsif step == 1
|
48
|
+
__rdoba_mixin_reverse_orig__
|
49
|
+
elsif step > 1
|
50
|
+
res = ''
|
51
|
+
offset = (size + 1) / step * step - step
|
52
|
+
(0..offset).step(step) do |shift|
|
53
|
+
res += self[offset - shift..offset - shift + 1]
|
54
|
+
end
|
55
|
+
res
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
module CaseString
|
61
|
+
Fixups = %i[upcase downcase]
|
62
|
+
|
63
|
+
Aliases = { __rdoba_mixin_upcase_orig__: :upcase, __rdoba_mixin_downcase_orig__: :downcase }
|
64
|
+
|
65
|
+
ConvertTable = {
|
66
|
+
up: {
|
67
|
+
ranges: [
|
68
|
+
{ ords: [(0xE0..0xFF), (0x3B1..0x3CB), (0x430..0x44F)], change: proc { |chr, _value| chr -= 0x20 } },
|
69
|
+
{ ords: [(0x3AC..0x3AC)], change: proc { |ord| ord -= 0x26 } },
|
70
|
+
{ ords: [(0x3AD..0x3AF)], change: proc { |ord| ord -= 0x25 } },
|
71
|
+
{ ords: [(0x3B0..0x3B0)], change: proc { |ord| ord -= 0x22 } },
|
72
|
+
{
|
73
|
+
ords: [
|
74
|
+
(0x1F00..0x1F07),
|
75
|
+
(0x1F10..0x1F17),
|
76
|
+
(0x1F20..0x1F27),
|
77
|
+
(0x1F30..0x1F37),
|
78
|
+
(0x1F40..0x1F47),
|
79
|
+
(0x1F50..0x1F57),
|
80
|
+
(0x1F60..0x1F67),
|
81
|
+
(0x1F80..0x1F87),
|
82
|
+
(0x1F90..0x1F97),
|
83
|
+
(0x1Fa0..0x1Fa7),
|
84
|
+
(0x1Fb0..0x1Fb3)
|
85
|
+
],
|
86
|
+
change: proc { |ord| ord += 0x8 }
|
87
|
+
},
|
88
|
+
{ ords: [(0x450..0x45F)], change: proc { |ord| ord -= 0x50 } },
|
89
|
+
{
|
90
|
+
ords: [
|
91
|
+
(0x100..0x1B9),
|
92
|
+
(0x1C4..0x233),
|
93
|
+
(0x460..0x481),
|
94
|
+
(0x48A..0x523),
|
95
|
+
(0x1E00..0x1E95),
|
96
|
+
(0x1EA0..0x1EFF),
|
97
|
+
(0x0A642..0xA667),
|
98
|
+
(0x0A680..0x0A697),
|
99
|
+
(0xA722..0xA7A9)
|
100
|
+
],
|
101
|
+
change: proc { |ord| ord.odd? && (ord - 1) || ord }
|
102
|
+
}
|
103
|
+
],
|
104
|
+
default:
|
105
|
+
proc do |ord|
|
106
|
+
[ord].pack('U').__rdoba_mixin_upcase_orig__
|
107
|
+
end
|
108
|
+
},
|
109
|
+
down: {
|
110
|
+
ranges: [
|
111
|
+
{ ords: [(0xC0..0xDF), (0x391..0x3AB), (0x410..0x42F)], change: proc { |chr, _value| chr += 0x20 } },
|
112
|
+
{ ords: [(0x386..0x386)], change: proc { |ord| ord += 0x26 } },
|
113
|
+
{ ords: [(0x388..0x38A)], change: proc { |ord| ord += 0x25 } },
|
114
|
+
{ ords: [(0x38E..0x38E)], change: proc { |ord| ord += 0x22 } },
|
115
|
+
{
|
116
|
+
ords: [
|
117
|
+
(0x1F08..0x1F0F),
|
118
|
+
(0x1F18..0x1F1F),
|
119
|
+
(0x1F28..0x1F2F),
|
120
|
+
(0x1F38..0x1F3F),
|
121
|
+
(0x1F48..0x1F4F),
|
122
|
+
(0x1F58..0x1F5F),
|
123
|
+
(0x1F68..0x1F6F),
|
124
|
+
(0x1F88..0x1F8F),
|
125
|
+
(0x1F98..0x1F9F),
|
126
|
+
(0x1Fa8..0x1FaF),
|
127
|
+
(0x1Fb8..0x1FbA)
|
128
|
+
],
|
129
|
+
change: proc { |ord| ord -= 0x8 }
|
130
|
+
},
|
131
|
+
{ ords: [(0x400..0x40F)], change: proc { |ord| ord += 0x50 } },
|
132
|
+
{
|
133
|
+
ords: [
|
134
|
+
(0x100..0x1B9),
|
135
|
+
(0x1C4..0x233),
|
136
|
+
(0x450..0x481),
|
137
|
+
(0x48A..0x523),
|
138
|
+
(0x1E00..0x1E95),
|
139
|
+
(0x1EA0..0x1EFF),
|
140
|
+
(0x0A642..0xA667),
|
141
|
+
(0x0A680..0x0A697),
|
142
|
+
(0xA722..0xA7A9)
|
143
|
+
],
|
144
|
+
change: proc { |ord| ord.even? && (ord + 1) || ord }
|
145
|
+
}
|
146
|
+
],
|
147
|
+
default:
|
148
|
+
proc do |ord|
|
149
|
+
[ord].pack('U').__rdoba_mixin_downcase_orig__
|
150
|
+
end
|
151
|
+
}
|
152
|
+
}
|
153
|
+
|
154
|
+
def self.change_case_char(dest, char)
|
155
|
+
ord = char.is_a?(String) ? char.ord : char.to_i
|
156
|
+
table = ConvertTable[dest]
|
157
|
+
nord =
|
158
|
+
table[:ranges].each do |range|
|
159
|
+
c =
|
160
|
+
range[:ords].each do |r|
|
161
|
+
if r.include?(ord)
|
162
|
+
break false
|
163
|
+
end
|
164
|
+
end
|
165
|
+
unless c
|
166
|
+
break range[:change].call ord
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
unless nord.is_a? Numeric
|
171
|
+
return table[:default].call ord
|
172
|
+
end
|
173
|
+
|
174
|
+
[nord].pack('U')
|
175
|
+
end
|
176
|
+
|
177
|
+
def self.up_char(char)
|
178
|
+
CaseString.change_case_char :up, char
|
179
|
+
end
|
180
|
+
|
181
|
+
def self.downcase_char(char)
|
182
|
+
CaseString.change_case_char :down, char
|
183
|
+
end
|
184
|
+
|
185
|
+
if RUBY_VERSION < '1.9'
|
186
|
+
alias setbyte []=
|
187
|
+
|
188
|
+
def encoding
|
189
|
+
'UTF-8'
|
190
|
+
end
|
56
191
|
|
192
|
+
def force_encoding(*_args)
|
193
|
+
self
|
194
|
+
end
|
57
195
|
|
196
|
+
def ord
|
197
|
+
a = nil
|
198
|
+
each_byte do |b|
|
199
|
+
case (b & 0xC0)
|
200
|
+
when 0xc0
|
201
|
+
a = (b & 0x3F)
|
202
|
+
when 0x80
|
203
|
+
return (a << 6) + (b & 0x3F)
|
204
|
+
else
|
205
|
+
return b
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
def __rdoba_mixin_downcase__(options = {})
|
212
|
+
__rdoba_mixin_changecase__ :down, options
|
213
|
+
end
|
214
|
+
|
215
|
+
def __rdoba_mixin_upcase__(options = {})
|
216
|
+
__rdoba_mixin_changecase__ :up, options
|
217
|
+
end
|
218
|
+
|
219
|
+
def __rdoba_mixin_changecase__(reg, options = {})
|
220
|
+
unless %i[up down].include? reg
|
221
|
+
return self
|
222
|
+
end
|
223
|
+
|
224
|
+
re = Regexp.new '[\x80-\xFF]', nil, 'n'
|
225
|
+
if options == String::FirstChar || options.include?(:first_char)
|
226
|
+
r = dup
|
227
|
+
r[0] = CaseString.change_case_char reg, ord
|
228
|
+
r
|
229
|
+
elsif dup.force_encoding('ASCII-8BIT').match re
|
230
|
+
unpack('U*').map do |chr|
|
231
|
+
CaseString.change_case_char reg, chr
|
232
|
+
end.join
|
233
|
+
elsif reg == :up
|
234
|
+
__rdoba_mixin_upcase_orig__
|
235
|
+
else
|
236
|
+
__rdoba_mixin_downcase_orig__
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
module To_hArray
|
242
|
+
def to_h(options = {})
|
243
|
+
h = {}
|
244
|
+
each do |v|
|
245
|
+
if v.is_a? Array
|
246
|
+
if h.key? v[0]
|
247
|
+
unless h[v[0]].is_a? Array
|
248
|
+
h[v[0]] = [h[v[0]]]
|
249
|
+
end
|
250
|
+
|
251
|
+
if v.size > 2
|
252
|
+
h[v[0]].concat v[1..-1]
|
253
|
+
else
|
254
|
+
h[v[0]] << v[1]
|
255
|
+
end
|
256
|
+
else
|
257
|
+
h[v[0]] = v.size > 2 && v[1..-1] || v[1]
|
258
|
+
end
|
259
|
+
elsif h.key? v
|
260
|
+
unless h[v].is_a? Array
|
261
|
+
h[v] = [h[v]]
|
262
|
+
end
|
263
|
+
|
264
|
+
h[v] << v
|
265
|
+
else
|
266
|
+
h[v] = nil
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
if options[:save_unique]
|
271
|
+
h.each_pair do |_k, v|
|
272
|
+
if v.is_a? Array
|
273
|
+
v.uniq!
|
274
|
+
end
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
h
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
module Split_byArray
|
283
|
+
#
|
284
|
+
# +split_by+ method splits the +self+ array by a condition,
|
285
|
+
# which is evaliated in a passed block, in two versions that are
|
286
|
+
# the return value. Usage:
|
287
|
+
#
|
288
|
+
# require 'rdoba'
|
289
|
+
#
|
290
|
+
# rdoba mixin: :split_by
|
291
|
+
#
|
292
|
+
# (first, second) = [0,1,2,3].split_by { |value| value % 2 == 0 }
|
293
|
+
# first # => [0,2]
|
294
|
+
# second # => [1,3]
|
295
|
+
#
|
296
|
+
def split_by
|
297
|
+
idxs = []
|
298
|
+
rejected = reject.with_index do |v, i| yield(v) && (idxs << i)end
|
299
|
+
[values_at(*idxs), rejected]
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
module EmptyObject
|
304
|
+
def empty?
|
305
|
+
false
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
module EmptyNilClass
|
310
|
+
def empty?
|
311
|
+
true
|
312
|
+
end
|
313
|
+
end
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
if RUBY_VERSION >= '2.0.0'
|
318
|
+
require_relative 'mixin/try'
|
319
|
+
else
|
320
|
+
require_relative 'mixin/try_1_9_0'
|
321
|
+
end
|
322
|
+
|
323
|
+
require_relative 'mixin/wait_if'
|
324
|
+
|
325
|
+
module Rdoba
|
326
|
+
def self.mixin(options)
|
327
|
+
[options[:value]].flatten.each do |value|
|
328
|
+
case value
|
329
|
+
when :case
|
330
|
+
Mixin::CaseString::Aliases.each do |k, v|
|
331
|
+
::String.send :alias_method, k, v
|
332
|
+
end
|
333
|
+
Mixin::CaseString::Fixups.each do |e|
|
334
|
+
::String.class_eval "def #{e}(*args);self.__rdoba_mixin_#{e}__(*args);end", __FILE__, __LINE__
|
335
|
+
end
|
336
|
+
::String.include Mixin::CaseString
|
337
|
+
when :reverse
|
338
|
+
Mixin::ReverseString::Aliases.each do |k, v|
|
339
|
+
::String.send :alias_method, k, v
|
340
|
+
end
|
341
|
+
Mixin::ReverseString::Fixups.each do |e|
|
342
|
+
::String.class_eval "def #{e}(*args);self.__rdoba_mixin_#{e}__(*args);end", __FILE__, __LINE__
|
343
|
+
end
|
344
|
+
String.include Mixin::ReverseString
|
345
|
+
when :compare
|
346
|
+
String.include Mixin::CompareString
|
347
|
+
when :to_h
|
348
|
+
if [].respond_to?(:to_h)
|
349
|
+
m = Mixin::To_hArray.instance_method(:to_h)
|
350
|
+
Array.send(:define_method, :to_h, m)
|
351
|
+
else
|
352
|
+
Array.include Mixin::To_hArray
|
353
|
+
end
|
354
|
+
when :time
|
355
|
+
require_relative 'mixin/time'
|
356
|
+
if File.respond_to?(:mtime)
|
357
|
+
%i[mtime atime ctime].each do |name|
|
358
|
+
m = Mixin::Time.instance_method(name)
|
359
|
+
::File.send(:define_singleton_method, name, m)
|
360
|
+
end
|
361
|
+
else
|
362
|
+
::File.extend Mixin::Time
|
363
|
+
end
|
364
|
+
when :wait_if
|
365
|
+
Object.include Mixin::Wait_ifKernel
|
366
|
+
when :split_by
|
367
|
+
Array.include Mixin::Split_byArray
|
368
|
+
when :try
|
369
|
+
Object.include Mixin::TryObject
|
370
|
+
when :empty
|
371
|
+
Object.include Mixin::EmptyObject
|
372
|
+
NilClass.include Mixin::EmptyNilClass
|
373
|
+
else
|
374
|
+
raise(Mixin::InvalidOption, 'Invalid rdoba-mixin options key: ' + value.to_s)
|
375
|
+
end
|
376
|
+
end
|
377
|
+
end
|
378
|
+
end
|
data/lib/rdoba/numeric.rb
CHANGED
@@ -1,20 +1,20 @@
|
|
1
1
|
#!/usr/bin/ruby -KU
|
2
|
-
#
|
2
|
+
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require 'rdoba/common'
|
5
5
|
require 'rdoba/strings'
|
6
6
|
|
7
7
|
class String
|
8
|
-
alias
|
8
|
+
alias _rdoba_to_i to_i
|
9
9
|
def to_i(base = 10, *opts)
|
10
10
|
v = parse_opts(opts)
|
11
11
|
if v[:be]
|
12
|
-
|
12
|
+
str, sign, num = (match /\s*(-?)([0-9a-fx]+)/u).to_a
|
13
13
|
if str
|
14
|
-
|
15
|
-
|
14
|
+
n = num.reverse._rdoba_to_i(base)
|
15
|
+
sign.empty? && n || -n
|
16
16
|
else
|
17
|
-
|
17
|
+
0
|
18
18
|
end
|
19
19
|
else
|
20
20
|
_rdoba_to_i(base)
|
@@ -22,8 +22,8 @@ class String
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
-
class
|
26
|
-
alias
|
25
|
+
class Integer
|
26
|
+
alias _rdoba_to_s to_s
|
27
27
|
def to_s(base = 10, *opts)
|
28
28
|
v = parse_opts(opts)
|
29
29
|
|
@@ -31,8 +31,10 @@ class Fixnum
|
|
31
31
|
|
32
32
|
raise "Base of number can't be equal or less then zero" if base <= 0
|
33
33
|
raise "Padding count numberr can't be equal or less then zero" if v[:padding] <= 0
|
34
|
+
|
34
35
|
value = self
|
35
|
-
minus =
|
36
|
+
minus =
|
37
|
+
if value < 0
|
36
38
|
value = -value
|
37
39
|
true
|
38
40
|
end
|
@@ -42,7 +44,7 @@ class Fixnum
|
|
42
44
|
rem += 0x40 - 0x39 if rem >= 10
|
43
45
|
res += (0x30 + rem).chr
|
44
46
|
end
|
45
|
-
res +=
|
47
|
+
res += '0' * (v[:padding].to_i - res.size) if res.size < v[:padding].to_i
|
46
48
|
res += 'x0' if v[:style_formatting] and base == 16
|
47
49
|
res += '-' if minus
|
48
50
|
res.reverse
|
@@ -54,7 +56,8 @@ class Numeric
|
|
54
56
|
v = parse_opts(opts)
|
55
57
|
|
56
58
|
value = self
|
57
|
-
minus =
|
59
|
+
minus =
|
60
|
+
if value < 0
|
58
61
|
value = -value
|
59
62
|
true
|
60
63
|
end
|
@@ -64,12 +67,14 @@ class Numeric
|
|
64
67
|
res += rem.chr
|
65
68
|
end
|
66
69
|
|
67
|
-
pad_char =
|
70
|
+
pad_char =
|
71
|
+
if minus
|
68
72
|
negres += ''
|
69
73
|
over = 1
|
70
74
|
res.each_byte do |byte|
|
71
75
|
negbyte = 255 - byte + over
|
72
|
-
negres +=
|
76
|
+
negres +=
|
77
|
+
if negbyte > 255
|
73
78
|
over = 1
|
74
79
|
0
|
75
80
|
else
|
@@ -85,9 +90,6 @@ class Numeric
|
|
85
90
|
|
86
91
|
res += pad_char * (v[:padding].to_i - res.size) if res.size < v[:padding].to_i
|
87
92
|
|
88
|
-
|
89
|
-
plain
|
93
|
+
(v[:be] ? res.reverse(String::ByteByByte) : res).to_p
|
90
94
|
end
|
91
95
|
end
|
92
|
-
|
93
|
-
|
data/lib/rdoba/os.rb
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
3
|
+
require 'rdoba/blank'
|
4
|
+
|
5
|
+
class Object
|
6
|
+
def to_os
|
7
|
+
OpenStruct.new(self.to_h.map {|(x, y)| [x.to_s, [Hash, Array].include?(y.class) && y.to_os || y] }.to_h)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class Array
|
12
|
+
def to_os
|
13
|
+
OpenStruct.new(self.map.with_index {|y, x| [x.to_s, [Hash, Array].include?(y.class) && y.to_os || y] }.to_h)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class Integer
|
18
|
+
def to_sym
|
19
|
+
to_s.to_sym
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class OpenStruct
|
24
|
+
def merge_to other
|
25
|
+
OpenStruct.new(other.to_h.merge(self.to_h))
|
26
|
+
end
|
27
|
+
|
28
|
+
def merge other
|
29
|
+
OpenStruct.new(self.to_h.merge(other.to_h))
|
30
|
+
end
|
31
|
+
|
32
|
+
def map *args, &block
|
33
|
+
res = self.class.new
|
34
|
+
|
35
|
+
self.each_pair do |key, value|
|
36
|
+
res[key] = block[key, value]
|
37
|
+
end
|
38
|
+
|
39
|
+
res
|
40
|
+
end
|
41
|
+
|
42
|
+
def select &block
|
43
|
+
res = self.class.new
|
44
|
+
|
45
|
+
self.each_pair do |key, value|
|
46
|
+
res[key] = value if block[key, value]
|
47
|
+
end
|
48
|
+
|
49
|
+
res
|
50
|
+
end
|
51
|
+
|
52
|
+
def compact
|
53
|
+
select { |_, value| !value.blank? }
|
54
|
+
end
|
55
|
+
|
56
|
+
def each *args, &block
|
57
|
+
self.each_pair(*args, &block)
|
58
|
+
end
|
59
|
+
|
60
|
+
def reduce default = nil, &block
|
61
|
+
res = default
|
62
|
+
|
63
|
+
self.each_pair do |key, value|
|
64
|
+
res = block[res, key, value]
|
65
|
+
end
|
66
|
+
|
67
|
+
res
|
68
|
+
end
|
69
|
+
|
70
|
+
# +deep_merge+ deeply merges the Open Struct hash structure with the +other_in+ enumerating it key by key.
|
71
|
+
# +options+ are the options to change behaviour of the method. It allows two keys: :mode, and :dedup
|
72
|
+
# :mode key can be :append, :prepend, or :replace, defaulting to :append, when mode is to append, it combines duplicated
|
73
|
+
# keys' values into an array, when :prepend it prepends an other value before previously stored one unlike for :append mode,
|
74
|
+
# when :replace it replace duplicate values with a last ones.
|
75
|
+
# :dedup key can be true, or false. It allows to deduplicate values when appending or prepending values.
|
76
|
+
# Examples:
|
77
|
+
# open_struct.deep_merge(other_open_struct)
|
78
|
+
# open_struct.deep_merge(other_open_struct, :prepend)
|
79
|
+
#
|
80
|
+
def deep_merge other_in, options_in = {}
|
81
|
+
return self if other_in.nil? or other_in.blank?
|
82
|
+
|
83
|
+
options = { mode: :append }.merge(options_in)
|
84
|
+
|
85
|
+
other =
|
86
|
+
if other_in.is_a?(OpenStruct)
|
87
|
+
other_in.dup
|
88
|
+
elsif other_in.is_a?(Hash)
|
89
|
+
other_in.to_os
|
90
|
+
else
|
91
|
+
OpenStruct.new(nil => other_in)
|
92
|
+
end
|
93
|
+
|
94
|
+
self.reduce(other) do |res, key, value|
|
95
|
+
res[key] =
|
96
|
+
if res.table.keys.include?(key)
|
97
|
+
case value
|
98
|
+
when Hash, OpenStruct
|
99
|
+
value.deep_merge(res[key], options)
|
100
|
+
when Array
|
101
|
+
value.concat([res[key]].compact.flatten(1))
|
102
|
+
when NilClass
|
103
|
+
res[key]
|
104
|
+
else
|
105
|
+
value_out =
|
106
|
+
if options[:mode] == :append
|
107
|
+
[res[key], value].compact.flatten(1)
|
108
|
+
elsif options[:mode] == :prepend
|
109
|
+
[value, res[key]].compact.flatten(1)
|
110
|
+
else
|
111
|
+
value
|
112
|
+
end
|
113
|
+
|
114
|
+
if value_out.is_a?(Array) && options[:dedup]
|
115
|
+
value_out.uniq
|
116
|
+
else
|
117
|
+
value_out
|
118
|
+
end
|
119
|
+
end
|
120
|
+
else
|
121
|
+
value
|
122
|
+
end
|
123
|
+
|
124
|
+
res
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
data/lib/rdoba/re.rb
CHANGED
@@ -1,13 +1,14 @@
|
|
1
1
|
#!/usr/bin/ruby -KU
|
2
|
-
#
|
2
|
+
# frozen_string_literal: true
|
3
3
|
|
4
4
|
class String
|
5
5
|
def to_res
|
6
|
-
ostr =
|
6
|
+
ostr = dup
|
7
7
|
res = ''
|
8
8
|
while true
|
9
|
-
m = ostr.match(
|
9
|
+
m = ostr.match(%r{(?:([+\[\]\\().*?{}^$/|])|«([^«]*)»)}u)
|
10
10
|
break unless m
|
11
|
+
|
11
12
|
res += m.pre_match + (m[2] || m[1] && ('\\' + m[1]))
|
12
13
|
ostr = m.post_match
|
13
14
|
end
|
@@ -19,4 +20,3 @@ class String
|
|
19
20
|
/#{to_res}/ui
|
20
21
|
end
|
21
22
|
end
|
22
|
-
|