kronk 1.2.5 → 1.3.0
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.
- data/.gemtest +0 -0
- data/History.rdoc +30 -2
- data/Manifest.txt +14 -0
- data/README.rdoc +5 -7
- data/Rakefile +88 -4
- data/bin/kronk +2 -1
- data/bin/yzma +13 -0
- data/lib/kronk.rb +112 -430
- data/lib/kronk/cmd.rb +469 -0
- data/lib/kronk/data_set.rb +38 -44
- data/lib/kronk/diff.rb +105 -112
- data/lib/kronk/diff/ascii_format.rb +35 -0
- data/lib/kronk/diff/color_format.rb +49 -0
- data/lib/kronk/request.rb +6 -6
- data/lib/kronk/test.rb +15 -0
- data/lib/kronk/test/assertions.rb +97 -0
- data/lib/kronk/test/core_ext.rb +65 -0
- data/lib/kronk/test/helper_methods.rb +86 -0
- data/lib/yzma.rb +174 -0
- data/lib/yzma/randomizer.rb +54 -0
- data/lib/yzma/report.rb +47 -0
- data/test/test_assertions.rb +93 -0
- data/test/test_core_ext.rb +74 -0
- data/test/test_data_set.rb +41 -32
- data/test/test_diff.rb +50 -24
- data/test/test_helper_methods.rb +177 -0
- data/test/test_kronk.rb +3 -1
- metadata +36 -19
data/lib/kronk/data_set.rb
CHANGED
@@ -19,22 +19,6 @@ class Kronk
|
|
19
19
|
end
|
20
20
|
|
21
21
|
|
22
|
-
##
|
23
|
-
# Retrieves the data at the given path array.
|
24
|
-
|
25
|
-
def data_at_path path
|
26
|
-
self.class.data_at_path @data, path
|
27
|
-
end
|
28
|
-
|
29
|
-
|
30
|
-
##
|
31
|
-
# Checks if data is available at the given path.
|
32
|
-
|
33
|
-
def data_at_path? path
|
34
|
-
self.class.data_at_path? @data, path
|
35
|
-
end
|
36
|
-
|
37
|
-
|
38
22
|
##
|
39
23
|
# Modify the data object by passing inclusive or exclusive data paths.
|
40
24
|
# Supports the following options:
|
@@ -85,6 +69,10 @@ class Kronk
|
|
85
69
|
new_curr_data[key] = curr_data[key]
|
86
70
|
break
|
87
71
|
|
72
|
+
elsif path.length == 1 && affect_parent
|
73
|
+
new_data = curr_data
|
74
|
+
break
|
75
|
+
|
88
76
|
else
|
89
77
|
new_curr_data[key] ||= curr_data[key].class.new
|
90
78
|
new_curr_data = new_curr_data[key]
|
@@ -106,6 +94,8 @@ class Kronk
|
|
106
94
|
find_data data_path do |obj, k, path|
|
107
95
|
|
108
96
|
if affect_parent && data_at_path?(path)
|
97
|
+
@data = @data.class.new and return if path.length == 1
|
98
|
+
|
109
99
|
parent_data = data_at_path path[0..-3]
|
110
100
|
del_method = Array === parent_data ? :delete_at : :delete
|
111
101
|
|
@@ -140,23 +130,16 @@ class Kronk
|
|
140
130
|
# # Returns an Array of grand-children key/value pairs
|
141
131
|
# # where the value is 'invalid' or blank
|
142
132
|
|
143
|
-
def find_data data_path, curr_path=nil, &block
|
144
|
-
self.class.find_data @data, data_path, curr_path, &block
|
145
|
-
end
|
146
|
-
|
147
|
-
|
148
|
-
##
|
149
|
-
# See DataSet#find_data
|
150
|
-
|
151
|
-
def self.find_data data, data_path, curr_path=nil, &block
|
133
|
+
def find_data data_path, curr_path=nil, data=nil, &block
|
152
134
|
curr_path ||= []
|
135
|
+
data ||= @data
|
153
136
|
|
154
137
|
key, value, rec, data_path = parse_data_path data_path
|
155
138
|
|
156
139
|
yield_data_points data, key, value, rec, curr_path do |d, k, p|
|
157
140
|
|
158
141
|
if data_path
|
159
|
-
find_data d[k],
|
142
|
+
find_data data_path, p, d[k], &block
|
160
143
|
else
|
161
144
|
yield d, k, p
|
162
145
|
end
|
@@ -167,8 +150,8 @@ class Kronk
|
|
167
150
|
##
|
168
151
|
# Checks if data is available at the given path.
|
169
152
|
|
170
|
-
def
|
171
|
-
data_at_path
|
153
|
+
def data_at_path? path
|
154
|
+
data_at_path path
|
172
155
|
true
|
173
156
|
|
174
157
|
rescue NoMethodError, TypeError
|
@@ -179,8 +162,8 @@ class Kronk
|
|
179
162
|
##
|
180
163
|
# Retrieve the data at the given path array location.
|
181
164
|
|
182
|
-
def
|
183
|
-
curr = data
|
165
|
+
def data_at_path path
|
166
|
+
curr = @data
|
184
167
|
path.each do |p|
|
185
168
|
raise TypeError, "Expected instance of Array or Hash" unless
|
186
169
|
Array === curr || Hash === curr
|
@@ -198,7 +181,7 @@ class Kronk
|
|
198
181
|
# - Recursive matching
|
199
182
|
# - New data path value
|
200
183
|
|
201
|
-
def
|
184
|
+
def parse_data_path data_path
|
202
185
|
data_path = data_path.dup
|
203
186
|
key = nil
|
204
187
|
value = nil
|
@@ -236,17 +219,22 @@ class Kronk
|
|
236
219
|
|
237
220
|
|
238
221
|
##
|
239
|
-
# Decide whether to make path item a regex or
|
222
|
+
# Decide whether to make path item a regex, range, array, or string.
|
240
223
|
|
241
|
-
def
|
224
|
+
def parse_path_item str
|
242
225
|
if str =~ /(^|[^\\])([\*\?\|])/
|
243
226
|
str.gsub!(/(^|[^\\])(\*|\?)/, '\1.\2')
|
244
|
-
|
227
|
+
/^(#{str})$/i
|
228
|
+
|
229
|
+
elsif str =~ %r{^(\-?\d+)(\.{2,3})(\-?\d+)$}
|
230
|
+
Range.new $1.to_i, $3.to_i, ($2 == "...")
|
231
|
+
|
232
|
+
elsif str =~ %r{^(\-?\d+),(\-?\d+)$}
|
233
|
+
Range.new $1.to_i, ($1.to_i + $2.to_i), true
|
234
|
+
|
245
235
|
else
|
246
|
-
str.gsub
|
236
|
+
str.gsub "\\", ""
|
247
237
|
end
|
248
|
-
|
249
|
-
str
|
250
238
|
end
|
251
239
|
|
252
240
|
|
@@ -254,7 +242,7 @@ class Kronk
|
|
254
242
|
# Yield data object and key, if a specific key or value matches
|
255
243
|
# the given data.
|
256
244
|
|
257
|
-
def
|
245
|
+
def yield_data_points data, mkey, mvalue=nil,
|
258
246
|
recursive=false, path=nil, &block
|
259
247
|
|
260
248
|
return unless Hash === data || Array === data
|
@@ -266,8 +254,6 @@ class Kronk
|
|
266
254
|
found = match_data_item(mkey, key) &&
|
267
255
|
match_data_item(mvalue, value)
|
268
256
|
|
269
|
-
#puts "Found: #{data.inspect} #{mkey.inspect} -> #{key.inspect}" if found
|
270
|
-
|
271
257
|
yield data, key, curr_path if found
|
272
258
|
yield_data_points data[key], mkey, mvalue, true, curr_path, &block if
|
273
259
|
recursive
|
@@ -278,15 +264,23 @@ class Kronk
|
|
278
264
|
##
|
279
265
|
# Check if data key or value is a match for nested data searches.
|
280
266
|
|
281
|
-
def
|
267
|
+
def match_data_item item1, item2
|
282
268
|
return if !item1.nil? && (Array === item2 || Hash === item2)
|
283
269
|
|
284
|
-
if
|
270
|
+
if item1.class == item2.class
|
271
|
+
item1 == item2
|
272
|
+
|
273
|
+
elsif Regexp === item1
|
285
274
|
item2.to_s =~ item1
|
275
|
+
|
276
|
+
elsif Range === item1
|
277
|
+
item1.include? item2.to_i
|
278
|
+
|
286
279
|
elsif item1.nil?
|
287
280
|
true
|
281
|
+
|
288
282
|
else
|
289
|
-
item2.to_s == item1.to_s
|
283
|
+
item2.to_s.downcase == item1.to_s.downcase
|
290
284
|
end
|
291
285
|
end
|
292
286
|
|
@@ -294,7 +288,7 @@ class Kronk
|
|
294
288
|
##
|
295
289
|
# Universal iterator for Hash and Array objects.
|
296
290
|
|
297
|
-
def
|
291
|
+
def each_data_item data, &block
|
298
292
|
case data
|
299
293
|
|
300
294
|
when Hash
|
data/lib/kronk/diff.rb
CHANGED
@@ -1,87 +1,11 @@
|
|
1
1
|
class Kronk
|
2
2
|
|
3
|
-
|
4
3
|
##
|
5
4
|
# Creates simple diffs as formatted strings or arrays, from two strings or
|
6
5
|
# data objects.
|
7
6
|
|
8
7
|
class Diff
|
9
8
|
|
10
|
-
##
|
11
|
-
# Format diff with ascii
|
12
|
-
|
13
|
-
class AsciiFormat
|
14
|
-
|
15
|
-
def self.lines line_nums, col_width
|
16
|
-
out =
|
17
|
-
[*line_nums].map do |lnum|
|
18
|
-
lnum.to_s.rjust col_width
|
19
|
-
end.join "|"
|
20
|
-
|
21
|
-
"#{out} "
|
22
|
-
end
|
23
|
-
|
24
|
-
|
25
|
-
def self.deleted str
|
26
|
-
"- #{str}"
|
27
|
-
end
|
28
|
-
|
29
|
-
|
30
|
-
def self.added str
|
31
|
-
"+ #{str}"
|
32
|
-
end
|
33
|
-
|
34
|
-
|
35
|
-
def self.common str
|
36
|
-
" #{str}"
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
|
41
|
-
##
|
42
|
-
# Format diff with ascii
|
43
|
-
|
44
|
-
class ColorFormat
|
45
|
-
|
46
|
-
def self.require_win_color
|
47
|
-
begin
|
48
|
-
require 'Win32/Console/ANSI'
|
49
|
-
rescue LoadError
|
50
|
-
puts "Warning: You must gem install win32console to use color"
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
|
55
|
-
def self.lines line_nums, col_width
|
56
|
-
require_win_color if Kronk.windows?
|
57
|
-
|
58
|
-
out =
|
59
|
-
[*line_nums].map do |lnum|
|
60
|
-
lnum.to_s.rjust col_width
|
61
|
-
end.join "\033[32m"
|
62
|
-
|
63
|
-
"\033[7;31m#{out}\033[0m "
|
64
|
-
end
|
65
|
-
|
66
|
-
|
67
|
-
def self.deleted str
|
68
|
-
require_win_color if Kronk.windows?
|
69
|
-
"\033[31m#{str}\033[0m"
|
70
|
-
end
|
71
|
-
|
72
|
-
|
73
|
-
def self.added str
|
74
|
-
require_win_color if Kronk.windows?
|
75
|
-
"\033[32m#{str}\033[0m"
|
76
|
-
end
|
77
|
-
|
78
|
-
|
79
|
-
def self.common str
|
80
|
-
str
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
|
85
9
|
##
|
86
10
|
# Creates a new diff from two data objects.
|
87
11
|
|
@@ -184,69 +108,127 @@ class Kronk
|
|
184
108
|
|
185
109
|
def create_diff
|
186
110
|
diff_ary = []
|
187
|
-
sub_diff = nil
|
188
111
|
|
189
112
|
arr1 = @str1.split @char
|
190
113
|
arr2 = @str2.split @char
|
191
114
|
|
192
|
-
|
193
|
-
item1, item2 = arr1.shift, arr2.shift
|
115
|
+
common_list = find_common arr1, arr2
|
194
116
|
|
195
|
-
|
196
|
-
if sub_diff
|
197
|
-
diff_ary << sub_diff
|
198
|
-
sub_diff = nil
|
199
|
-
end
|
117
|
+
return [[arr1, arr2]] if common_list.empty?
|
200
118
|
|
201
|
-
|
202
|
-
|
203
|
-
end
|
119
|
+
last_i1 = 0
|
120
|
+
last_i2 = 0
|
204
121
|
|
205
|
-
|
206
|
-
|
122
|
+
common_list.each do |c|
|
123
|
+
next unless c
|
207
124
|
|
125
|
+
left = arr1[last_i1...c[1]]
|
126
|
+
right = arr2[last_i2...c[2]]
|
208
127
|
|
209
|
-
|
210
|
-
|
211
|
-
sub_diff = nil
|
128
|
+
# add diffs
|
129
|
+
diff_ary << [left, right] unless left.empty? && right.empty?
|
212
130
|
|
213
|
-
|
214
|
-
|
215
|
-
sub_diff = nil
|
131
|
+
# add common
|
132
|
+
diff_ary.concat arr1[c[1], c[0]]
|
216
133
|
|
217
|
-
|
218
|
-
|
219
|
-
sub_diff[0] << item1 if item1
|
220
|
-
sub_diff[1] << item2 if item2
|
221
|
-
end
|
134
|
+
last_i1 = c[1] + c[0]
|
135
|
+
last_i2 = c[2] + c[0]
|
222
136
|
end
|
223
137
|
|
224
|
-
|
138
|
+
left = arr1[last_i1..-1]
|
139
|
+
right = arr2[last_i2..-1]
|
140
|
+
|
141
|
+
diff_ary << [left, right] unless left.empty? && right.empty?
|
225
142
|
|
226
143
|
diff_ary
|
227
144
|
end
|
228
145
|
|
229
146
|
|
230
147
|
##
|
231
|
-
#
|
148
|
+
# Recursively finds common sequences between two arrays and returns
|
149
|
+
# them in the order they occur as an array of arrays:
|
150
|
+
# find_common arr1, arr2
|
151
|
+
# #=> [[size, arr1_index, arr2_index], [size, arr1_index, arr2_index],...]
|
152
|
+
|
153
|
+
def find_common arr1, arr2
|
154
|
+
used1 = []
|
155
|
+
used2 = []
|
156
|
+
|
157
|
+
common = []
|
232
158
|
|
233
|
-
|
234
|
-
|
159
|
+
common_sequences(arr1, arr2) do |seq|
|
160
|
+
next if used1[seq[1]] || used2[seq[2]]
|
161
|
+
|
162
|
+
next if used1[seq[1], seq[0]].to_a.index(true) ||
|
163
|
+
used2[seq[2], seq[0]].to_a.index(true)
|
164
|
+
|
165
|
+
next if used1[seq[1]+seq[0]..-1].to_a.nitems !=
|
166
|
+
used2[seq[2]+seq[0]..-1].to_a.nitems
|
167
|
+
|
168
|
+
|
169
|
+
used1.fill(true, seq[1], seq[0])
|
170
|
+
used2.fill(true, seq[2], seq[0])
|
171
|
+
|
172
|
+
common[seq[1]] = seq
|
173
|
+
end
|
174
|
+
|
175
|
+
common
|
235
176
|
end
|
236
177
|
|
237
178
|
|
238
179
|
##
|
239
|
-
#
|
180
|
+
# Returns all common sequences between to arrays ordered by sequence length
|
181
|
+
# according to the following format:
|
182
|
+
# [[[len1, ix, iy], [len1, ix, iy]],[[len2, ix, iy]]]
|
183
|
+
# # e.g.
|
184
|
+
# [nil,[[1,2,3],[1,2,5]],nil,[[3,4,5],[3,6,9]]
|
185
|
+
|
186
|
+
def common_sequences arr1, arr2, &block
|
187
|
+
sequences = []
|
188
|
+
|
189
|
+
arr2_map = {}
|
190
|
+
arr2.each_with_index do |line, j|
|
191
|
+
arr2_map[line] ||= []
|
192
|
+
arr2_map[line] << j
|
193
|
+
end
|
194
|
+
|
195
|
+
arr1.each_with_index do |line, i|
|
196
|
+
next unless arr2_map[line]
|
240
197
|
|
241
|
-
|
242
|
-
|
198
|
+
arr2_map[line].each do |j|
|
199
|
+
line1 = line
|
200
|
+
line2 = arr2[j]
|
243
201
|
|
244
|
-
|
245
|
-
|
246
|
-
added.concat arr.slice!(0..index) if index >= 0
|
202
|
+
k = i
|
203
|
+
start_j = j
|
247
204
|
|
248
|
-
|
249
|
-
|
205
|
+
while line1 && line1 == line2 && k < arr1.length
|
206
|
+
k += 1
|
207
|
+
j += 1
|
208
|
+
|
209
|
+
line1 = arr1[k]
|
210
|
+
line2 = arr2[j]
|
211
|
+
end
|
212
|
+
|
213
|
+
len = j - start_j
|
214
|
+
|
215
|
+
sequences[len] ||= []
|
216
|
+
sequences[len] << [len, i, start_j]
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
yield_sequences sequences, &block if block_given?
|
221
|
+
|
222
|
+
sequences
|
223
|
+
end
|
224
|
+
|
225
|
+
|
226
|
+
def yield_sequences sequences, dist=0, &block
|
227
|
+
while sequences.length > dist
|
228
|
+
item = sequences.pop
|
229
|
+
next unless item
|
230
|
+
item.each &block
|
231
|
+
end
|
250
232
|
end
|
251
233
|
|
252
234
|
|
@@ -329,3 +311,14 @@ class Kronk
|
|
329
311
|
end
|
330
312
|
end
|
331
313
|
end
|
314
|
+
|
315
|
+
|
316
|
+
# For Ruby 1.9
|
317
|
+
|
318
|
+
unless [].respond_to? :nitems
|
319
|
+
class Array
|
320
|
+
def nitems
|
321
|
+
self.compact.length
|
322
|
+
end
|
323
|
+
end
|
324
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
class Kronk
|
2
|
+
|
3
|
+
class Diff
|
4
|
+
|
5
|
+
##
|
6
|
+
# Format diff with ascii
|
7
|
+
|
8
|
+
class AsciiFormat
|
9
|
+
|
10
|
+
def self.lines line_nums, col_width
|
11
|
+
out =
|
12
|
+
[*line_nums].map do |lnum|
|
13
|
+
lnum.to_s.rjust col_width
|
14
|
+
end.join "|"
|
15
|
+
|
16
|
+
"#{out} "
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
def self.deleted str
|
21
|
+
"- #{str}"
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
def self.added str
|
26
|
+
"+ #{str}"
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
def self.common str
|
31
|
+
" #{str}"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|