@hackage diff-loc0.1.0.0

Map file locations across diffs

diff-loc: Map file locations across diffs Hackage

Example

You have a diff between two versions of a file. Given a source span in one version, find the corresponding span in the other version.

For example, here is a diff d between a source string "abcdefgh" and a target string "appcfgzzh", with deletions and insertions in the middle:

  ab cdefg  h
-  b  de
+  pp     zz
  appc  fgzzh

Diffs are represented by the type Diff. Only locations and lengths are recorded, not the actual characters.

import DiffLoc
import DiffLoc.Unsafe (offset)

d :: Diff N
d = addDiff (Replace 1 (offset 1) (offset 2))  -- at location 1, replace "b" (length 1) with "pp" (length 2)
  $ addDiff (Replace 3 (offset 2) (offset 0))  -- at location 3, replace "de" with ""
  $ addDiff (Replace 7 (offset 0) (offset 2))  -- at location 7, replace "" with "zz"
  $ emptyDiff
-- N.B.: replacements should be inserted right to left, starting from 'emptyDiff'.

The span s of "fg" in the first string is an interval that starts at location 5 and has length 2.

s :: Interval N
s = 5 :.. offset 2

Illustration of the span:

 a b c d e f g h
0 1 2 3 4 5 6 7 8
          ^f+g+ length 2
          ^
          start 5

After applying the diff, the span has been shifted to location 4.

>>> mapDiff d (5 :.. offset 2)
Just (4 :.. offset 2)
 a p p c f g q q h
0 1 2 3 4 5 6 7 8 9
        ^f+g+ length 2
        ^
        start 4

Conversely, we can map spans from the target string to the source string of the diff:

>>> comapDiff d (4 :.. offset 2)
Just (5 :.. offset 2)

If part of the input span is modified by the diff, there is no corresponding output span.

>>> mapDiff d (1 :.. offset 2)  -- "bc" contains "b" which is edited by the diff
Nothing

See the API documentation in DiffLoc.