2015-12-18 17:48:04 +03:00
|
|
|
module PatchOutput (
|
|
|
|
patch,
|
|
|
|
hunks
|
|
|
|
) where
|
2015-12-18 01:22:09 +03:00
|
|
|
|
2015-12-18 01:22:53 +03:00
|
|
|
import Diff
|
2015-12-25 02:11:19 +03:00
|
|
|
import Line
|
2015-12-25 01:41:45 +03:00
|
|
|
import Row
|
2015-12-25 00:37:14 +03:00
|
|
|
import Source hiding ((++))
|
2015-12-25 01:41:45 +03:00
|
|
|
import Split
|
2015-12-25 02:11:19 +03:00
|
|
|
import Control.Comonad.Cofree
|
|
|
|
import Control.Monad.Free
|
2015-12-18 01:22:53 +03:00
|
|
|
|
2015-12-25 00:37:14 +03:00
|
|
|
patch :: Diff a Info -> Source Char -> Source Char -> String
|
2015-12-25 02:11:32 +03:00
|
|
|
patch diff sourceA sourceB = mconcat $ showHunk sourceA sourceB <$> hunks diff sourceA sourceB
|
2015-12-18 16:00:01 +03:00
|
|
|
|
2015-12-25 01:41:45 +03:00
|
|
|
data Hunk a = Hunk { offsetA :: Int, offsetB :: Int, getRows :: [Row (SplitDiff a Info)] }
|
2015-12-25 02:11:38 +03:00
|
|
|
deriving (Eq, Show)
|
2015-12-18 16:25:37 +03:00
|
|
|
|
2015-12-25 02:11:19 +03:00
|
|
|
showHunk sourceA sourceB hunk = header hunk ++ concat (showRow <$> getRows hunk)
|
|
|
|
where showRow (Row lineA lineB) = showLine sourceA lineA ++ showLine sourceB lineB
|
|
|
|
showLine _ EmptyLine = ""
|
|
|
|
showLine source line = toString . (`slice` source) . mconcat $ getRange <$> unLine line
|
|
|
|
getRange (Free (Annotated (Info range _) _)) = range
|
|
|
|
getRange (Pure (Info range _ :< _)) = range
|
|
|
|
|
2015-12-25 01:41:45 +03:00
|
|
|
header :: Hunk a -> String
|
|
|
|
header hunk = "@@ -" ++ show (offsetA hunk) ++ "," ++ show 0 ++ " +" ++ show (offsetB hunk) ++ "," ++ show 0 ++ " @@\n"
|
2015-12-18 16:07:43 +03:00
|
|
|
|
2015-12-25 01:41:45 +03:00
|
|
|
hunks :: Diff a Info -> Source Char -> Source Char -> [Hunk a]
|
2015-12-25 01:42:38 +03:00
|
|
|
hunks diff sourceA sourceB = hunksInRows rows
|
|
|
|
where (rows, _) = splitDiffByLines diff (0, 0) (sourceA, sourceB)
|
2015-12-25 01:42:08 +03:00
|
|
|
|
2015-12-25 01:42:22 +03:00
|
|
|
hunksInRows :: [Row (SplitDiff a Info)] -> [Hunk a]
|
|
|
|
hunksInRows rows = case nextHunk rows of
|
|
|
|
Nothing -> []
|
|
|
|
Just (hunk, rest) -> hunk : hunksInRows rest
|
|
|
|
|
2015-12-25 01:42:08 +03:00
|
|
|
nextHunk :: [Row (SplitDiff a Info)] -> Maybe (Hunk a, [Row (SplitDiff a Info)])
|
2015-12-25 01:58:09 +03:00
|
|
|
nextHunk rows = case hunkRows of
|
|
|
|
[] -> Nothing
|
|
|
|
hunkRows' -> Just (Hunk 0 0 hunkRows', afterChanges)
|
|
|
|
where hunkRows = takeLast 3 leadingRows ++ changes
|
|
|
|
|
|
|
|
(leadingRows, afterLeadingContext) = Prelude.break rowHasChanges rows
|
2015-12-25 01:42:08 +03:00
|
|
|
(changes, afterChanges) = span rowHasChanges afterLeadingContext
|
|
|
|
|
|
|
|
rowHasChanges (Row left right) = lineHasChanges left || lineHasChanges right
|
|
|
|
lineHasChanges = or . fmap diffHasChanges
|
|
|
|
diffHasChanges = or . fmap (const True)
|
2015-12-25 01:54:26 +03:00
|
|
|
|
|
|
|
takeLast :: Int -> [a] -> [a]
|
|
|
|
takeLast n = fst . foldr accum ([], 0)
|
|
|
|
where accum each (rest, i) = if i < n
|
|
|
|
then (each : rest, i + 1)
|
|
|
|
else (rest, i)
|