coopy 0.6.4.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.rspec +2 -0
  4. data/CHANGELOG.md +7 -0
  5. data/Gemfile +7 -0
  6. data/LICENSE.md +22 -0
  7. data/README.md +59 -0
  8. data/Rakefile +4 -6
  9. data/coopy.gemspec +26 -0
  10. data/lib/coopy.rb +32 -175
  11. data/lib/coopy/alignment.rb +260 -0
  12. data/lib/coopy/bag.rb +17 -0
  13. data/lib/coopy/cell_info.rb +24 -0
  14. data/lib/coopy/change_type.rb +10 -0
  15. data/lib/coopy/compare_flags.rb +62 -0
  16. data/lib/coopy/compare_table.rb +327 -0
  17. data/lib/coopy/coopy.rb +22 -0
  18. data/lib/coopy/cross_match.rb +10 -0
  19. data/lib/coopy/csv_table.rb +51 -0
  20. data/lib/coopy/diff_render.rb +307 -0
  21. data/lib/coopy/index.rb +73 -0
  22. data/lib/coopy/index_item.rb +17 -0
  23. data/lib/coopy/index_pair.rb +72 -0
  24. data/lib/coopy/mover.rb +123 -0
  25. data/lib/coopy/ordering.rb +27 -0
  26. data/lib/coopy/row.rb +9 -0
  27. data/lib/coopy/simple_cell.rb +15 -0
  28. data/lib/coopy/simple_table.rb +144 -0
  29. data/lib/coopy/simple_view.rb +36 -0
  30. data/lib/coopy/table.rb +44 -0
  31. data/lib/coopy/table_comparison_state.rb +33 -0
  32. data/lib/coopy/table_diff.rb +634 -0
  33. data/lib/coopy/table_text.rb +14 -0
  34. data/lib/coopy/table_view.rb +31 -0
  35. data/lib/coopy/unit.rb +53 -0
  36. data/lib/coopy/version.rb +3 -0
  37. data/lib/coopy/view.rb +34 -0
  38. data/spec/fixtures/bridges.html +10 -0
  39. data/spec/fixtures/bridges_diff.csv +8 -0
  40. data/spec/fixtures/bridges_new.csv +9 -0
  41. data/spec/fixtures/bridges_old.csv +9 -0
  42. data/spec/fixtures/planetary_bodies.html +22 -0
  43. data/spec/fixtures/planetary_bodies_diff.csv +19 -0
  44. data/spec/fixtures/planetary_bodies_new.csv +20 -0
  45. data/spec/fixtures/planetary_bodies_old.csv +19 -0
  46. data/spec/fixtures/quote_me.csv +10 -0
  47. data/spec/fixtures/quote_me2.csv +11 -0
  48. data/spec/integration/table_diff_spec.rb +57 -0
  49. data/spec/libs/compare_flags_spec.rb +40 -0
  50. data/spec/libs/coopy_spec.rb +14 -0
  51. data/spec/libs/ordering_spec.rb +28 -0
  52. data/spec/libs/unit_spec.rb +31 -0
  53. data/spec/spec_helper.rb +29 -0
  54. metadata +153 -46
  55. data/bin/sqlite_diff +0 -4
  56. data/bin/sqlite_patch +0 -4
  57. data/bin/sqlite_rediff +0 -4
  58. data/lib/coopy/dbi_sql_wrapper.rb +0 -89
  59. data/lib/coopy/diff_apply_sql.rb +0 -35
  60. data/lib/coopy/diff_columns.rb +0 -33
  61. data/lib/coopy/diff_output.rb +0 -21
  62. data/lib/coopy/diff_output_action.rb +0 -34
  63. data/lib/coopy/diff_output_group.rb +0 -40
  64. data/lib/coopy/diff_output_raw.rb +0 -17
  65. data/lib/coopy/diff_output_stats.rb +0 -45
  66. data/lib/coopy/diff_output_table.rb +0 -49
  67. data/lib/coopy/diff_output_tdiff.rb +0 -48
  68. data/lib/coopy/diff_parser.rb +0 -92
  69. data/lib/coopy/diff_render_csv.rb +0 -29
  70. data/lib/coopy/diff_render_html.rb +0 -74
  71. data/lib/coopy/diff_render_log.rb +0 -52
  72. data/lib/coopy/row_change.rb +0 -25
  73. data/lib/coopy/scraperwiki_sql_wrapper.rb +0 -8
  74. data/lib/coopy/scraperwiki_utils.rb +0 -23
  75. data/lib/coopy/sequel_sql_wrapper.rb +0 -73
  76. data/lib/coopy/sql_compare.rb +0 -222
  77. data/lib/coopy/sql_wrapper.rb +0 -34
  78. data/lib/coopy/sqlite_sql_wrapper.rb +0 -143
  79. data/test/test_coopy.rb +0 -126
