module Data.Algorithm.Diff.Context
( contextDiff
, groups
) where
import Data.Algorithm.Diff (Diff(..), getGroupedDiff)
contextDiff :: Eq a => Int -> [a] -> [a] -> [[Diff [a]]]
contextDiff context a b =
group $ swap $ trimTail $ trimHead $ concatMap split $ getGroupedDiff a b
where
split (Both xs ys) =
case length xs of
n | n > (2 * context) -> [Both (take context xs) (take context ys), Both (drop (n context) xs) (drop (n context) ys)]
_ -> [Both xs ys]
split x = [x]
trimHead [] = []
trimHead [Both _ _] = []
trimHead [Both _ _, Both _ _] = []
trimHead (Both _ _ : x@(Both _ _) : more) = x : more
trimHead xs = trimTail xs
trimTail [x@(Both _ _), Both _ _] = [x]
trimTail (x : more) = x : trimTail more
trimTail [] = []
swap (x@(Second _) : y@(First _) : xs) = y : x : swap xs
swap (x : xs) = x : swap xs
swap [] = []
group xs =
groups (\ x y -> not (isBoth x && isBoth y)) xs
where
isBoth (Both _ _) = True
isBoth _ = False
groups :: Eq a => (a -> a -> Bool) -> [a] -> [[a]]
groups f xs =
filter (/= []) $ reverse (groups' [[]] xs)
where
groups' (r : rs) (x : y : xs') | f x y = groups' ((x : r) : rs) (y : xs')
groups' (r : rs) (x : y : xs') = groups' ([y] : reverse (x : r) : rs) xs'
groups' (r : rs) [y] = reverse (y : r) : rs
groups' rs [] = rs
groups' [] (_ : _) = error "groups"