1
1
mirror of https://github.com/github/semantic.git synced 2024-12-29 01:42:43 +03:00
semantic/src/PatchOutput.hs

66 lines
2.4 KiB
Haskell
Raw Normal View History

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
import Line
2015-12-25 01:41:45 +03:00
import Row
import Source hiding ((++))
2015-12-25 01:41:45 +03:00
import Split
import Control.Comonad.Cofree
import Control.Monad.Free
2015-12-18 01:22:53 +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-25 02:23:04 +03:00
data Hunk a = Hunk { offsetA :: Int, offsetB :: Int, getRows :: [Row a] }
2015-12-25 02:11:38 +03:00
deriving (Eq, Show)
2015-12-18 16:25:37 +03:00
data Change a = Change { context :: [Row a], contents :: [Row a] }
deriving (Eq, Show)
2015-12-25 02:23:04 +03:00
showHunk :: Source Char -> Source Char -> Hunk (SplitDiff a Info) -> String
showHunk sourceA sourceB hunk = header hunk ++ concat (showRow <$> getRows hunk)
2015-12-25 02:20:28 +03:00
where showRow (Row lineA lineB) = showLine '-' sourceA lineA ++ showLine '+' sourceB lineB
showLine _ _ EmptyLine = ""
showLine prefix source line = prefix : (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 02:23:04 +03:00
hunks :: Diff a Info -> Source Char -> Source Char -> [Hunk (SplitDiff a Info)]
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 02:23:04 +03:00
hunksInRows :: [Row (SplitDiff a Info)] -> [Hunk (SplitDiff a Info)]
hunksInRows rows = case nextHunk rows of
Nothing -> []
Just (hunk, rest) -> hunk : hunksInRows rest
2015-12-25 02:23:04 +03:00
nextHunk :: [Row (SplitDiff a Info)] -> Maybe (Hunk (SplitDiff a Info), [Row (SplitDiff a Info)])
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
(changes, afterChanges) = span rowHasChanges afterLeadingContext
rowHasChanges :: Row (SplitDiff a Info) -> Bool
rowHasChanges (Row left right) = lineHasChanges left || lineHasChanges right
lineHasChanges :: Line (SplitDiff a Info) -> Bool
lineHasChanges = or . fmap diffHasChanges
diffHasChanges :: SplitDiff a Info -> Bool
diffHasChanges = or . fmap (const True)
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)