1
1
mirror of https://github.com/github/semantic.git synced 2024-11-28 10:15:55 +03:00
semantic/app/Unified.hs

52 lines
2.3 KiB
Haskell
Raw Normal View History

2015-11-20 04:38:21 +03:00
module Unified (unified) where
2015-11-20 01:36:32 +03:00
import Diff
import Patch
import Syntax
import Term
2015-11-20 02:53:23 +03:00
import Control.Arrow
import Control.Monad.Free
2015-11-20 02:53:23 +03:00
import Control.Comonad.Cofree
2015-11-20 04:23:06 +03:00
import Data.List hiding (foldl)
2015-11-20 04:22:55 +03:00
import qualified Data.Map as Map
2015-11-27 18:36:59 +03:00
import Rainbow
2015-11-20 01:36:32 +03:00
unified :: Diff a Info -> String -> String -> IO ByteString
unified diff before after = do
renderer <- byteStringMakerFromEnvironment
return . mconcat . chunksToByteStrings renderer . pure . fst $ iter g mapped where
2015-11-20 02:53:23 +03:00
mapped = fmap (unifiedPatch &&& range) diff
2015-11-20 04:22:55 +03:00
g (Annotated (_, info) syntax) = f info syntax
f (Info range _) (Leaf _) = (substring range after, Just range)
f (Info range _) (Indexed i) = (unifiedRange range i after, Just range)
f (Info range _) (Fixed f) = (unifiedRange range f after, Just range)
f (Info range _) (Keyed k) = (unifiedRange range (sort $ snd <$> Map.toList k) after, Just range)
2015-11-20 02:53:23 +03:00
unifiedPatch :: Patch (Term a Info) -> Chunk String
unifiedPatch patch = mappend (beforeChunk & fore red & bold) (afterChunk & fore green & bold) where
beforeChunk = maybe (chunk "") (change "-" . unifiedTerm before) $ Patch.before patch
afterChunk = maybe (chunk "") (change "+" . unifiedTerm after) $ Patch.after patch
2015-11-20 19:06:44 +03:00
unifiedTerm :: String -> Term a Info -> Chunk String
2015-11-20 04:36:51 +03:00
unifiedTerm source term = fst $ cata f term
2015-11-20 03:27:31 +03:00
unifiedRange :: Range -> [(Chunk String, Maybe Range)] -> String -> Chunk String
unifiedRange range children source = mappend out $ substring Range { start = previous, end = end range } after where
(out, previous) = foldl accumulateContext (chunk "", start range) children
accumulateContext (out, previous) (child, Just range) = (mconcat [ out, substring Range { start = previous, end = start range } source, child ], end range)
accumulateContext (out, previous) (child, _) = (mappend out child, previous)
2015-11-20 02:05:33 +03:00
substring :: Range -> String -> Chunk String
substring range = chunk . take (end range) . drop (start range)
2015-11-20 02:30:37 +03:00
range :: Patch (Term a Info) -> Maybe Range
range patch = range . extract <$> after patch where
extract (annotation :< _) = annotation
range (Info range _) = range
2015-11-20 03:07:30 +03:00
change :: String -> Chunk String -> Chunk String
change bound content = mconcat [ chunk "{", chunk bound, content, chunk bound, chunk "}" ]
2015-11-20 03:23:18 +03:00
instance Ord Range where
a <= b = start a <= start b