daff 1.2.3 → 1.2.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. data/README.md +4 -1
  2. data/lib/daff.rb +20 -7
  3. data/lib/lib/coopy/alignment.rb +6 -0
  4. data/lib/lib/coopy/cell_info.rb +1 -0
  5. data/lib/lib/coopy/compare_flags.rb +2 -0
  6. data/lib/lib/coopy/compare_table.rb +1 -1
  7. data/lib/lib/coopy/coopy.rb +80 -18
  8. data/lib/lib/coopy/csv.rb +1 -1
  9. data/lib/lib/coopy/diff_render.rb +61 -22
  10. data/lib/lib/coopy/flat_cell_builder.rb +1 -1
  11. data/lib/lib/coopy/highlight_patch.rb +8 -6
  12. data/lib/lib/coopy/mover.rb +1 -1
  13. data/lib/lib/coopy/ndjson.rb +134 -0
  14. data/lib/lib/coopy/nested_cell_builder.rb +74 -0
  15. data/lib/lib/coopy/simple_view.rb +29 -0
  16. data/lib/lib/coopy/sql_column.rb +35 -0
  17. data/lib/lib/coopy/sql_compare.rb +245 -0
  18. data/lib/lib/coopy/sql_database.rb +19 -0
  19. data/lib/lib/coopy/sql_helper.rb +12 -0
  20. data/lib/lib/coopy/sql_table.rb +216 -0
  21. data/lib/lib/coopy/sql_table_name.rb +23 -0
  22. data/lib/lib/coopy/sqlite_helper.rb +47 -0
  23. data/lib/lib/coopy/table_diff.rb +18 -6
  24. data/lib/lib/coopy/table_io.rb +5 -0
  25. data/lib/lib/coopy/terminal_diff_render.rb +8 -9
  26. data/lib/lib/coopy/view.rb +5 -0
  27. data/lib/lib/haxe/ds/int_map.rb +4 -0
  28. data/lib/lib/haxe/ds/string_map.rb +4 -0
  29. data/lib/lib/haxe/format/json_parser.rb +8 -8
  30. data/lib/lib/haxe/imap.rb +1 -0
  31. data/lib/lib/haxe/io/bytes.rb +1 -1
  32. data/lib/lib/haxe/io/bytes_output.rb +1 -1
  33. data/lib/lib/haxe/io/error.rb +1 -0
  34. data/lib/lib/haxe/io/output.rb +2 -2
  35. data/lib/lib/hx_overrides.rb +12 -0
  36. data/lib/lib/hx_sys.rb +1 -1
  37. data/lib/lib/rb/boot.rb +5 -1
  38. data/lib/lib/reflect.rb +1 -0
  39. data/lib/lib/sys/io/file_handle.rb +1 -0
  40. data/lib/lib/sys/io/file_output.rb +1 -1
  41. data/lib/lib/value_type.rb +1 -0
  42. metadata +36 -25