@@ -0,0 +1,10 @@
1
+ module Coopy
2
+ class CrossMatch
3
+
4
+ attr_accessor :spot_a # integer
5
+ attr_accessor :spot_b # integer
6
+ attr_accessor :item_a # IndexItem
7
+ attr_accessor :item_b # IndexItem
8
+
9
+ end
10
+ end
@@ -0,0 +1,51 @@
1
+ require 'csv'
2
+
3
+ module Coopy
4
+ class CsvTable
5
+
6
+ include Coopy::Table
7
+
8
+ def initialize(csv)
9
+ @csv = csv
10
+ @height = csv.size
11
+ @width = csv[0].size
12
+ end
13
+
14
+ def get_cell(x, y)
15
+ @csv[y][x]
16
+ end
17
+
18
+ def set_cell(x, y, cell)
19
+ @csv[y][x] = cell
20
+ end
21
+
22
+ def get_cell_view
23
+ Coopy::SimpleView.new
24
+ end
25
+
26
+ def is_resizable?
27
+ false
28
+ end
29
+
30
+ def resize(w, h)
31
+ raise NotImplementedError
32
+ end
33
+
34
+ def clear
35
+ @csv = []
36
+ end
37
+
38
+ def insert_or_delete_rows(fate, hfate)
39
+ raise NotImplementedError
40
+ end
41
+
42
+ def insert_or_delete_columns(fate, wfate)
43
+ raise NotImplementedError
44
+ end
45
+
46
+ def trim_blank
47
+ raise NotImplementedError
48
+ end
49
+
50
+ end
51
+ end
@@ -0,0 +1,307 @@
1
+ module Coopy
2
+ class DiffRender
3
+
4
+ def initialize
5
+ @text_to_insert = []
6
+ @open = false
7
+ @pretty_arrows = true
8
+ end
9
+
10
+ def use_pretty_arrows(flag)
11
+ @pretty_arrows = flag
12
+ end
13
+
14
+ def insert(str)
15
+ @text_to_insert.push(str)
16
+ end
17
+
18
+ def begin_table()
19
+ insert("<table>\n")
20
+ end
21
+
22
+ def begin_row(mode)
23
+ @td_open = '<td'
24
+ @td_close = '</td>'
25
+ row_class = ""
26
+ if (mode=="header")
27
+ @td_open = "<th"
28
+ @td_close = "</th>"
29
+ else
30
+ row_class = mode
31
+ end
32
+ tr = "<tr>"
33
+ if (row_class!="")
34
+ tr = "<tr class=\"" + row_class + "\">"
35
+ end
36
+ insert(tr)
37
+ end
38
+
39
+ def insert_cell(txt, mode)
40
+ cell_decorate = ""
41
+ if (mode!="")
42
+ cell_decorate = " class=\"" + mode + "\""
43
+ end
44
+ insert(@td_open+cell_decorate+">")
45
+ insert(txt)
46
+ insert(@td_close)
47
+ end
48
+
49
+ def end_row()
50
+ insert("</tr>\n")
51
+ end
52
+
53
+ def end_table()
54
+ insert("</table>\n")
55
+ end
56
+
57
+ def html()
58
+ return @text_to_insert.join('')
59
+ end
60
+
61
+ def to_s()
62
+ return html()
63
+ end
64
+
65
+
66
+ def self.examine_cell(x, y, value, vcol, vrow, vcorner, cell)
67
+ cell.category = ""
68
+ cell.category_given_tr = ""
69
+ cell.separator = ""
70
+ cell.conflicted = false
71
+ cell.updated = false
72
+ cell.pvalue = cell.lvalue = cell.rvalue = nil
73
+ cell.value = value
74
+ cell.value = "" if (cell.value.nil?)
75
+ cell.pretty_value = cell.value
76
+ vrow = "" if (vrow.nil?)
77
+ vcol = "" if (vcol.nil?)
78
+ removed_column = false
79
+ if (vrow == ":")
80
+ cell.category = 'move'
81
+ end
82
+ if (vcol.index("+++"))
83
+ cell.category_given_tr = cell.category = 'add'
84
+ elsif (vcol.index("---"))
85
+ cell.category_given_tr = cell.category = 'remove'
86
+ removed_column = true
87
+ end
88
+ if (vrow == "!")
89
+ cell.category = 'spec'
90
+ elsif (vrow == "@@")
91
+ cell.category = 'header'
92
+ elsif (vrow == "+++")
93
+ if (!removed_column)
94
+ cell.category = 'add'
95
+ end
96
+ elsif (vrow == "---")
97
+ cell.category = "remove"
98
+ elsif (vrow.index("->"))
99
+ if (!removed_column)
100
+ tokens = vrow.split("!")
101
+ full = vrow
102
+ part = tokens[1]
103
+ part = full if (part.nil?)
104
+ if (cell.value.index(part))
105
+ cat = "modify"
106
+ div = part
107
+ # render with utf8 -> symbol
108
+ if (part!=full)
109
+ if (cell.value.index(full))
110
+ div = full
111
+ cat = "conflict"
112
+ cell.conflicted = true
113
+ end
114
+ end
115
+ cell.updated = true
116
+ cell.separator = div
117
+ tokens = cell.pretty_value.split(div)
118
+ pretty_tokens = tokens
119
+ if (tokens.length>=2)
120
+ pretty_tokens[0] = mark_spaces(tokens[0],tokens[1])
121
+ pretty_tokens[1] = mark_spaces(tokens[1],tokens[0])
122
+ end
123
+ if (tokens.length>=3)
124
+ ref = pretty_tokens[0]
125
+ pretty_tokens[0] = mark_spaces(ref,tokens[2])
126
+ pretty_tokens[2] = mark_spaces(tokens[2],ref)
127
+ end
128
+ if (tokens.length == 0)
129
+ pretty_tokens = ['','']
130
+ end
131
+ cell.pretty_value = pretty_tokens.join("→")
132
+ cell.category_given_tr = cell.category = cat
133
+ offset = cell.conflicted ? 1 : 0
134
+ cell.lvalue = tokens[offset]
135
+ cell.rvalue = tokens[offset+1]
136
+ cell.pvalue = tokens[0] if (cell.conflicted)
137
+ end
138
+ end
139
+ end
140
+ end
141
+
142
+ def self.mark_spaces(sl, sr)
143
+ return sl if (sl==sr)
144
+ return sl if (sl.nil? || sr.nil?)
145
+ slc = sl.gsub(" ","")
146
+ src = sr.gsub(" ","")
147
+ return sl if (slc!=src)
148
+ slo = ""
149
+ il = 0
150
+ ir = 0
151
+ while (il<sl.length)
152
+ cl = sl[il]
153
+ cr = ""
154
+ if (ir<sr.length)
155
+ cr = sr[ir]
156
+ end
157
+ if (cl==cr)
158
+ slo += cl
159
+ il+=1
160
+ ir+=1
161
+ elsif (cr==" ")
162
+ ir+=1
163
+ else
164
+ slo += " " # this is U+2423, open box
165
+ il+=1
166
+ end
167
+ end
168
+ return slo
169
+ end
170
+
171
+ def self.render_cell(tt, x, y)
172
+ cell = Coopy::CellInfo.new
173
+ corner = tt.get_cell_text(0,0)
174
+ off = (corner=="@:@") ? 1 : 0
175
+
176
+ examine_cell(x,
177
+ y,
178
+ tt.get_cell_text(x,y),
179
+ tt.get_cell_text(x,off),
180
+ tt.get_cell_text(off,y),
181
+ corner,
182
+ cell)
183
+ return cell
184
+ end
185
+
186
+ def render(rows)
187
+ return if (rows.width==0||rows.height==0)
188
+ render = self
189
+ render.begin_table()
190
+ change_row = -1
191
+ tt = Coopy::TableText.new(rows)
192
+ cell = CellInfo.new
193
+ corner = tt.get_cell_text(0,0)
194
+ off = (corner=="@:@") ? 1 : 0
195
+ if (off>0)
196
+ return if (rows.width<=1||rows.height<=1)
197
+ end
198
+ (0...rows.height).each do |row|
199
+
200
+ @open = false
201
+
202
+ txt = tt.get_cell_text(off,row)
203
+ txt = "" if (txt.nil?)
204
+ DiffRender.examine_cell(0,row,txt,"",txt,corner,cell)
205
+ row_mode = cell.category
206
+ if (row_mode == "spec")
207
+ change_row = row
208
+ end
209
+
210
+ render.begin_row(row_mode)
211
+
212
+ (0...rows.width).each do |c|
213
+ DiffRender.examine_cell(c,
214
+ row,
215
+ tt.get_cell_text(c,row),
216
+ (change_row>=0)?tt.get_cell_text(c,change_row):"",
217
+ txt,
218
+ corner,
219
+ cell)
220
+ render.insert_cell(@pretty_arrows ? cell.pretty_value : cell.value,
221
+ cell.category_given_tr)
222
+ end
223
+ render.end_row()
224
+ end
225
+ render.end_table()
226
+ end
227
+
228
+ def sample_css()
229
+ return ".highlighter .add
230
+ background-color: #7fff7f
231
+ end
232
+
233
+ .highlighter .remove
234
+ background-color: #ff7f7f
235
+ end
236
+
237
+ .highlighter td.modify
238
+ background-color: #7f7fff
239
+ end
240
+
241
+ .highlighter td.conflict
242
+ background-color: #f00
243
+ end
244
+
245
+ .highlighter .spec
246
+ background-color: #aaa
247
+ end
248
+
249
+ .highlighter .move
250
+ background-color: #ffa
251
+ end
252
+
253
+ .highlighter .nil
254
+ color: #888
255
+ end
256
+
257
+ .highlighter table
258
+ border-collapse:collapse
259
+ end
260
+
261
+ .highlighter td, .highlighter th
262
+ border: 1px solid #2D4068
263
+ padding: 3px 7px 2px
264
+ end
265
+
266
+ .highlighter th, .highlighter .header
267
+ background-color: #aaf
268
+ font-weight: bold
269
+ padding-bottom: 4px
270
+ padding-top: 5px
271
+ text-align:left
272
+ end
273
+
274
+ .highlighter tr:first-child td
275
+ border-top: 1px solid #2D4068
276
+ end
277
+
278
+ .highlighter td:first-child
279
+ border-left: 1px solid #2D4068
280
+ end
281
+
282
+ .highlighter td
283
+ empty-cells: show
284
+ end
285
+ "
286
+ end
287
+
288
+ def completeHtml()
289
+ @text_to_insert.insert(0,"<html>
290
+ <meta charset='utf-8'>
291
+ <head>
292
+ <style TYPE='text/css'>
293
+ ")
294
+ @text_to_insert.insert(1,sample_css())
295
+ @text_to_insert.insert(2,"</style>
296
+ </head>
297
+ <body>
298
+ <div class='highlighter'>
299
+ ")
300
+ @text_to_insert.push("</div>
301
+ </body>
302
+ </html>
303
+ ")
304
+ end
305
+ end
306
+ end
307
+
@@ -0,0 +1,73 @@
1
+ module Coopy
2
+ class Index
3
+
4
+ attr_accessor :items # Hash<String,IndexItem>
5
+ attr_accessor :keys # Array<String>
6
+ attr_accessor :top_freq # integer
7
+ attr_accessor :height # integer
8
+
9
+ def initialize
10
+ @items = {}
11
+ @cols = [] # Array<integer>
12
+ @keys = []
13
+ @top_freq = 0
14
+ @height = 0
15
+ @v = nil # View
16
+ @indexed_table = nil # Table
17
+ end
18
+
19
+ def add_column(i)
20
+ @cols << i
21
+ end
22
+
23
+ def index_table(t)
24
+ @indexed_table = t
25
+ (0...t.height).each do |i|
26
+ key = ""
27
+ if @keys.length > i
28
+ key = @keys[i]
29
+ else
30
+ key = to_key(t,i)
31
+ @keys << key
32
+ end
33
+ item = @items[key]
34
+ if item.nil?
35
+ item = IndexItem.new
36
+ @items[key] = item
37
+ end
38
+ ct = item.add(i)
39
+ @top_freq = ct if ct>@top_freq
40
+ end
41
+ @height = t.height
42
+ end
43
+
44
+ def to_key(table, i)
45
+ wide = ""
46
+ @v = table.get_cell_view if @v.nil?
47
+ @cols.each_with_index do |col, k|
48
+ d = table.get_cell(col,i)
49
+ txt = @v.to_s(d)
50
+ next if (txt=="" || txt=="null" || txt=="undefined")
51
+ wide += " // " if (k>0)
52
+ wide += txt
53
+ end
54
+ wide
55
+ end
56
+
57
+ def to_key_by_content(row)
58
+ wide = ""
59
+ @cols.each_with_index do |col, k|
60
+ txt = row.get_row_string(col)
61
+ next if (txt=="" || txt=="null" || txt=="undefined")
62
+ wide += " // " if (k>0)
63
+ wide += txt
64
+ end
65
+ wide
66
+ end
67
+
68
+ def get_table
69
+ @indexed_table
70
+ end
71
+
72
+ end
73
+ end
@@ -0,0 +1,17 @@
1
+ module Coopy
2
+ class IndexItem
3
+
4
+ attr_accessor :lst # Array<Int>
5
+
6
+ def initialize
7
+ @lst = []
8
+ end
9
+
10
+ def add(i)
11
+ @lst ||= []
12
+ @lst << i
13
+ @lst.length
14
+ end
15
+
16
+ end
17
+ end