rdoba 0.9.1 → 0.9.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
|