everypolitician-daff 1.3.26

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +252 -0
  3. data/bin/daff.rb +3 -0
  4. data/lib/daff.rb +150 -0
  5. data/lib/lib/coopy/alignment.rb +307 -0
  6. data/lib/lib/coopy/cell_builder.rb +17 -0
  7. data/lib/lib/coopy/cell_info.rb +33 -0
  8. data/lib/lib/coopy/column_change.rb +16 -0
  9. data/lib/lib/coopy/combined_table.rb +127 -0
  10. data/lib/lib/coopy/combined_table_body.rb +151 -0
  11. data/lib/lib/coopy/combined_table_head.rb +103 -0
  12. data/lib/lib/coopy/compare_flags.rb +127 -0
  13. data/lib/lib/coopy/compare_table.rb +688 -0
  14. data/lib/lib/coopy/conflict_info.rb +23 -0
  15. data/lib/lib/coopy/coopy.rb +1065 -0
  16. data/lib/lib/coopy/cross_match.rb +17 -0
  17. data/lib/lib/coopy/csv.rb +290 -0
  18. data/lib/lib/coopy/diff_render.rb +339 -0
  19. data/lib/lib/coopy/diff_summary.rb +28 -0
  20. data/lib/lib/coopy/flat_cell_builder.rb +75 -0
  21. data/lib/lib/coopy/highlight_patch.rb +977 -0
  22. data/lib/lib/coopy/highlight_patch_unit.rb +38 -0
  23. data/lib/lib/coopy/index.rb +131 -0
  24. data/lib/lib/coopy/index_item.rb +37 -0
  25. data/lib/lib/coopy/index_pair.rb +96 -0
  26. data/lib/lib/coopy/json_table.rb +165 -0
  27. data/lib/lib/coopy/json_tables.rb +129 -0
  28. data/lib/lib/coopy/merger.rb +197 -0
  29. data/lib/lib/coopy/meta.rb +20 -0
  30. data/lib/lib/coopy/mover.rb +197 -0
  31. data/lib/lib/coopy/ndjson.rb +134 -0
  32. data/lib/lib/coopy/nested_cell_builder.rb +74 -0
  33. data/lib/lib/coopy/ordering.rb +54 -0
  34. data/lib/lib/coopy/property_change.rb +16 -0
  35. data/lib/lib/coopy/row.rb +11 -0
  36. data/lib/lib/coopy/row_change.rb +42 -0
  37. data/lib/lib/coopy/row_stream.rb +11 -0
  38. data/lib/lib/coopy/simple_meta.rb +314 -0
  39. data/lib/lib/coopy/simple_table.rb +345 -0
  40. data/lib/lib/coopy/simple_view.rb +70 -0
  41. data/lib/lib/coopy/sparse_sheet.rb +51 -0
  42. data/lib/lib/coopy/sql_column.rb +47 -0
  43. data/lib/lib/coopy/sql_compare.rb +605 -0
  44. data/lib/lib/coopy/sql_database.rb +21 -0
  45. data/lib/lib/coopy/sql_helper.rb +17 -0
  46. data/lib/lib/coopy/sql_table.rb +335 -0
  47. data/lib/lib/coopy/sql_table_name.rb +23 -0
  48. data/lib/lib/coopy/sql_tables.rb +128 -0
  49. data/lib/lib/coopy/sqlite_helper.rb +316 -0
  50. data/lib/lib/coopy/table.rb +24 -0
  51. data/lib/lib/coopy/table_comparison_state.rb +50 -0
  52. data/lib/lib/coopy/table_diff.rb +1185 -0
  53. data/lib/lib/coopy/table_io.rb +72 -0
  54. data/lib/lib/coopy/table_modifier.rb +40 -0
  55. data/lib/lib/coopy/table_stream.rb +102 -0
  56. data/lib/lib/coopy/table_view.rb +148 -0
  57. data/lib/lib/coopy/tables.rb +52 -0
  58. data/lib/lib/coopy/terminal_diff_render.rb +213 -0
  59. data/lib/lib/coopy/unit.rb +93 -0
  60. data/lib/lib/coopy/view.rb +20 -0
  61. data/lib/lib/coopy/viterbi.rb +177 -0
  62. data/lib/lib/haxe/ds/int_map.rb +19 -0
  63. data/lib/lib/haxe/ds/string_map.rb +19 -0
  64. data/lib/lib/haxe/format/json_parser.rb +265 -0
  65. data/lib/lib/haxe/format/json_printer.rb +240 -0
  66. data/lib/lib/haxe/imap.rb +10 -0
  67. data/lib/lib/haxe/io/bytes.rb +34 -0
  68. data/lib/lib/haxe/io/eof.rb +18 -0
  69. data/lib/lib/haxe/io/error.rb +22 -0
  70. data/lib/lib/haxe/io/output.rb +41 -0
  71. data/lib/lib/hx_overrides.rb +19 -0
  72. data/lib/lib/hx_sys.rb +74 -0
  73. data/lib/lib/lambda.rb +37 -0
  74. data/lib/lib/list.rb +36 -0
  75. data/lib/lib/math.rb +5 -0
  76. data/lib/lib/rb/boot.rb +39 -0
  77. data/lib/lib/rb/ruby_iterator.rb +50 -0
  78. data/lib/lib/reflect.rb +41 -0
  79. data/lib/lib/std.rb +12 -0
  80. data/lib/lib/string_buf.rb +19 -0
  81. data/lib/lib/sys/io/file_handle.rb +18 -0
  82. data/lib/lib/sys/io/file_output.rb +36 -0
  83. data/lib/lib/sys/io/hx_file.rb +20 -0
  84. data/lib/lib/type.rb +37 -0
  85. data/lib/lib/value_type.rb +23 -0
  86. data/lib/lib/x_list/list_iterator.rb +32 -0
  87. metadata +235 -0
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ module Coopy
5
+ class ConflictInfo
6
+
7
+ def initialize(row,col,pvalue,lvalue,rvalue)
8
+ @row = row
9
+ @col = col
10
+ @pvalue = pvalue
11
+ @lvalue = lvalue
12
+ @rvalue = rvalue
13
+ end
14
+
15
+ attr_accessor :row
16
+ attr_accessor :col
17
+ attr_accessor :pvalue
18
+ attr_accessor :lvalue
19
+ attr_accessor :rvalue
20
+ haxe_me ["coopy", "ConflictInfo"]
21
+ end
22
+
23
+ end
@@ -0,0 +1,1065 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ module Coopy
5
+ class Coopy
6
+
7
+ def initialize(io = nil)
8
+ self.init
9
+ @io = io
10
+ end
11
+
12
+ # protected - in ruby this doesn't play well with static/inline methods
13
+
14
+ attr_accessor :format_preference
15
+ attr_accessor :delim_preference
16
+ attr_accessor :csv_eol_preference
17
+ attr_accessor :extern_preference
18
+ attr_accessor :output_format
19
+ attr_accessor :output_format_set
20
+ attr_accessor :nested_output
21
+ attr_accessor :order_set
22
+ attr_accessor :order_preference
23
+ attr_accessor :io
24
+ attr_accessor :strategy
25
+ attr_accessor :css_output
26
+ attr_accessor :fragment
27
+ attr_accessor :flags
28
+ attr_accessor :cache_txt
29
+ attr_accessor :mv
30
+
31
+ def init
32
+ @extern_preference = false
33
+ @format_preference = nil
34
+ @delim_preference = nil
35
+ @csv_eol_preference = nil
36
+ @output_format = "copy"
37
+ @output_format_set = false
38
+ @nested_output = false
39
+ @order_set = false
40
+ @order_preference = false
41
+ @strategy = nil
42
+ @css_output = nil
43
+ @fragment = false
44
+ @flags = nil
45
+ @cache_txt = nil
46
+ end
47
+
48
+ def check_format(name)
49
+ return @format_preference if @extern_preference
50
+ ext = ""
51
+ if name != nil
52
+ pt = name.rindex(".",nil || 0) || -1
53
+ if pt >= 0
54
+ begin
55
+ _this = name[pt + 1..-1]
56
+ ext = _this.downcase
57
+ end
58
+ case(ext)
59
+ when "json"
60
+ @format_preference = "json"
61
+ when "ndjson"
62
+ @format_preference = "ndjson"
63
+ when "csv"
64
+ @format_preference = "csv"
65
+ @delim_preference = ","
66
+ when "tsv"
67
+ @format_preference = "csv"
68
+ @delim_preference = "\t"
69
+ when "ssv"
70
+ @format_preference = "csv"
71
+ @delim_preference = ";"
72
+ @format_preference = "csv"
73
+ when "psv"
74
+ @format_preference = "csv"
75
+ @delim_preference = [128169].pack("U")
76
+ when "sqlite3"
77
+ @format_preference = "sqlite"
78
+ when "sqlite"
79
+ @format_preference = "sqlite"
80
+ when "html","htm"
81
+ @format_preference = "html"
82
+ when "www"
83
+ @format_preference = "www"
84
+ else
85
+ ext = ""
86
+ end
87
+ end
88
+ end
89
+ @nested_output = @format_preference == "json" || @format_preference == "ndjson"
90
+ @order_preference = !@nested_output
91
+ ext
92
+ end
93
+
94
+ def set_format(name)
95
+ @extern_preference = false
96
+ self.check_format("." + _hx_str(name))
97
+ @extern_preference = true
98
+ end
99
+
100
+ def get_renderer
101
+ renderer = ::Coopy::DiffRender.new
102
+ renderer.use_pretty_arrows(@flags.use_glyphs)
103
+ renderer
104
+ end
105
+
106
+ def apply_renderer(name,renderer)
107
+ renderer.complete_html if !@fragment
108
+ if @format_preference == "www"
109
+ @io.send_to_browser(renderer.html)
110
+ else
111
+ self.save_text(name,renderer.html)
112
+ end
113
+ self.save_text(@css_output,renderer.sample_css) if @css_output != nil
114
+ true
115
+ end
116
+
117
+ def render_table(name,t)
118
+ renderer = self.get_renderer
119
+ renderer.render(t)
120
+ self.apply_renderer(name,renderer)
121
+ end
122
+
123
+ def render_tables(name,t)
124
+ renderer = self.get_renderer
125
+ renderer.render_tables(t)
126
+ self.apply_renderer(name,renderer)
127
+ end
128
+
129
+ def save_table(name,t,render = nil)
130
+ txt = self.encode_table(name,t,render)
131
+ return true if txt == nil
132
+ self.save_text(name,txt)
133
+ end
134
+
135
+ def encode_table(name,t,render = nil)
136
+ self.set_format(@output_format) if @output_format != "copy"
137
+ txt = ""
138
+ self.check_format(name)
139
+ @format_preference = "csv" if @format_preference == "sqlite" && !@extern_preference
140
+ if render == nil
141
+ if @format_preference == "csv"
142
+ csv = ::Coopy::Csv.new(@delim_preference,@csv_eol_preference)
143
+ txt = csv.render_table(t)
144
+ elsif @format_preference == "ndjson"
145
+ txt = ::Coopy::Ndjson.new(t).render
146
+ elsif @format_preference == "html" || @format_preference == "www"
147
+ self.render_table(name,t)
148
+ return nil
149
+ elsif @format_preference == "sqlite"
150
+ @io.write_stderr("! Cannot yet output to sqlite, aborting\n")
151
+ return ""
152
+ else
153
+ value = ::Coopy::Coopy.jsonify(t)
154
+ txt = ::Haxe::Format::JsonPrinter._print(value,nil," ")
155
+ end
156
+ else
157
+ txt = render.render(t)
158
+ end
159
+ txt
160
+ end
161
+
162
+ def save_tables(name,os,use_color,is_diff)
163
+ self.set_format(@output_format) if @output_format != "copy"
164
+ txt = ""
165
+ self.check_format(name)
166
+ render = nil
167
+ render = ::Coopy::TerminalDiffRender.new(@flags,@delim_preference,is_diff) if use_color
168
+ order = os.get_order
169
+ return self.save_table(name,os.one,render) if order.length == 1
170
+ return self.render_tables(name,os) if @format_preference == "html" || @format_preference == "www"
171
+ need_blank = false
172
+ if order.length == 0 || os.has_ins_del
173
+ txt += self.encode_table(name,os.one,render)
174
+ need_blank = true
175
+ end
176
+ if order.length > 1
177
+ _g1 = 1
178
+ _g = order.length
179
+ while(_g1 < _g)
180
+ i = _g1
181
+ _g1+=1
182
+ t = os.get(order[i])
183
+ if t != nil
184
+ txt += "\n" if need_blank
185
+ need_blank = true
186
+ txt += _hx_str(order[i]) + "\n"
187
+ line = ""
188
+ begin
189
+ _g3 = 0
190
+ _g2 = order[i].length
191
+ while(_g3 < _g2)
192
+ i1 = _g3
193
+ _g3+=1
194
+ line += "="
195
+ end
196
+ end
197
+ txt += _hx_str(line) + "\n"
198
+ txt += self.encode_table(name,os.get(order[i]),render)
199
+ end
200
+ end
201
+ end
202
+ self.save_text(name,txt)
203
+ end
204
+
205
+ def save_text(name,txt)
206
+ if name == nil
207
+ @cache_txt += txt
208
+ elsif name != "-"
209
+ @io.save_content(name,txt)
210
+ else
211
+ @io.write_stdout(txt)
212
+ end
213
+ true
214
+ end
215
+
216
+ def json_to_tables(json)
217
+ tables = Reflect.field(json,"tables")
218
+ return self.json_to_table(json) if tables == nil
219
+ ::Coopy::JsonTables.new(json,@flags)
220
+ end
221
+
222
+ def json_to_table(json)
223
+ output = nil
224
+ begin
225
+ _g = 0
226
+ _g1 = Reflect.fields(json)
227
+ while(_g < _g1.length)
228
+ name = _g1[_g]
229
+ _g+=1
230
+ t = Reflect.field(json,name)
231
+ columns = Reflect.field(t,"columns")
232
+ next if columns == nil
233
+ rows = Reflect.field(t,"rows")
234
+ next if rows == nil
235
+ output = ::Coopy::SimpleTable.new(columns.length,rows.length)
236
+ has_hash = false
237
+ has_hash_known = false
238
+ begin
239
+ _g3 = 0
240
+ _g2 = rows.length
241
+ while(_g3 < _g2)
242
+ i = _g3
243
+ _g3+=1
244
+ row = rows[i]
245
+ if !has_hash_known
246
+ has_hash = true if Reflect.fields(row).length == columns.length
247
+ has_hash_known = true
248
+ end
249
+ if !has_hash
250
+ lst = row
251
+ begin
252
+ _g5 = 0
253
+ _g4 = columns.length
254
+ while(_g5 < _g4)
255
+ j = _g5
256
+ _g5+=1
257
+ val = lst[j]
258
+ output.set_cell(j,i,::Coopy::Coopy.cell_for(val))
259
+ end
260
+ end
261
+ else
262
+ _g51 = 0
263
+ _g41 = columns.length
264
+ while(_g51 < _g41)
265
+ j1 = _g51
266
+ _g51+=1
267
+ val1 = Reflect.field(row,columns[j1])
268
+ output.set_cell(j1,i,::Coopy::Coopy.cell_for(val1))
269
+ end
270
+ end
271
+ end
272
+ end
273
+ end
274
+ end
275
+ output.trim_blank if output != nil
276
+ output
277
+ end
278
+
279
+ def use_color(flags,output)
280
+ use_color = flags.terminal_format == "ansi"
281
+ if flags.terminal_format == nil
282
+ if (output == nil || output == "-") && (@output_format == "copy" || @output_format == "csv" || @output_format == "psv")
283
+ if @io != nil
284
+ use_color = @io.is_tty if @io.is_tty_known
285
+ end
286
+ end
287
+ end
288
+ use_color
289
+ end
290
+
291
+ def run_diff(parent,a,b,flags,output)
292
+ ct = ::Coopy::Coopy.compare_tables3(parent,a,b,flags)
293
+ align = ct.align
294
+ td = ::Coopy::TableDiff.new(align,flags)
295
+ o = ::Coopy::SimpleTable.new(0,0)
296
+ os = ::Coopy::Tables.new(o)
297
+ td.hilite_with_nesting(os)
298
+ use_color = self.use_color(flags,output)
299
+ self.save_tables(output,os,use_color,true)
300
+ end
301
+
302
+ public
303
+
304
+ def load_table(name)
305
+ ext = self.check_format(name)
306
+ if ext == "sqlite"
307
+ sql = @io.open_sqlite_database(name)
308
+ if sql == nil
309
+ @io.write_stderr("! Cannot open database, aborting\n")
310
+ return nil
311
+ end
312
+ tab = ::Coopy::SqlTables.new(sql,@flags)
313
+ return tab
314
+ end
315
+ txt = @io.get_content(name)
316
+ if ext == "ndjson"
317
+ t = ::Coopy::SimpleTable.new(0,0)
318
+ ndjson = ::Coopy::Ndjson.new(t)
319
+ ndjson.parse(txt)
320
+ return t
321
+ end
322
+ begin
323
+ json = ::Haxe::Format::JsonParser.new(txt).parse_rec
324
+ @format_preference = "json"
325
+ t1 = self.json_to_tables(json)
326
+ raise hx_raise("JSON failed") if t1 == nil
327
+ return t1
328
+ rescue => e
329
+ e = hx_rescued(e)
330
+ raise hx_raise(e) if ext == "json"
331
+ end if ext == "json" || ext == ""
332
+ @format_preference = "csv"
333
+ csv = ::Coopy::Csv.new(@delim_preference)
334
+ output = ::Coopy::SimpleTable.new(0,0)
335
+ csv.parse_table(txt,output)
336
+ @csv_eol_preference = csv.get_discovered_eol if @csv_eol_preference == nil
337
+ output.trim_blank if output != nil
338
+ output
339
+ end
340
+
341
+ # protected - in ruby this doesn't play well with static/inline methods
342
+
343
+ attr_accessor :status
344
+ attr_accessor :daff_cmd
345
+
346
+ def command(io,cmd,args)
347
+ r = 0
348
+ r = io.command(cmd,args) if io.async
349
+ if r != 999
350
+ io.write_stdout("$ " + _hx_str(cmd))
351
+ begin
352
+ _g = 0
353
+ while(_g < args.length)
354
+ arg = args[_g]
355
+ _g+=1
356
+ io.write_stdout(" ")
357
+ spaced = (arg.index(" ",nil || 0) || -1) >= 0
358
+ io.write_stdout("\"") if spaced
359
+ io.write_stdout(arg)
360
+ io.write_stdout("\"") if spaced
361
+ end
362
+ end
363
+ io.write_stdout("\n")
364
+ end
365
+ r = io.command(cmd,args) if !io.async
366
+ r
367
+ end
368
+
369
+ def install_git_driver(io,formats)
370
+ r = 0
371
+ if @status == nil
372
+ @status = {}
373
+ @daff_cmd = ""
374
+ end
375
+ key = "hello"
376
+ if !@status.include?(key)
377
+ io.write_stdout("Setting up git to use daff on")
378
+ begin
379
+ _g = 0
380
+ while(_g < formats.length)
381
+ format = formats[_g]
382
+ _g+=1
383
+ io.write_stdout(" *." + _hx_str(format))
384
+ end
385
+ end
386
+ io.write_stdout(" files\n")
387
+ @status[key] = r
388
+ end
389
+ key = "can_run_git"
390
+ if !@status.include?(key)
391
+ r = self.command(io,"git",["--version"])
392
+ return r if r == 999
393
+ @status[key] = r
394
+ if r != 0
395
+ io.write_stderr("! Cannot run git, aborting\n")
396
+ return 1
397
+ end
398
+ io.write_stdout("- Can run git\n")
399
+ end
400
+ daffs = ["daff","daff.rb","daff.py"]
401
+ if @daff_cmd == ""
402
+ begin
403
+ _g1 = 0
404
+ while(_g1 < daffs.length)
405
+ daff = daffs[_g1]
406
+ _g1+=1
407
+ key1 = "can_run_" + _hx_str(daff)
408
+ if !@status.include?(key1)
409
+ r = self.command(io,daff,["version"])
410
+ return r if r == 999
411
+ @status[key1] = r
412
+ if r == 0
413
+ @daff_cmd = daff
414
+ io.write_stdout("- Can run " + _hx_str(daff) + " as \"" + _hx_str(daff) + "\"\n")
415
+ break
416
+ end
417
+ end
418
+ end
419
+ end
420
+ if @daff_cmd == ""
421
+ io.write_stderr("! Cannot find daff, is it in your path?\n")
422
+ return 1
423
+ end
424
+ end
425
+ begin
426
+ _g2 = 0
427
+ while(_g2 < formats.length)
428
+ format1 = formats[_g2]
429
+ _g2+=1
430
+ key = "have_diff_driver_" + _hx_str(format1)
431
+ if !@status.include?(key)
432
+ r = self.command(io,"git",["config","--global","--get","diff.daff-" + _hx_str(format1) + ".command"])
433
+ return r if r == 999
434
+ @status[key] = r
435
+ end
436
+ have_diff_driver = @status[key] == 0
437
+ key = "add_diff_driver_" + _hx_str(format1)
438
+ if !@status.include?(key)
439
+ r = self.command(io,"git",["config","--global","diff.daff-" + _hx_str(format1) + ".command",_hx_str(@daff_cmd) + " diff --git"])
440
+ return r if r == 999
441
+ io.write_stdout("- Cleared existing daff diff driver for " + _hx_str(format1) + "\n") if have_diff_driver
442
+ io.write_stdout("- Added diff driver for " + _hx_str(format1) + "\n")
443
+ @status[key] = r
444
+ end
445
+ key = "have_merge_driver_" + _hx_str(format1)
446
+ if !@status.include?(key)
447
+ r = self.command(io,"git",["config","--global","--get","merge.daff-" + _hx_str(format1) + ".driver"])
448
+ return r if r == 999
449
+ @status[key] = r
450
+ end
451
+ have_merge_driver = @status[key] == 0
452
+ key = "name_merge_driver_" + _hx_str(format1)
453
+ if !@status.include?(key)
454
+ if !have_merge_driver
455
+ r = self.command(io,"git",["config","--global","merge.daff-" + _hx_str(format1) + ".name","daff tabular " + _hx_str(format1) + " merge"])
456
+ return r if r == 999
457
+ else
458
+ r = 0
459
+ end
460
+ @status[key] = r
461
+ end
462
+ key = "add_merge_driver_" + _hx_str(format1)
463
+ if !@status.include?(key)
464
+ r = self.command(io,"git",["config","--global","merge.daff-" + _hx_str(format1) + ".driver",_hx_str(@daff_cmd) + " merge --output %A %O %A %B"])
465
+ return r if r == 999
466
+ io.write_stdout("- Cleared existing daff merge driver for " + _hx_str(format1) + "\n") if have_merge_driver
467
+ io.write_stdout("- Added merge driver for " + _hx_str(format1) + "\n")
468
+ @status[key] = r
469
+ end
470
+ end
471
+ end
472
+ if !io.exists(".git/config")
473
+ io.write_stderr("! This next part needs to happen in a git repository.\n")
474
+ io.write_stderr("! Please run again from the root of a git repository.\n")
475
+ return 1
476
+ end
477
+ attr = ".gitattributes"
478
+ txt = ""
479
+ post = ""
480
+ if !io.exists(attr)
481
+ io.write_stdout("- No .gitattributes file\n")
482
+ else
483
+ io.write_stdout("- You have a .gitattributes file\n")
484
+ txt = io.get_content(attr)
485
+ end
486
+ need_update = false
487
+ begin
488
+ _g3 = 0
489
+ while(_g3 < formats.length)
490
+ format2 = formats[_g3]
491
+ _g3+=1
492
+ if (txt.index("*." + _hx_str(format2),nil || 0) || -1) >= 0
493
+ io.write_stderr("- Your .gitattributes file already mentions *." + _hx_str(format2) + "\n")
494
+ else
495
+ post += "*." + _hx_str(format2) + " diff=daff-" + _hx_str(format2) + "\n"
496
+ post += "*." + _hx_str(format2) + " merge=daff-" + _hx_str(format2) + "\n"
497
+ io.write_stdout("- Placing the following lines in .gitattributes:\n")
498
+ io.write_stdout(post)
499
+ txt += "\n" if txt != "" && !need_update
500
+ txt += post
501
+ need_update = true
502
+ end
503
+ end
504
+ end
505
+ io.save_content(attr,txt) if need_update
506
+ io.write_stdout("- Done!\n")
507
+ 0
508
+ end
509
+
510
+ public
511
+
512
+ def run(args,io = nil)
513
+ io = ::Coopy::TableIO.new if io == nil
514
+ if io == nil
515
+ puts "No system interface available"
516
+ return 1
517
+ end
518
+ self.init
519
+ @io = io
520
+ more = true
521
+ output = nil
522
+ inplace = false
523
+ git = false
524
+ @flags = ::Coopy::CompareFlags.new
525
+ @flags.always_show_header = true
526
+ while(more)
527
+ more = false
528
+ begin
529
+ _g1 = 0
530
+ _g = args.length
531
+ while(_g1 < _g)
532
+ i = _g1
533
+ _g1+=1
534
+ tag = args[i]
535
+ if tag == "--output"
536
+ more = true
537
+ output = args[i + 1]
538
+ args.slice!(i,2)
539
+ break
540
+ elsif tag == "--css"
541
+ more = true
542
+ @fragment = true
543
+ @css_output = args[i + 1]
544
+ args.slice!(i,2)
545
+ break
546
+ elsif tag == "--fragment"
547
+ more = true
548
+ @fragment = true
549
+ args.slice!(i,1)
550
+ break
551
+ elsif tag == "--plain"
552
+ more = true
553
+ @flags.use_glyphs = false
554
+ args.slice!(i,1)
555
+ break
556
+ elsif tag == "--all"
557
+ more = true
558
+ @flags.show_unchanged = true
559
+ @flags.show_unchanged_columns = true
560
+ args.slice!(i,1)
561
+ break
562
+ elsif tag == "--all-rows"
563
+ more = true
564
+ @flags.show_unchanged = true
565
+ args.slice!(i,1)
566
+ break
567
+ elsif tag == "--all-columns"
568
+ more = true
569
+ @flags.show_unchanged_columns = true
570
+ args.slice!(i,1)
571
+ break
572
+ elsif tag == "--act"
573
+ more = true
574
+ @flags.acts = {} if @flags.acts == nil
575
+ begin
576
+ @flags.acts[args[i + 1]] = true
577
+ true
578
+ end
579
+ args.slice!(i,2)
580
+ break
581
+ elsif tag == "--context"
582
+ more = true
583
+ context = args[i + 1].to_i
584
+ @flags.unchanged_context = context if context >= 0
585
+ args.slice!(i,2)
586
+ break
587
+ elsif tag == "--inplace"
588
+ more = true
589
+ inplace = true
590
+ args.slice!(i,1)
591
+ break
592
+ elsif tag == "--git"
593
+ more = true
594
+ git = true
595
+ args.slice!(i,1)
596
+ break
597
+ elsif tag == "--unordered"
598
+ more = true
599
+ @flags.ordered = false
600
+ @flags.unchanged_context = 0
601
+ @order_set = true
602
+ args.slice!(i,1)
603
+ break
604
+ elsif tag == "--ordered"
605
+ more = true
606
+ @flags.ordered = true
607
+ @order_set = true
608
+ args.slice!(i,1)
609
+ break
610
+ elsif tag == "--color"
611
+ more = true
612
+ @flags.terminal_format = "ansi"
613
+ args.slice!(i,1)
614
+ break
615
+ elsif tag == "--no-color"
616
+ more = true
617
+ @flags.terminal_format = "plain"
618
+ args.slice!(i,1)
619
+ break
620
+ elsif tag == "--input-format"
621
+ more = true
622
+ self.set_format(args[i + 1])
623
+ args.slice!(i,2)
624
+ break
625
+ elsif tag == "--output-format"
626
+ more = true
627
+ @output_format = args[i + 1]
628
+ @output_format_set = true
629
+ args.slice!(i,2)
630
+ break
631
+ elsif tag == "--id"
632
+ more = true
633
+ @flags.ids = Array.new if @flags.ids == nil
634
+ @flags.ids.push(args[i + 1])
635
+ args.slice!(i,2)
636
+ break
637
+ elsif tag == "--ignore"
638
+ more = true
639
+ @flags.ignore_column(args[i + 1])
640
+ args.slice!(i,2)
641
+ break
642
+ elsif tag == "--index"
643
+ more = true
644
+ @flags.always_show_order = true
645
+ @flags.never_show_order = false
646
+ args.slice!(i,1)
647
+ break
648
+ elsif tag == "--www"
649
+ more = true
650
+ @output_format = "www"
651
+ @output_format_set = true
652
+ args.slice!(i,1)
653
+ elsif tag == "--table"
654
+ more = true
655
+ @flags.add_table(args[i + 1])
656
+ args.slice!(i,2)
657
+ break
658
+ elsif tag == "-w" || tag == "--ignore-whitespace"
659
+ more = true
660
+ @flags.ignore_whitespace = true
661
+ args.slice!(i,1)
662
+ break
663
+ elsif tag == "-i" || tag == "--ignore-case"
664
+ more = true
665
+ @flags.ignore_case = true
666
+ args.slice!(i,1)
667
+ break
668
+ elsif tag == "--padding"
669
+ more = true
670
+ @flags.padding_strategy = args[i + 1]
671
+ args.slice!(i,2)
672
+ break
673
+ elsif tag == "-e" || tag == "--eol"
674
+ more = true
675
+ ending = args[i + 1]
676
+ if ending == "crlf"
677
+ ending = "\r\n"
678
+ elsif ending == "lf"
679
+ ending = "\n"
680
+ elsif ending == "cr"
681
+ ending = "\r"
682
+ elsif ending == "auto"
683
+ ending = nil
684
+ else
685
+ io.write_stderr("Expected line ending of either 'crlf' or 'lf' but got " + _hx_str(ending) + "\n")
686
+ return 1
687
+ end
688
+ @csv_eol_preference = ending
689
+ args.slice!(i,2)
690
+ break
691
+ end
692
+ end
693
+ end
694
+ end
695
+ cmd = args[0]
696
+ if args.length < 2
697
+ if cmd == "version"
698
+ io.write_stdout(_hx_str(::Coopy::Coopy.version) + "\n")
699
+ return 0
700
+ end
701
+ if cmd == "git"
702
+ io.write_stdout("You can use daff to improve git's handling of csv files, by using it as a\ndiff driver (for showing what has changed) and as a merge driver (for merging\nchanges between multiple versions).\n")
703
+ io.write_stdout("\n")
704
+ io.write_stdout("Automatic setup\n")
705
+ io.write_stdout("---------------\n\n")
706
+ io.write_stdout("Run:\n")
707
+ io.write_stdout(" daff git csv\n")
708
+ io.write_stdout("\n")
709
+ io.write_stdout("Manual setup\n")
710
+ io.write_stdout("------------\n\n")
711
+ io.write_stdout("Create and add a file called .gitattributes in the root directory of your\nrepository, containing:\n\n")
712
+ io.write_stdout(" *.csv diff=daff-csv\n")
713
+ io.write_stdout(" *.csv merge=daff-csv\n")
714
+ io.write_stdout("\nCreate a file called .gitconfig in your home directory (or alternatively\nopen .git/config for a particular repository) and add:\n\n")
715
+ io.write_stdout(" [diff \"daff-csv\"]\n")
716
+ io.write_stdout(" command = daff diff --git\n")
717
+ io.write_stderr("\n")
718
+ io.write_stdout(" [merge \"daff-csv\"]\n")
719
+ io.write_stdout(" name = daff tabular merge\n")
720
+ io.write_stdout(" driver = daff merge --output %A %O %A %B\n\n")
721
+ io.write_stderr("Make sure you can run daff from the command-line as just \"daff\" - if not,\nreplace \"daff\" in the driver and command lines above with the correct way\nto call it. Add --no-color if your terminal does not support ANSI colors.")
722
+ io.write_stderr("\n")
723
+ return 0
724
+ end
725
+ if args.length < 1
726
+ io.write_stderr("daff can produce and apply tabular diffs.\n")
727
+ io.write_stderr("Call as:\n")
728
+ io.write_stderr(" daff [--color] [--no-color] [--output OUTPUT.csv] a.csv b.csv\n")
729
+ io.write_stderr(" daff [--output OUTPUT.html] a.csv b.csv\n")
730
+ io.write_stderr(" daff [--output OUTPUT.csv] parent.csv a.csv b.csv\n")
731
+ io.write_stderr(" daff [--output OUTPUT.ndjson] a.ndjson b.ndjson\n")
732
+ io.write_stderr(" daff [--www] a.csv b.csv\n")
733
+ io.write_stderr(" daff patch [--inplace] [--output OUTPUT.csv] a.csv patch.csv\n")
734
+ io.write_stderr(" daff merge [--inplace] [--output OUTPUT.csv] parent.csv a.csv b.csv\n")
735
+ io.write_stderr(" daff trim [--output OUTPUT.csv] source.csv\n")
736
+ io.write_stderr(" daff render [--output OUTPUT.html] diff.csv\n")
737
+ io.write_stderr(" daff copy in.csv out.tsv\n")
738
+ io.write_stderr(" daff in.csv\n")
739
+ io.write_stderr(" daff git\n")
740
+ io.write_stderr(" daff version\n")
741
+ io.write_stderr("\n")
742
+ io.write_stderr("The --inplace option to patch and merge will result in modification of a.csv.\n")
743
+ io.write_stderr("\n")
744
+ io.write_stderr("If you need more control, here is the full list of flags:\n")
745
+ io.write_stderr(" daff diff [--output OUTPUT.csv] [--context NUM] [--all] [--act ACT] a.csv b.csv\n")
746
+ io.write_stderr(" --act ACT: show only a certain kind of change (update, insert, delete)\n")
747
+ io.write_stderr(" --all: do not prune unchanged rows or columns\n")
748
+ io.write_stderr(" --all-rows: do not prune unchanged rows\n")
749
+ io.write_stderr(" --all-columns: do not prune unchanged columns\n")
750
+ io.write_stderr(" --color: highlight changes with terminal colors (default in terminals)\n")
751
+ io.write_stderr(" --context NUM: show NUM rows of context\n")
752
+ io.write_stderr(" --id: specify column to use as primary key (repeat for multi-column key)\n")
753
+ io.write_stderr(" --ignore: specify column to ignore completely (can repeat)\n")
754
+ io.write_stderr(" --index: include row/columns numbers from original tables\n")
755
+ io.write_stderr(" --input-format [csv|tsv|ssv|psv|json]: set format to expect for input\n")
756
+ io.write_stderr(" --eol [crlf|lf|cr|auto]: separator between rows of csv output.\n")
757
+ io.write_stderr(" --no-color: make sure terminal colors are not used\n")
758
+ io.write_stderr(" --ordered: assume row order is meaningful (default for CSV)\n")
759
+ io.write_stderr(" --output-format [csv|tsv|ssv|psv|json|copy|html]: set format for output\n")
760
+ io.write_stderr(" --padding [dense|sparse|smart]: set padding method for aligning columns\n")
761
+ io.write_stderr(" --table NAME: compare the named table, used with SQL sources\n")
762
+ io.write_stderr(" --unordered: assume row order is meaningless (default for json formats)\n")
763
+ io.write_stderr(" -w / --ignore-whitespace: ignore changes in leading/trailing whitespace\n")
764
+ io.write_stderr(" -i / --ignore-case: ignore differences in case\n")
765
+ io.write_stderr("\n")
766
+ io.write_stderr(" daff render [--output OUTPUT.html] [--css CSS.css] [--fragment] [--plain] diff.csv\n")
767
+ io.write_stderr(" --css CSS.css: generate a suitable css file to go with the html\n")
768
+ io.write_stderr(" --fragment: generate just a html fragment rather than a page\n")
769
+ io.write_stderr(" --plain: do not use fancy utf8 characters to make arrows prettier\n")
770
+ io.write_stderr(" --www: send output to a browser\n")
771
+ return 1
772
+ end
773
+ end
774
+ cmd1 = args[0]
775
+ offset = 1
776
+ if !Lambda.has(["diff","patch","merge","trim","render","git","version","copy"],cmd1)
777
+ if (cmd1.index("--",nil || 0) || -1) == 0
778
+ cmd1 = "diff"
779
+ offset = 0
780
+ elsif (cmd1.index(".",nil || 0) || -1) != -1
781
+ if args.length == 2
782
+ cmd1 = "diff"
783
+ offset = 0
784
+ elsif args.length == 1
785
+ cmd1 = "copy"
786
+ offset = 0
787
+ end
788
+ end
789
+ end
790
+ if cmd1 == "git"
791
+ types = args.slice!(offset,args.length - offset)
792
+ return self.install_git_driver(io,types)
793
+ end
794
+ if git
795
+ ct = args.length - offset
796
+ if ct != 7 && ct != 9
797
+ io.write_stderr("Expected 7 or 9 parameters from git, but got " + _hx_str(ct) + "\n")
798
+ return 1
799
+ end
800
+ git_args = args.slice!(offset,ct)
801
+ args.slice!(0,args.length)
802
+ offset = 0
803
+ old_display_path = git_args[0]
804
+ new_display_path = git_args[0]
805
+ old_file = git_args[1]
806
+ new_file = git_args[4]
807
+ if ct == 9
808
+ io.write_stdout(git_args[8])
809
+ new_display_path = git_args[7]
810
+ end
811
+ io.write_stdout("--- a/" + _hx_str(old_display_path) + "\n")
812
+ io.write_stdout("+++ b/" + _hx_str(new_display_path) + "\n")
813
+ args.push(old_file)
814
+ args.push(new_file)
815
+ end
816
+ parent = nil
817
+ if args.length - offset >= 3
818
+ parent = self.load_table(args[offset])
819
+ offset+=1
820
+ end
821
+ aname = args[offset]
822
+ a = self.load_table(aname)
823
+ b = nil
824
+ if args.length - offset >= 2
825
+ if cmd1 != "copy"
826
+ b = self.load_table(args[1 + offset])
827
+ else
828
+ output = args[1 + offset]
829
+ end
830
+ end
831
+ @flags.diff_strategy = @strategy
832
+ if inplace
833
+ io.write_stderr("Please do not use --inplace when specifying an output.\n") if output != nil
834
+ output = aname
835
+ return 1
836
+ end
837
+ output = "-" if output == nil
838
+ ok = true
839
+ if cmd1 == "diff"
840
+ if !@order_set
841
+ @flags.ordered = @order_preference
842
+ @flags.unchanged_context = 0 if !@flags.ordered
843
+ end
844
+ @flags.allow_nested_cells = @nested_output
845
+ self.run_diff(parent,a,b,@flags,output)
846
+ elsif cmd1 == "patch"
847
+ patcher = ::Coopy::HighlightPatch.new(a,b)
848
+ patcher.apply
849
+ self.save_table(output,a)
850
+ elsif cmd1 == "merge"
851
+ merger = ::Coopy::Merger.new(parent,a,b,@flags)
852
+ conflicts = merger.apply
853
+ ok = conflicts == 0
854
+ io.write_stderr(_hx_str(conflicts) + " conflict" + _hx_str((((conflicts > 1) ? "s" : ""))) + "\n") if conflicts > 0
855
+ self.save_table(output,a)
856
+ elsif cmd1 == "trim"
857
+ self.save_table(output,a)
858
+ elsif cmd1 == "render"
859
+ self.render_table(output,a)
860
+ elsif cmd1 == "copy"
861
+ os = ::Coopy::Tables.new(a)
862
+ os.add("untitled")
863
+ self.save_tables(output,os,self.use_color(@flags,output),false)
864
+ end
865
+ if ok
866
+ return 0
867
+ else
868
+ return 1
869
+ end
870
+ end
871
+
872
+ def coopyhx(io)
873
+ args = io.args
874
+ return ::Coopy::Coopy.keep_around if args[0] == "--keep"
875
+ self.run(args,io)
876
+ end
877
+
878
+
879
+ class << self
880
+ attr_accessor :version
881
+ end
882
+ @version = "1.3.26"
883
+
884
+ def Coopy.diff_as_html(local,remote,flags = nil)
885
+ comp = ::Coopy::TableComparisonState.new
886
+ td = ::Coopy::Coopy.align(local,remote,flags,comp)
887
+ o = ::Coopy::Coopy.get_blank_table(td,comp)
888
+ o = comp.a.create if comp.a != nil
889
+ o = comp.b.create if o == nil && comp.b != nil
890
+ o = ::Coopy::SimpleTable.new(0,0) if o == nil
891
+ os = ::Coopy::Tables.new(o)
892
+ td.hilite_with_nesting(os)
893
+ render = ::Coopy::DiffRender.new
894
+ render.render_tables(os).html
895
+ end
896
+
897
+ def Coopy.diff_as_ansi(local,remote,flags = nil)
898
+ tool = ::Coopy::Coopy.new(::Coopy::TableIO.new)
899
+ tool.cache_txt = ""
900
+ flags = ::Coopy::CompareFlags.new if flags == nil
901
+ tool.output_format = "csv"
902
+ tool.run_diff(flags.parent,local,remote,flags,nil)
903
+ tool.cache_txt
904
+ end
905
+
906
+ def Coopy.diff(local,remote,flags = nil)
907
+ comp = ::Coopy::TableComparisonState.new
908
+ td = ::Coopy::Coopy.align(local,remote,flags,comp)
909
+ o = ::Coopy::Coopy.get_blank_table(td,comp)
910
+ o = comp.a.create if comp.a != nil
911
+ o = comp.b.create if o == nil && comp.b != nil
912
+ o = ::Coopy::SimpleTable.new(0,0) if o == nil
913
+ td.hilite(o)
914
+ o
915
+ end
916
+
917
+ # protected - in ruby this doesn't play well with static/inline methods
918
+
919
+ def Coopy.get_blank_table(td,comp)
920
+ o = nil
921
+ o = comp.a.create if comp.a != nil
922
+ o = comp.b.create if o == nil && comp.b != nil
923
+ o = ::Coopy::SimpleTable.new(0,0) if o == nil
924
+ o
925
+ end
926
+
927
+ def Coopy.align(local,remote,flags,comp)
928
+ comp.a = ::Coopy::Coopy.tablify(local)
929
+ comp.b = ::Coopy::Coopy.tablify(remote)
930
+ flags = ::Coopy::CompareFlags.new if flags == nil
931
+ comp.compare_flags = flags
932
+ ct = ::Coopy::CompareTable.new(comp)
933
+ align = ct.align
934
+ td = ::Coopy::TableDiff.new(align,flags)
935
+ td
936
+ end
937
+
938
+ public
939
+
940
+ def Coopy.patch(local,patch,flags = nil)
941
+ patcher = ::Coopy::HighlightPatch.new(::Coopy::Coopy.tablify(local),::Coopy::Coopy.tablify(patch))
942
+ patcher.apply
943
+ end
944
+
945
+ def Coopy.compare_tables(local,remote,flags = nil)
946
+ comp = ::Coopy::TableComparisonState.new
947
+ comp.a = ::Coopy::Coopy.tablify(local)
948
+ comp.b = ::Coopy::Coopy.tablify(remote)
949
+ comp.compare_flags = flags
950
+ ct = ::Coopy::CompareTable.new(comp)
951
+ ct
952
+ end
953
+
954
+ def Coopy.compare_tables3(parent,local,remote,flags = nil)
955
+ comp = ::Coopy::TableComparisonState.new
956
+ comp.p = ::Coopy::Coopy.tablify(parent)
957
+ comp.a = ::Coopy::Coopy.tablify(local)
958
+ comp.b = ::Coopy::Coopy.tablify(remote)
959
+ comp.compare_flags = flags
960
+ ct = ::Coopy::CompareTable.new(comp)
961
+ ct
962
+ end
963
+
964
+ # protected - in ruby this doesn't play well with static/inline methods
965
+
966
+ def Coopy.keep_around
967
+ st = ::Coopy::SimpleTable.new(1,1)
968
+ v = ::Coopy::Viterbi.new
969
+ td = ::Coopy::TableDiff.new(nil,nil)
970
+ cf = ::Coopy::CompareFlags.new
971
+ idx = ::Coopy::Index.new(cf)
972
+ dr = ::Coopy::DiffRender.new
973
+ hp = ::Coopy::HighlightPatch.new(nil,nil)
974
+ csv = ::Coopy::Csv.new
975
+ tm = ::Coopy::TableModifier.new(nil)
976
+ sc = ::Coopy::SqlCompare.new(nil,nil,nil,nil)
977
+ sq = ::Coopy::SqliteHelper.new
978
+ sm = ::Coopy::SimpleMeta.new(nil)
979
+ ct = ::Coopy::CombinedTable.new(nil)
980
+ 0
981
+ end
982
+
983
+ def Coopy.cell_for(x)
984
+ x
985
+ end
986
+
987
+ public
988
+
989
+ def Coopy.main
990
+ io = ::Coopy::TableIO.new
991
+ coopy1 = ::Coopy::Coopy.new
992
+ ret = coopy1.coopyhx(io)
993
+ HxSys.exit(ret) if ret != 0
994
+ ret
995
+ end
996
+
997
+ # protected - in ruby this doesn't play well with static/inline methods
998
+
999
+ def Coopy.show(t)
1000
+ w = t.get_width
1001
+ h = t.get_height
1002
+ txt = ""
1003
+ begin
1004
+ _g = 0
1005
+ while(_g < h)
1006
+ y = _g
1007
+ _g+=1
1008
+ begin
1009
+ _g1 = 0
1010
+ while(_g1 < w)
1011
+ x = _g1
1012
+ _g1+=1
1013
+ begin
1014
+ s = t.get_cell(x,y)
1015
+ txt += s.to_s
1016
+ end
1017
+ txt += " "
1018
+ end
1019
+ end
1020
+ txt += "\n"
1021
+ end
1022
+ end
1023
+ puts txt
1024
+ end
1025
+
1026
+ def Coopy.jsonify(t)
1027
+ workbook = {}
1028
+ sheet = Array.new
1029
+ w = t.get_width
1030
+ h = t.get_height
1031
+ txt = ""
1032
+ begin
1033
+ _g = 0
1034
+ while(_g < h)
1035
+ y = _g
1036
+ _g+=1
1037
+ row = Array.new
1038
+ begin
1039
+ _g1 = 0
1040
+ while(_g1 < w)
1041
+ x = _g1
1042
+ _g1+=1
1043
+ v = t.get_cell(x,y)
1044
+ row.push(v)
1045
+ end
1046
+ end
1047
+ sheet.push(row)
1048
+ end
1049
+ end
1050
+ workbook["sheet"] = sheet
1051
+ workbook
1052
+ end
1053
+
1054
+ public
1055
+
1056
+ def Coopy.tablify(data)
1057
+ return data if data == nil
1058
+ return data if data.respond_to? :get_cell_view
1059
+ ::Coopy::TableView.new(data)
1060
+ end
1061
+
1062
+ haxe_me ["coopy", "Coopy"]
1063
+ end
1064
+
1065
+ end