Method: String#stroke_diff

Defined in:
lib/strokedb/sync/diff/string.rb

#stroke_diff(to) ⇒ Object



3
4
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
# File 'lib/strokedb/sync/diff/string.rb', line 3

def stroke_diff(to)
  return super(to) unless to.is_a?(String)
  return nil if self == to
  
  _f = self[0,2]
  _t = to[0,2]
  pfx = "@#"
  # both are refs
  return super(to) if _f == _t && _t == pfx
  # one of items is ref, another is not.
  return super(to) if _f == pfx || _t == pfx
        
  lcs_diff = ::Diff::LCS.diff(self, to)
  patchset = lcs_diff.map do |changes| 
    parts = []
    last_part = changes.inject(nil) do |part, change|
      if part && part[0] == change.action && part[3] == change.position - 1
        part[3] += 1
        part[2] << change.element
        part
      else
        parts << part if part
        # emit
        [change.action, change.position, change.element, change.position]
      end
    end
    parts << last_part if last_part
    parts.empty? ? nil : parts
  end.compact.inject([]) do |patches, ps|
    ps.map do |p|
      patches << if p[0] == '+'
        [PATCH_PLUS,  p[1], p[2]]      # [+  position_in_b  substr]
      else
        [PATCH_MINUS, p[1], p[2].size] # [-  position_in_a  length]
      end
    end
    patches
  end
  #p patchset
  patchset.empty? ? nil : patchset
end