data/README.md CHANGED
@@ -3,6 +3,7 @@
3
3
  [![Gem Version](https://badge.fury.io/rb/daff.svg)](http://badge.fury.io/rb/daff)
4
4
  [![PyPI version](https://badge.fury.io/py/daff.svg)](http://badge.fury.io/py/daff)
5
5
  [![PHP version](https://badge.fury.io/ph/paulfitz%2Fdaff-php.svg)](http://badge.fury.io/ph/paulfitz%2Fdaff-php)
6
+ [![tips](https://img.shields.io/gratipay/paulfitz.svg)](https://gratipay.com/paulfitz/)
6
7
 
7
8
  daff: data diff
8
9
  ===============
@@ -47,7 +48,7 @@ daff can produce and apply tabular diffs.
47
48
  Call as:
48
49
  daff [--output OUTPUT.csv] a.csv b.csv
49
50
  daff [--output OUTPUT.csv] parent.csv a.csv b.csv
50
- daff [--output OUTPUT.jsonbook] a.jsonbook b.jsonbook
51
+ daff [--output OUTPUT.ndjson] a.ndjson b.ndjson
51
52
  daff patch [--inplace] [--output OUTPUT.csv] a.csv patch.csv
52
53
  daff merge [--inplace] [--output OUTPUT.csv] parent.csv a.csv b.csv
53
54
  daff trim [--output OUTPUT.csv] source.csv
@@ -72,6 +73,8 @@ If you need more control, here is the full list of flags:
72
73
  --plain: do not use fancy utf8 characters to make arrows prettier
73
74
  ````
74
75
 
76
+ Formats supported are CSV, TSV, and [ndjson](http://dataprotocols.org/ndjson/).
77
+
75
78
  Using with git
76
79
  --------------
77
80
 
data/lib/daff.rb CHANGED
@@ -55,17 +55,25 @@ require_relative 'lib/coopy/index_item'
55
55
  require_relative 'lib/coopy/index_pair'
56
56
  require_relative 'lib/coopy/merger'
57
57
  require_relative 'lib/coopy/mover'
58
+ require_relative 'lib/coopy/ndjson'
59
+ require_relative 'lib/coopy/nested_cell_builder'
58
60
  require_relative 'lib/coopy/ordering'
59
61
  require_relative 'lib/coopy/table'
60
62
  require_relative 'lib/coopy/simple_table'
61
63
  require_relative 'lib/coopy/view'
62
64
  require_relative 'lib/coopy/simple_view'
63
65
  require_relative 'lib/coopy/sparse_sheet'
66
+ require_relative 'lib/coopy/sql_column'
67
+ require_relative 'lib/coopy/sql_compare'
68
+ require_relative 'lib/coopy/sql_database'
69
+ require_relative 'lib/coopy/sql_helper'
70
+ require_relative 'lib/coopy/sql_table'
71
+ require_relative 'lib/coopy/sql_table_name'
72
+ require_relative 'lib/coopy/sqlite_helper'
64
73
  require_relative 'lib/coopy/table_comparison_state'
65
74
  require_relative 'lib/coopy/table_diff'
66
75
  require_relative 'lib/coopy/table_io'
67
76
  require_relative 'lib/coopy/table_modifier'
68
- require_relative 'lib/coopy/table_text'
69
77
  require_relative 'lib/coopy/terminal_diff_render'
70
78
  require_relative 'lib/coopy/unit'
71
79
  require_relative 'lib/coopy/viterbi'
@@ -96,16 +104,21 @@ def _hx_ord(s) return 0 if s.nil?; s.ord end
96
104
  $hx_exception_classes = {}
97
105
  def hx_exception_class(c)
98
106
  $hx_exception_classes[c.name] ||= Class.new(RuntimeError) do
99
- Object.const_set((c.name.split(/::/).old_access(-1)||'') + 'HaxeException',self)
100
- def initialize(target) @target = target; end
101
- def method_missing(name, *args, &block)
102
- @target.send(name, *args, &block)
103
- end
107
+ Object.const_set((c.name.split(/::/)[-1]||'') + 'HaxeException',self)
108
+ attr_accessor :hx_exception_target
109
+ def initialize(target) @hx_exception_target = target; end
104
110
  end
105
111
  end
106
- def hx_exception(x)
112
+ def hx_raise(x)
107
113
  hx_exception_class(x.class).new(x)
108
114
  end
115
+ def hx_rescue(x)
116
+ hx_exception_class(x.class)
117
+ end
118
+ def hx_rescued(x)
119
+ return x.hx_exception_target if x.respond_to? :hx_exception_target
120
+ x
121
+ end
109
122
 
110
123
 
111
124
  Daff = Coopy
@@ -96,6 +96,12 @@ module Coopy
96
96
  return @order_cache
97
97
  end
98
98
 
99
+ def add_to_order(l,r,p = -2)
100
+ @order_cache = ::Coopy::Ordering.new if @order_cache == nil
101
+ @order_cache.add(l,r,p)
102
+ @order_cache_has_reference = p != -2
103
+ end
104
+
99
105
  def get_source
100
106
  return @ta
101
107
  end
@@ -7,6 +7,7 @@ module Coopy
7
7
  def initialize
8
8
  end
9
9
 
10
+ attr_accessor :raw
10
11
  attr_accessor :value
11
12
  attr_accessor :pretty_value
12
13
  attr_accessor :category
@@ -16,6 +16,7 @@ module Coopy
16
16
  @acts = nil
17
17
  @ids = nil
18
18
  @columns_to_ignore = nil
19
+ @allow_nested_cells = false
19
20
  end
20
21
 
21
22
  attr_accessor :ordered
@@ -29,6 +30,7 @@ module Coopy
29
30
  attr_accessor :acts
30
31
  attr_accessor :ids
31
32
  attr_accessor :columns_to_ignore
33
+ attr_accessor :allow_nested_cells
32
34
 
33
35
  def filter(act,allow)
34
36
  if @acts == nil
@@ -179,7 +179,7 @@ module Coopy
179
179
  return -1 if a1[1] > b1[1]
180
180
  return 0
181
181
  }
182
- columns_eval.sort{|a,b| sorter.call(a,b)}
182
+ columns_eval.sort!{|a,b| sorter.call(a,b)}
183
183
  columns = Lambda.array(Lambda.map(columns_eval,lambda {|v|
184
184
  return v[0]
185
185
  }))
@@ -9,6 +9,9 @@ module Coopy
9
9
  @format_preference = nil
10
10
  @delim_preference = nil
11
11
  @output_format = "copy"
12
+ @nested_output = false
13
+ @order_set = false
14
+ @order_preference = false
12
15
  end
13
16
 
14
17
  # protected - in ruby this doesn't play well with static/inline methods
@@ -17,6 +20,9 @@ module Coopy
17
20
  attr_accessor :delim_preference
18
21
  attr_accessor :extern_preference
19
22
  attr_accessor :output_format
23
+ attr_accessor :nested_output
24
+ attr_accessor :order_set
25
+ attr_accessor :order_preference
20
26
  attr_accessor :io
21
27
  attr_accessor :mv
22
28
 
@@ -25,10 +31,12 @@ module Coopy
25
31
  ext = ""
26
32
  pt = name.rindex(".",nil || 0) || -1
27
33
  if pt >= 0
28
- ext = name[pt + 1..-1].to_lower_case
34
+ ext = HxOverrides.substr(name,pt + 1,nil).to_lower_case
29
35
  case(ext)
30
36
  when "json"
31
37
  @format_preference = "json"
38
+ when "ndjson"
39
+ @format_preference = "ndjson"
32
40
  when "csv"
33
41
  @format_preference = "csv"
34
42
  @delim_preference = ","
@@ -38,10 +46,16 @@ module Coopy
38
46
  when "ssv"
39
47
  @format_preference = "csv"
40
48
  @delim_preference = ";"
49
+ when "sqlite3"
50
+ @format_preference = "sqlite"
51
+ when "sqlite"
52
+ @format_preference = "sqlite"
41
53
  else
42
54
  ext = ""
43
55
  end
44
56
  end
57
+ @nested_output = @format_preference == "json" || @format_preference == "ndjson"
58
+ @order_preference = !@nested_output
45
59
  return ext
46
60
  end
47
61
 
@@ -55,12 +69,17 @@ module Coopy
55
69
  self.set_format(@output_format) if @output_format != "copy"
56
70
  txt = ""
57
71
  self.check_format(name)
58
- if @format_preference != "json"
72
+ if @format_preference == "csv"
59
73
  csv = ::Coopy::Csv.new(@delim_preference)
60
74
  txt = csv.render_table(t)
75
+ elsif @format_preference == "ndjson"
76
+ txt = ::Coopy::Ndjson.new(t).render
77
+ elsif @format_preference == "sqlite"
78
+ @io.write_stderr("! Cannot yet output to sqlite, aborting\n")
79
+ return false
61
80
  else
62
81
  value = ::Coopy::Coopy.jsonify(t)
63
- txt = ::Haxe::Format::JsonPrinter._print(value,nil,nil)
82
+ txt = ::Haxe::Format::JsonPrinter._print(value,nil," ")
64
83
  end
65
84
  return self.save_text(name,txt)
66
85
  end
@@ -77,14 +96,40 @@ module Coopy
77
96
  def load_table(name)
78
97
  txt = @io.get_content(name)
79
98
  ext = self.check_format(name)
99
+ if ext == "sqlite"
100
+ sql = @io.open_sqlite_database(name)
101
+ if sql == nil
102
+ @io.write_stderr("! Cannot open database, aborting\n")
103
+ return nil
104
+ end
105
+ helper = ::Coopy::SqliteHelper.new
106
+ names = helper.get_table_names(sql)
107
+ if names == nil
108
+ @io.write_stderr("! Cannot find database tables, aborting\n")
109
+ return nil
110
+ end
111
+ if names.length == 0
112
+ @io.write_stderr("! No tables in database, aborting\n")
113
+ return nil
114
+ end
115
+ tab = ::Coopy::SqlTable.new(sql,::Coopy::SqlTableName.new(names[0]),helper)
116
+ return tab
117
+ end
118
+ if ext == "ndjson"
119
+ t = ::Coopy::SimpleTable.new(0,0)
120
+ ndjson = ::Coopy::Ndjson.new(t)
121
+ ndjson.parse(txt)
122
+ return t
123
+ end
80
124
  begin
81
125
  json = ::Haxe::Format::JsonParser.new(txt).parse_rec
82
126
  @format_preference = "json"
83
- t = ::Coopy::Coopy.json_to_table(json)
84
- raise "JSON failed" if t == nil
85
- return t
127
+ t1 = ::Coopy::Coopy.json_to_table(json)
128
+ raise hx_raise("JSON failed") if t1 == nil
129
+ return t1
86
130
  rescue => e
87
- raise e if ext == "json"
131
+ e = hx_rescued(e)
132
+ raise hx_raise(e) if ext == "json"
88
133
  end if ext == "json" || ext == ""
89
134
  @format_preference = "csv"
90
135
  csv = ::Coopy::Csv.new(@delim_preference)
@@ -344,6 +389,19 @@ module Coopy
344
389
  git = true
345
390
  args.slice!(i,1)
346
391
  break
392
+ elsif tag == "--unordered"
393
+ more = true
394
+ flags.ordered = false
395
+ flags.unchanged_context = 0
396
+ @order_set = true
397
+ args.slice!(i,1)
398
+ break
399
+ elsif tag == "--ordered"
400
+ more = true
401
+ flags.ordered = true
402
+ @order_set = true
403
+ args.slice!(i,1)
404
+ break
347
405
  elsif tag == "--color"
348
406
  more = true
349
407
  color = true
@@ -415,7 +473,7 @@ module Coopy
415
473
  io.write_stderr("Call as:\n")
416
474
  io.write_stderr(" daff [--color] [--output OUTPUT.csv] a.csv b.csv\n")
417
475
  io.write_stderr(" daff [--output OUTPUT.csv] parent.csv a.csv b.csv\n")
418
- io.write_stderr(" daff [--output OUTPUT.jsonbook] a.jsonbook b.jsonbook\n")
476
+ io.write_stderr(" daff [--output OUTPUT.ndjson] a.ndjson b.ndjson\n")
419
477
  io.write_stderr(" daff patch [--inplace] [--output OUTPUT.csv] a.csv patch.csv\n")
420
478
  io.write_stderr(" daff merge [--inplace] [--output OUTPUT.csv] parent.csv a.csv b.csv\n")
421
479
  io.write_stderr(" daff trim [--output OUTPUT.csv] source.csv\n")
@@ -428,14 +486,16 @@ module Coopy
428
486
  io.write_stderr("\n")
429
487
  io.write_stderr("If you need more control, here is the full list of flags:\n")
430
488
  io.write_stderr(" daff diff [--output OUTPUT.csv] [--context NUM] [--all] [--act ACT] a.csv b.csv\n")
431
- io.write_stderr(" --id: specify column to use as primary key (repeat for multi-column key)\n")
432
- io.write_stderr(" --ignore: specify column to ignore completely (can repeat)\n")
489
+ io.write_stderr(" --act ACT: show only a certain kind of change (update, insert, delete)\n")
490
+ io.write_stderr(" --all: do not prune unchanged rows\n")
433
491
  io.write_stderr(" --color: highlight changes with terminal colors\n")
434
492
  io.write_stderr(" --context NUM: show NUM rows of context\n")
435
- io.write_stderr(" --all: do not prune unchanged rows\n")
436
- io.write_stderr(" --act ACT: show only a certain kind of change (update, insert, delete)\n")
493
+ io.write_stderr(" --id: specify column to use as primary key (repeat for multi-column key)\n")
494
+ io.write_stderr(" --ignore: specify column to ignore completely (can repeat)\n")
437
495
  io.write_stderr(" --input-format [csv|tsv|ssv|json]: set format to expect for input\n")
496
+ io.write_stderr(" --ordered: assume row order is meaningful (default for CSV)\n")
438
497
  io.write_stderr(" --output-format [csv|tsv|ssv|json|copy]: set format for output\n")
498
+ io.write_stderr(" --unordered: assume row order is meaningless (default for json formats)\n")
439
499
  io.write_stderr("\n")
440
500
  io.write_stderr(" daff diff --git path old-file old-hex old-mode new-file new-hex new-mode\n")
441
501
  io.write_stderr(" --git: process arguments provided by git to diff drivers\n")
@@ -501,6 +561,11 @@ module Coopy
501
561
  output = "-" if output == nil
502
562
  ok = true
503
563
  if cmd1 == "diff"
564
+ if !@order_set
565
+ flags.ordered = @order_preference
566
+ flags.unchanged_context = 0 if !flags.ordered
567
+ end
568
+ flags.allow_nested_cells = @nested_output
504
569
  ct1 = ::Coopy::Coopy.compare_tables3(parent,a,b,flags)
505
570
  align = ct1.align
506
571
  td = ::Coopy::TableDiff.new(align,flags)
@@ -545,7 +610,7 @@ module Coopy
545
610
  class << self
546
611
  attr_accessor :version
547
612
  end
548
- @version = "1.2.3"
613
+ @version = "1.2.4"
549
614
 
550
615
  def Coopy.compare_tables(local,remote,flags = nil)
551
616
  comp = ::Coopy::TableComparisonState.new
@@ -578,6 +643,7 @@ module Coopy
578
643
  hp = ::Coopy::HighlightPatch.new(nil,nil)
579
644
  csv = ::Coopy::Csv.new
580
645
  tm = ::Coopy::TableModifier.new(nil)
646
+ sc = ::Coopy::SqlCompare.new(nil,nil,nil)
581
647
  return 0
582
648
  end
583
649
 
@@ -697,11 +763,7 @@ module Coopy
697
763
  x = _g1
698
764
  _g1+=1
699
765
  v = t.get_cell(x,y)
700
- if v != nil
701
- row.push(v[:to_s].call)
702
- else
703
- row.push(nil)
704
- end
766
+ row.push(v)
705
767
  end
706
768
  end
707
769
  sheet.push(row)
data/lib/lib/coopy/csv.rb CHANGED
@@ -188,7 +188,7 @@ module Coopy
188
188
  return nil if result == "NULL"
189
189
  if first_non_underscore > start
190
190
  del = first_non_underscore - start
191
- return result[1..-1] if result[del..-1] == "NULL"
191
+ return HxOverrides.substr(result,1,nil) if HxOverrides.substr(result,del,nil) == "NULL"
192
192
  end
193
193
  end
194
194
  return result
@@ -17,6 +17,7 @@ module Coopy
17
17
  attr_accessor :td_close
18
18
  attr_accessor :open
19
19
  attr_accessor :pretty_arrows
20
+ attr_accessor :section
20
21
 
21
22
  public
22
23
 
@@ -32,6 +33,22 @@ module Coopy
32
33
 
33
34
  def begin_table
34
35
  self.insert("<table>\n")
36
+ @section = nil
37
+ end
38
+
39
+ def set_section(str)
40
+ return if str == @section
41
+ if @section != nil
42
+ self.insert("</t")
43
+ self.insert(@section)
44
+ self.insert(">\n")
45
+ end
46
+ @section = str
47
+ if @section != nil
48
+ self.insert("<t")
49
+ self.insert(@section)
50
+ self.insert(">\n")
51
+ end
35
52
  end
36
53
 
37
54
  def begin_row(mode)
@@ -41,9 +58,8 @@ module Coopy
41
58
  if mode == "header"
42
59
  @td_open = "<th"
43
60
  @td_close = "</th>"
44
- else
45
- row_class = mode
46
61
  end
62
+ row_class = mode
47
63
  tr = "<tr>"
48
64
  tr = "<tr class=\"" + _hx_str(row_class) + "\">" if row_class != ""
49
65
  self.insert(tr)
@@ -62,6 +78,7 @@ module Coopy
62
78
  end
63
79
 
64
80
  def end_table
81
+ self.set_section(nil)
65
82
  self.insert("</table>\n")
66
83
  end
67
84
 
@@ -80,9 +97,9 @@ module Coopy
80
97
  render = self
81
98
  render.begin_table
82
99
  change_row = -1
83
- tt = ::Coopy::TableText.new(tab)
84
100
  cell = ::Coopy::CellInfo.new
85
- corner = tt.get_cell_text(0,0)
101
+ view = tab.get_cell_view
102
+ corner = view.to_s(tab.get_cell(0,0))
86
103
  off = nil
87
104
  if corner == "@:@"
88
105
  off = 1
@@ -99,11 +116,16 @@ module Coopy
99
116
  row = _g1
100
117
  _g1+=1
101
118
  open = false
102
- txt = tt.get_cell_text(off,row)
119
+ txt = view.to_s(tab.get_cell(off,row))
103
120
  txt = "" if txt == nil
104
- ::Coopy::DiffRender.examine_cell(0,row,txt,"",txt,corner,cell)
121
+ ::Coopy::DiffRender.examine_cell(off,row,view,txt,"",txt,corner,cell,off)
105
122
  row_mode = cell.category
106
123
  change_row = row if row_mode == "spec"
124
+ if row_mode == "header" || row_mode == "spec" || row_mode == "index"
125
+ self.set_section("head")
126
+ else
127
+ self.set_section("body")
128
+ end
107
129
  render.begin_row(row_mode)
108
130
  begin
109
131
  _g3 = 0
@@ -111,7 +133,7 @@ module Coopy
111
133
  while(_g3 < _g2)
112
134
  c = _g3
113
135
  _g3+=1
114
- ::Coopy::DiffRender.examine_cell(c,row,tt.get_cell_text(c,row),((change_row >= 0) ? tt.get_cell_text(c,change_row) : ""),txt,corner,cell)
136
+ ::Coopy::DiffRender.examine_cell(c,row,view,tab.get_cell(c,row),((change_row >= 0) ? view.to_s(tab.get_cell(c,change_row)) : ""),txt,corner,cell,off)
115
137
  render.insert_cell(((@pretty_arrows) ? cell.pretty_value : cell.value),cell.category_given_tr)
116
138
  end
117
139
  end
@@ -123,17 +145,20 @@ module Coopy
123
145
  end
124
146
 
125
147
  def sample_css
126
- return ".highlighter .add { \n background-color: #7fff7f;\n}\n\n.highlighter .remove { \n background-color: #ff7f7f;\n}\n\n.highlighter td.modify { \n background-color: #7f7fff;\n}\n\n.highlighter td.conflict { \n background-color: #f00;\n}\n\n.highlighter .spec { \n background-color: #aaa;\n}\n\n.highlighter .move { \n background-color: #ffa;\n}\n\n.highlighter .null { \n color: #888;\n}\n\n.highlighter table { \n border-collapse:collapse;\n}\n\n.highlighter td, .highlighter th {\n border: 1px solid #2D4068;\n padding: 3px 7px 2px;\n}\n\n.highlighter th, .highlighter .header { \n background-color: #aaf;\n font-weight: bold;\n padding-bottom: 4px;\n padding-top: 5px;\n text-align:left;\n}\n\n.highlighter tr:first-child td {\n border-top: 1px solid #2D4068;\n}\n\n.highlighter td:first-child { \n border-left: 1px solid #2D4068;\n}\n\n.highlighter td {\n empty-cells: show;\n}\n"
148
+ return ".highlighter .add { \n background-color: #7fff7f;\n}\n\n.highlighter .remove { \n background-color: #ff7f7f;\n}\n\n.highlighter td.modify { \n background-color: #7f7fff;\n}\n\n.highlighter td.conflict { \n background-color: #f00;\n}\n\n.highlighter .spec { \n background-color: #aaa;\n}\n\n.highlighter .move { \n background-color: #ffa;\n}\n\n.highlighter .null { \n color: #888;\n}\n\n.highlighter table { \n border-collapse:collapse;\n}\n\n.highlighter td, .highlighter th {\n border: 1px solid #2D4068;\n padding: 3px 7px 2px;\n}\n\n.highlighter th, .highlighter .header { \n background-color: #aaf;\n font-weight: bold;\n padding-bottom: 4px;\n padding-top: 5px;\n text-align:left;\n}\n\n.highlighter tr.header th {\n border-bottom: 2px solid black;\n}\n\n.highlighter tr.index td, .highlighter .index, .highlighter tr.header th.index {\n background-color: white;\n border: none;\n}\n\n.highlighter .gap {\n color: #888;\n}\n\n.highlighter td {\n empty-cells: show;\n}\n"
127
149
  end
128
150
 
129
151
  def complete_html
130
- @text_to_insert.insert(0,"<html>\n<meta charset='utf-8'>\n<head>\n<style TYPE='text/css'>\n")
152
+ @text_to_insert.insert(0,"<!DOCTYPE html>\n<html>\n<head>\n<meta charset='utf-8'>\n<style TYPE='text/css'>\n")
131
153
  @text_to_insert.insert(1,self.sample_css)
132
154
  @text_to_insert.insert(2,"</style>\n</head>\n<body>\n<div class='highlighter'>\n")
133
155
  @text_to_insert.push("</div>\n</body>\n</html>\n")
134
156
  end
135
157
 
136
- def DiffRender.examine_cell(x,y,value,vcol,vrow,vcorner,cell)
158
+ def DiffRender.examine_cell(x,y,view,raw,vcol,vrow,vcorner,cell,offset = 0)
159
+ nested = view.is_hash(raw)
160
+ value = nil
161
+ value = view.to_s(raw) if !nested
137
162
  cell.category = ""
138
163
  cell.category_given_tr = ""
139
164
  cell.separator = ""
@@ -148,6 +173,7 @@ module Coopy
148
173
  vcol = "" if vcol == nil
149
174
  removed_column = false
150
175
  cell.category = "move" if vrow == ":"
176
+ cell.category = "index" if vrow == "" && offset == 1 && y == 0
151
177
  if (vcol.index("+++",nil || 0) || -1) >= 0
152
178
  cell.category_given_tr = cell.category = "add"
153
179
  elsif (vcol.index("---",nil || 0) || -1) >= 0
@@ -158,6 +184,8 @@ module Coopy
158
184
  cell.category = "spec"
159
185
  elsif vrow == "@@"
160
186
  cell.category = "header"
187
+ elsif vrow == "..."
188
+ cell.category = "gap"
161
189
  elsif vrow == "+++"
162
190
  cell.category = "add" if !removed_column
163
191
  elsif vrow == "---"
@@ -168,20 +196,30 @@ module Coopy
168
196
  full = vrow
169
197
  part = tokens[1]
170
198
  part = full if part == nil
171
- if (cell.value.index(part,nil || 0) || -1) >= 0
199
+ if nested || (cell.value.index(part,nil || 0) || -1) >= 0
172
200
  cat = "modify"
173
201
  div = part
174
202
  if part != full
175
- if (cell.value.index(full,nil || 0) || -1) >= 0
203
+ if nested
204
+ cell.conflicted = view.hash_exists(raw,"theirs")
205
+ else
206
+ cell.conflicted = (cell.value.index(full,nil || 0) || -1) >= 0
207
+ end
208
+ if cell.conflicted
176
209
  div = full
177
210
  cat = "conflict"
178
- cell.conflicted = true
179
211
  end
180
212
  end
181
213
  cell.updated = true
182
214
  cell.separator = div
183
215
  cell.pretty_separator = div
184
- if cell.pretty_value == div
216
+ if nested
217
+ if cell.conflicted
218
+ tokens = [view.hash_get(raw,"before"),view.hash_get(raw,"ours"),view.hash_get(raw,"theirs")]
219
+ else
220
+ tokens = [view.hash_get(raw,"before"),view.hash_get(raw,"after")]
221
+ end
222
+ elsif cell.pretty_value == div
185
223
  tokens = ["",""]
186
224
  else
187
225
  tokens = cell.pretty_value.split(div)
@@ -199,18 +237,19 @@ module Coopy
199
237
  cell.pretty_separator = [8594].pack("U")
200
238
  cell.pretty_value = pretty_tokens.join(cell.pretty_separator)
201
239
  cell.category_given_tr = cell.category = cat
202
- offset = nil
240
+ offset1 = nil
203
241
  if cell.conflicted
204
- offset = 1
242
+ offset1 = 1
205
243
  else
206
- offset = 0
244
+ offset1 = 0
207
245
  end
208
- cell.lvalue = tokens[offset]
209
- cell.rvalue = tokens[offset + 1]
246
+ cell.lvalue = tokens[offset1]
247
+ cell.rvalue = tokens[offset1 + 1]
210
248
  cell.pvalue = tokens[0] if cell.conflicted
211
249
  end
212
250
  end
213
251
  end
252
+ cell.category_given_tr = cell.category = "index" if x == 0 && offset > 0
214
253
  end
215
254
 
216
255
  # protected - in ruby this doesn't play well with static/inline methods
@@ -244,16 +283,16 @@ module Coopy
244
283
 
245
284
  public
246
285
 
247
- def DiffRender.render_cell(tt,x,y)
286
+ def DiffRender.render_cell(tab,view,x,y)
248
287
  cell = ::Coopy::CellInfo.new
249
- corner = tt.get_cell_text(0,0)
288
+ corner = view.to_s(tab.get_cell(0,0))
250
289
  off = nil
251
290
  if corner == "@:@"
252
291
  off = 1
253
292
  else
254
293
  off = 0
255
294
  end
256
- ::Coopy::DiffRender.examine_cell(x,y,tt.get_cell_text(x,y),tt.get_cell_text(x,off),tt.get_cell_text(off,y),corner,cell)
295
+ ::Coopy::DiffRender.examine_cell(x,y,view,tab.get_cell(x,y),view.to_s(tab.get_cell(x,off)),view.to_s(tab.get_cell(off,y)),corner,cell,off)
257
296
  return cell
258
297
  end
259
298