diff --git a/src/Split.hs b/src/Split.hs index 59c277bb5..98020635e 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -19,15 +19,15 @@ import Data.Monoid import qualified Data.Set as Set type ClassName = String -type Source = String +type Source a = [a] -subsource :: Range -> Source -> Source +subsource :: Range -> Source a -> Source a subsource = substring -toString :: Source -> String +toString :: Source Char -> String toString source = source -at :: Source -> Int -> Char +at :: Source a -> Int -> a at = (!!) classifyMarkup :: Foldable f => f String -> Markup -> Markup @@ -76,7 +76,7 @@ split diff before after = return . renderHtml -- | A diff with only one side’s annotations. type SplitDiff leaf annotation = Free (Annotated leaf annotation) (Term leaf annotation) -newtype Renderable a = Renderable (Source, a) +newtype Renderable a = Renderable (Source Char, a) instance ToMarkup f => ToMarkup (Renderable (Info, Syntax a (f, Range))) where toMarkup (Renderable (source, (Info range categories, syntax))) = classifyMarkup categories $ case syntax of @@ -98,7 +98,7 @@ instance ToMarkup (Renderable (SplitDiff a Info)) where where toMarkupAndRange :: Term a Info -> (Markup, Range) toMarkupAndRange term@(Info range _ :< _) = ((div ! A.class_ (stringValue "patch")) . toMarkup $ Renderable (source, term), range) -splitDiffByLines :: Diff a Info -> (Int, Int) -> (Source, Source) -> ([Row (SplitDiff a Info)], (Range, Range)) +splitDiffByLines :: Diff a Info -> (Int, Int) -> (Source Char, Source Char) -> ([Row (SplitDiff a Info)], (Range, Range)) splitDiffByLines diff (prevLeft, prevRight) sources = case diff of Free (Annotated annotation syntax) -> (splitAnnotatedByLines sources (ranges annotation) (categories annotation) syntax, ranges annotation) Pure (Insert term) -> let (lines, range) = splitTermByLines term (snd sources) in @@ -112,7 +112,7 @@ splitDiffByLines diff (prevLeft, prevRight) sources = case diff of ranges (Info left _, Info right _) = (left, right) -- | Takes a term and a source and returns a list of lines and their range within source. -splitTermByLines :: Term a Info -> Source -> ([Line (Term a Info)], Range) +splitTermByLines :: Term a Info -> Source Char -> ([Line (Term a Info)], Range) splitTermByLines (Info range categories :< syntax) source = flip (,) range $ case syntax of Leaf a -> contextLines (:< Leaf a) range categories source Indexed children -> adjoinChildLines Indexed children @@ -125,7 +125,7 @@ splitTermByLines (Info range categories :< syntax) source = flip (,) range $ cas childLines constructor (lines, previous) child = let (childLines, childRange) = splitTermByLines child source in (adjoin $ lines ++ contextLines (:< constructor) (Range previous $ start childRange) categories source ++ childLines, end childRange) -splitAnnotatedByLines :: (Source, Source) -> (Range, Range) -> (Set.Set Category, Set.Set Category) -> Syntax a (Diff a Info) -> [Row (SplitDiff a Info)] +splitAnnotatedByLines :: (Source Char, Source Char) -> (Range, Range) -> (Set.Set Category, Set.Set Category) -> Syntax a (Diff a Info) -> [Row (SplitDiff a Info)] splitAnnotatedByLines sources ranges categories syntax = case syntax of Leaf a -> contextRows (Leaf a) ranges categories sources Indexed children -> adjoinChildRows Indexed children @@ -144,25 +144,25 @@ splitAnnotatedByLines sources ranges categories syntax = case syntax of ends (left, right) = (end left, end right) makeRanges (leftStart, rightStart) (leftEnd, rightEnd) = (Range leftStart leftEnd, Range rightStart rightEnd) -contextLines :: (Info -> a) -> Range -> Set.Set Category -> Source -> [Line a] +contextLines :: (Info -> a) -> Range -> Set.Set Category -> Source Char -> [Line a] contextLines constructor range categories source = Line . (:[]) . constructor . (`Info` categories) <$> actualLineRanges range source -openRange :: Source -> Range -> Maybe Range +openRange :: Source Char -> Range -> Maybe Range openRange source range = case (source `at`) <$> maybeLastIndex range of Just '\n' -> Nothing _ -> Just range -openTerm :: Source -> Term a Info -> Maybe (Term a Info) +openTerm :: Source Char -> Term a Info -> Maybe (Term a Info) openTerm source term@(Info range _ :< _) = const term <$> openRange source range -openDiff :: Source -> SplitDiff a Info -> Maybe (SplitDiff a Info) +openDiff :: Source Char -> SplitDiff a Info -> Maybe (SplitDiff a Info) openDiff source diff@(Free (Annotated (Info range _) _)) = const diff <$> openRange source range openDiff source diff@(Pure term) = const diff <$> openTerm source term zipWithDefaults :: (a -> b -> c) -> a -> b -> [a] -> [b] -> [c] zipWithDefaults f da db a b = take (max (length a) (length b)) $ zipWith f (a ++ repeat da) (b ++ repeat db) -actualLines :: Source -> [Source] +actualLines :: Source Char -> [Source Char] actualLines "" = [""] actualLines lines = case break (== '\n') lines of (l, lines') -> case lines' of @@ -170,6 +170,6 @@ actualLines lines = case break (== '\n') lines of _:lines' -> (l ++ "\n") : actualLines lines' -- | Compute the line ranges within a given range of a string. -actualLineRanges :: Range -> Source -> [Range] +actualLineRanges :: Range -> Source Char -> [Range] actualLineRanges range = drop 1 . scanl toRange (Range (start range) (start range)) . actualLines . subsource range where toRange previous string = Range (end previous) $ end previous + length string