From c70c14bf1b00df7173bb6a3ae2499254ea9d1597 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 18 Dec 2015 16:16:43 -0500 Subject: [PATCH 001/259] Remove Debug.Trace. --- src/Split.hs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index a39afc2ab..bcfa8f90c 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -18,7 +18,6 @@ import qualified OrderedMap as Map import Data.Maybe import Data.Monoid import qualified Data.Set as Set -import Debug.Trace import Data.List (intersperse) type ClassName = String @@ -54,9 +53,6 @@ instance ToMarkup HTML where toMarkup (Div className children) = classifyMarkup className . div $ mconcat (toMarkup <$> children) toMarkup (Dt key) = dt $ string key -trace' :: Show a => a -> a -trace' a = traceShow a a - split :: Diff a Info -> String -> String -> IO ByteString split diff before after = return . renderHtml . docTypeHtml From eb89e828bba8029d1c821e45b525a1af6e69368c Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 18 Dec 2015 16:37:16 -0500 Subject: [PATCH 002/259] Add a type parameter to Row. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently it’s a phantom type. --- src/Split.hs | 24 ++++++++++++------------ test/SplitSpec.hs | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index bcfa8f90c..15a5b73c7 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -74,7 +74,7 @@ split diff before after = return . renderHtml columnWidth = max (20 + digits maxNumber * 8) 40 - numberRows :: [(Int, Line, Int, Line)] -> Row -> [(Int, Line, Int, Line)] + numberRows :: [(Int, Line, Int, Line)] -> Row HTML -> [(Int, Line, Int, Line)] numberRows [] (Row EmptyLine EmptyLine) = [] numberRows [] (Row left@(Line _ _) EmptyLine) = [(1, left, 0, EmptyLine)] numberRows [] (Row EmptyLine right@(Line _ _)) = [(0, EmptyLine, 1, right)] @@ -85,10 +85,10 @@ split diff before after = return . renderHtml numberRows rows@((leftCount, _, rightCount, _):_) (Row left right) = (leftCount + 1, left, rightCount + 1, right):rows -data Row = Row Line Line +data Row a = Row Line Line deriving Eq -instance Show Row where +instance Show (Row a) where show (Row left right) = "\n" ++ show left ++ " | " ++ show right instance ToMarkup (Int, Line, Int, Line) where @@ -136,11 +136,11 @@ instance Monoid Line where mappend (Line c xs) EmptyLine = Line c xs mappend (Line c1 xs) (Line c2 ys) = Line (c1 || c2) (xs <> ys) -instance Monoid Row where +instance Monoid (Row a) where mempty = Row EmptyLine EmptyLine mappend (Row x1 y1) (Row x2 y2) = Row (x1 <> x2) (y1 <> y2) -diffToRows :: Diff a Info -> (Int, Int) -> String -> String -> ([Row], (Range, Range)) +diffToRows :: Diff a Info -> (Int, Int) -> String -> String -> ([Row HTML], (Range, Range)) diffToRows (Free annotated) _ before after = annotatedToRows annotated before after diffToRows (Pure (Insert term)) (previousIndex, _) _ after = (rowWithInsertedLine <$> afterLines, (Range previousIndex previousIndex, range)) where @@ -156,7 +156,7 @@ diffToRows (Pure (Replace a b)) _ before after = (replacedRows, (leftRange, righ where replacedRows = zipWithMaybe rowFromMaybeRows (replace <$> leftElements) (replace <$> rightElements) replace = (:[]) . Div (Just "replace") . unLine - rowFromMaybeRows :: Maybe [HTML] -> Maybe [HTML] -> Row + rowFromMaybeRows :: Maybe [HTML] -> Maybe [HTML] -> Row HTML rowFromMaybeRows a b = Row (maybe EmptyLine (Line True) a) (maybe EmptyLine (Line True) b) (leftElements, leftRange) = termToLines a before (rightElements, rightRange) = termToLines b after @@ -185,7 +185,7 @@ termToLines (Info range categories :< syntax) source = (rows syntax, range) elements = (elementAndBreak $ Span (classify categories)) =<< actualLines (substring range source) -- | Given an Annotated and before/after strings, returns a list of `Row`s representing the newline-separated diff. -annotatedToRows :: Annotated a (Info, Info) (Diff a Info) -> String -> String -> ([Row], (Range, Range)) +annotatedToRows :: Annotated a (Info, Info) (Diff a Info) -> String -> String -> ([Row HTML], (Range, Range)) annotatedToRows (Annotated (Info left leftCategories, Info right rightCategories) syntax) before after = (rows syntax, ranges) where rows (Leaf _) = zipWithMaybe rowFromMaybeRows leftElements rightElements @@ -209,7 +209,7 @@ annotatedToRows (Annotated (Info left leftCategories, Info right rightCategories allRows = rows ++ separatorRows ++ childRows (childRows, childRanges) = diffToRows child previousIndices before after -contextRows :: (Int, Int) -> (Int, Int) -> (String, String) -> [Row] +contextRows :: (Int, Int) -> (Int, Int) -> (String, String) -> [Row HTML] contextRows childIndices previousIndices sources = zipWithMaybe rowFromMaybeRows leftElements rightElements where leftElements = textElements (Range (fst previousIndices) (fst childIndices)) (fst sources) @@ -231,13 +231,13 @@ starts (left, right) = (start left, start right) ends :: (Range, Range) -> (Int, Int) ends (left, right) = (end left, end right) -rowFromMaybeRows :: Maybe HTML -> Maybe HTML -> Row +rowFromMaybeRows :: Maybe HTML -> Maybe HTML -> (Row HTML) rowFromMaybeRows a b = Row (maybe EmptyLine (Line False . (:[])) a) (maybe EmptyLine (Line False . (:[])) b) maybeLast :: [a] -> Maybe a maybeLast list = listToMaybe $ reverse list -adjoin2 :: [Row] -> Row -> [Row] +adjoin2 :: [Row a] -> Row a -> [Row a] adjoin2 [] row = [row] adjoin2 rows (Row left' right') | Just _ <- openLine $ leftLines rows, Just _ <- openLine $ rightLines rows = zipWith Row lefts rights @@ -260,12 +260,12 @@ adjoin2 rows (Row left' right') | Just _ <- openLine $ rightLines rows = case le adjoin2 rows row = row : rows -leftLines :: [Row] -> [Line] +leftLines :: [Row a] -> [Line] leftLines rows = left <$> rows where left (Row left _) = left -rightLines :: [Row] -> [Line] +rightLines :: [Row a] -> [Line] rightLines rows = right <$> rows where right (Row _ right) = right diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index fc71340a5..dc4219869 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -12,7 +12,7 @@ import Control.Monad.Free hiding (unfold) import Patch import Syntax -instance Arbitrary Row where +instance Arbitrary (Row a) where arbitrary = oneof [ Row <$> arbitrary <*> arbitrary ] From 7964727da6fbc099ea28a21823636708f535b575 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 18 Dec 2015 16:41:50 -0500 Subject: [PATCH 003/259] Add a type parameter to Line. --- src/Split.hs | 30 +++++++++++++++--------------- test/SplitSpec.hs | 2 +- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 15a5b73c7..8260cd496 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -74,7 +74,7 @@ split diff before after = return . renderHtml columnWidth = max (20 + digits maxNumber * 8) 40 - numberRows :: [(Int, Line, Int, Line)] -> Row HTML -> [(Int, Line, Int, Line)] + numberRows :: [(Int, Line HTML, Int, Line HTML)] -> Row HTML -> [(Int, Line HTML, Int, Line HTML)] numberRows [] (Row EmptyLine EmptyLine) = [] numberRows [] (Row left@(Line _ _) EmptyLine) = [(1, left, 0, EmptyLine)] numberRows [] (Row EmptyLine right@(Line _ _)) = [(0, EmptyLine, 1, right)] @@ -85,16 +85,16 @@ split diff before after = return . renderHtml numberRows rows@((leftCount, _, rightCount, _):_) (Row left right) = (leftCount + 1, left, rightCount + 1, right):rows -data Row a = Row Line Line +data Row a = Row (Line a) (Line a) deriving Eq instance Show (Row a) where show (Row left right) = "\n" ++ show left ++ " | " ++ show right -instance ToMarkup (Int, Line, Int, Line) where +instance ToMarkup (Int, Line a, Int, Line a) where toMarkup (m, left, n, right) = tr $ toMarkup (m, left) <> toMarkup (n, right) <> string "\n" -instance ToMarkup (Int, Line) where +instance ToMarkup (Int, Line a) where toMarkup (_, EmptyLine) = numberTd "" <> toMarkup EmptyLine <> string "\n" toMarkup (num, line@(Line True _)) = td (string $ show num) ! A.class_ (stringValue "blob-num blob-num-replacement") <> toMarkup line <> string "\n" toMarkup (num, line@(Line _ _)) = numberTd (show num) <> toMarkup line <> string "\n" @@ -108,28 +108,28 @@ codeTd _ Nothing = td mempty ! A.class_ (stringValue "blob-code blob-code-empty codeTd True (Just el) = td el ! A.class_ (stringValue "blob-code blob-code-replacement") codeTd _ (Just el) = td el ! A.class_ (stringValue "blob-code") -instance ToMarkup Line where +instance ToMarkup (Line a) where toMarkup EmptyLine = codeTd False Nothing toMarkup (Line changed html) = codeTd changed . Just . mconcat $ toMarkup <$> html -data Line = +data Line a = Line Bool [HTML] | EmptyLine deriving Eq -unLine :: Line -> [HTML] +unLine :: Line a -> [HTML] unLine EmptyLine = [] unLine (Line _ htmls) = htmls -isChanged :: Line -> Bool +isChanged :: Line a -> Bool isChanged EmptyLine = False isChanged (Line isChanged _) = isChanged -instance Show Line where +instance Show (Line a) where show (Line change elements) = show change ++ " [" ++ (concat . intersperse ", " $ show <$> elements) ++ "]" show EmptyLine = "EmptyLine" -instance Monoid Line where +instance Monoid (Line a) where mempty = EmptyLine mappend EmptyLine EmptyLine = EmptyLine mappend EmptyLine (Line c ys) = Line c ys @@ -163,7 +163,7 @@ diffToRows (Pure (Replace a b)) _ before after = (replacedRows, (leftRange, righ -- | Takes a term and a `source` and returns a list of HTML lines -- | and their range within `source`. -termToLines :: Term a Info -> String -> ([Line], Range) +termToLines :: Term a Info -> String -> ([Line HTML], Range) termToLines (Info range categories :< syntax) source = (rows syntax, range) where rows (Leaf _) = reverse $ foldl adjoin2Lines [] $ Line True . (:[]) <$> elements @@ -260,12 +260,12 @@ adjoin2 rows (Row left' right') | Just _ <- openLine $ rightLines rows = case le adjoin2 rows row = row : rows -leftLines :: [Row a] -> [Line] +leftLines :: [Row a] -> [Line a] leftLines rows = left <$> rows where left (Row left _) = left -rightLines :: [Row a] -> [Line] +rightLines :: [Row a] -> [Line a] rightLines rows = right <$> rows where right (Row _ right) = right @@ -277,12 +277,12 @@ openElement (Dl _ elements) = openElement =<< maybeLast elements openElement (Div _ elements) = openElement =<< maybeLast elements openElement h = Just h -openLine :: [Line] -> Maybe Line +openLine :: [Line a] -> Maybe (Line a) openLine [] = Nothing openLine (EmptyLine : rest) = openLine rest openLine (line : _) = const line <$> (openElement =<< (maybeLast $ unLine line)) -adjoin2Lines :: [Line] -> Line -> [Line] +adjoin2Lines :: [Line a] -> Line a -> [Line a] adjoin2Lines [] line = [line] adjoin2Lines (EmptyLine : xs) line | Just _ <- openLine xs = EmptyLine : adjoin2Lines xs line adjoin2Lines (prev:rest) line | Just _ <- openLine [ prev ] = (prev <> line) : rest diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index dc4219869..a7f29bbfc 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -22,7 +22,7 @@ instance Arbitrary HTML where Span <$> arbitrary <*> arbitrary, const Break <$> (arbitrary :: Gen ()) ] -instance Arbitrary Line where +instance Arbitrary (Line a) where arbitrary = oneof [ Line <$> arbitrary <*> arbitrary, const EmptyLine <$> (arbitrary :: Gen ()) ] From 2ede50401ef226f1b142da66bbebcf3d37a1e1ec Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 18 Dec 2015 16:45:06 -0500 Subject: [PATCH 004/259] Constrain the ToMarkup instances to ToMarkup a. --- src/Split.hs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 8260cd496..3f8f84dea 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -91,11 +91,11 @@ data Row a = Row (Line a) (Line a) instance Show (Row a) where show (Row left right) = "\n" ++ show left ++ " | " ++ show right -instance ToMarkup (Int, Line a, Int, Line a) where +instance ToMarkup a => ToMarkup (Int, Line a, Int, Line a) where toMarkup (m, left, n, right) = tr $ toMarkup (m, left) <> toMarkup (n, right) <> string "\n" -instance ToMarkup (Int, Line a) where - toMarkup (_, EmptyLine) = numberTd "" <> toMarkup EmptyLine <> string "\n" +instance ToMarkup a => ToMarkup (Int, Line a) where + toMarkup (_, line@EmptyLine) = numberTd "" <> toMarkup line <> string "\n" toMarkup (num, line@(Line True _)) = td (string $ show num) ! A.class_ (stringValue "blob-num blob-num-replacement") <> toMarkup line <> string "\n" toMarkup (num, line@(Line _ _)) = numberTd (show num) <> toMarkup line <> string "\n" @@ -108,7 +108,7 @@ codeTd _ Nothing = td mempty ! A.class_ (stringValue "blob-code blob-code-empty codeTd True (Just el) = td el ! A.class_ (stringValue "blob-code blob-code-replacement") codeTd _ (Just el) = td el ! A.class_ (stringValue "blob-code") -instance ToMarkup (Line a) where +instance ToMarkup a => ToMarkup (Line a) where toMarkup EmptyLine = codeTd False Nothing toMarkup (Line changed html) = codeTd changed . Just . mconcat $ toMarkup <$> html From 9ec602ee821d1476bb249557e9c5a505972a6372 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 18 Dec 2015 17:33:45 -0500 Subject: [PATCH 005/259] The Show instances are constrained to `Show a`. --- src/Split.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 3f8f84dea..43bd4bd6e 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -88,7 +88,7 @@ split diff before after = return . renderHtml data Row a = Row (Line a) (Line a) deriving Eq -instance Show (Row a) where +instance Show a => Show (Row a) where show (Row left right) = "\n" ++ show left ++ " | " ++ show right instance ToMarkup a => ToMarkup (Int, Line a, Int, Line a) where @@ -125,7 +125,7 @@ isChanged :: Line a -> Bool isChanged EmptyLine = False isChanged (Line isChanged _) = isChanged -instance Show (Line a) where +instance Show a => Show (Line a) where show (Line change elements) = show change ++ " [" ++ (concat . intersperse ", " $ show <$> elements) ++ "]" show EmptyLine = "EmptyLine" From 5089c1d2ed1ece77d7ea8540af2995613b3f0bbf Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 18 Dec 2015 17:34:08 -0500 Subject: [PATCH 006/259] Rename the unLine parameter. --- src/Split.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Split.hs b/src/Split.hs index 43bd4bd6e..004376a72 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -119,7 +119,7 @@ data Line a = unLine :: Line a -> [HTML] unLine EmptyLine = [] -unLine (Line _ htmls) = htmls +unLine (Line _ elements) = elements isChanged :: Line a -> Bool isChanged EmptyLine = False From 3ec55a34a4e0f300ba2b3ce33859714e0128a45c Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 09:52:27 -0500 Subject: [PATCH 007/259] Add a generalization of openLine, parameterized by the selection of an open element. --- src/Split.hs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Split.hs b/src/Split.hs index 004376a72..f25f35c57 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -282,6 +282,11 @@ openLine [] = Nothing openLine (EmptyLine : rest) = openLine rest openLine (line : _) = const line <$> (openElement =<< (maybeLast $ unLine line)) +openLineBy :: (a -> Maybe a) -> [Line a] -> Maybe (Line a) +openLineBy _ [] = Nothing +openLineBy f (EmptyLine : rest) = openLineBy f rest +openLineBy f (line : _) = const line <$> (f =<< (maybeLast $ unLine line)) + adjoin2Lines :: [Line a] -> Line a -> [Line a] adjoin2Lines [] line = [line] adjoin2Lines (EmptyLine : xs) line | Just _ <- openLine xs = EmptyLine : adjoin2Lines xs line From afafed623c6da4fd914b00cb7617541bed2a2f4f Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 09:52:41 -0500 Subject: [PATCH 008/259] Define openLine in terms of openLineBy. --- src/Split.hs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index f25f35c57..ca7a09694 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -277,10 +277,8 @@ openElement (Dl _ elements) = openElement =<< maybeLast elements openElement (Div _ elements) = openElement =<< maybeLast elements openElement h = Just h -openLine :: [Line a] -> Maybe (Line a) -openLine [] = Nothing -openLine (EmptyLine : rest) = openLine rest -openLine (line : _) = const line <$> (openElement =<< (maybeLast $ unLine line)) +openLine :: [Line HTML] -> Maybe (Line HTML) +openLine lines = openLineBy openElement lines openLineBy :: (a -> Maybe a) -> [Line a] -> Maybe (Line a) openLineBy _ [] = Nothing From 05785a0b0673c871a2aafc445445aed007822c79 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 09:52:57 -0500 Subject: [PATCH 009/259] Add a generalization of adjoin2Lines, parameterized by the selection of an open element. --- src/Split.hs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Split.hs b/src/Split.hs index ca7a09694..91f574182 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -291,6 +291,12 @@ adjoin2Lines (EmptyLine : xs) line | Just _ <- openLine xs = EmptyLine : adjoin2 adjoin2Lines (prev:rest) line | Just _ <- openLine [ prev ] = (prev <> line) : rest adjoin2Lines lines line = line : lines +adjoin2LinesBy :: (a -> Maybe a) -> [Line a] -> Line a -> [Line a] +adjoin2LinesBy _ [] line = [line] +adjoin2LinesBy f (EmptyLine : xs) line | Just _ <- openLineBy f xs = EmptyLine : adjoin2LinesBy f xs line +adjoin2LinesBy f (prev:rest) line | Just _ <- openLineBy f [ prev ] = (prev <> line) : rest +adjoin2LinesBy _ lines line = line : lines + zipWithMaybe :: (Maybe a -> Maybe b -> c) -> [a] -> [b] -> [c] zipWithMaybe f la lb = take len $ zipWith f la' lb' where From 4c0b6e963634d23021632b14ba6fde7567ebe9f4 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 09:53:37 -0500 Subject: [PATCH 010/259] Define adjoin2Lines in terms of adjoin2LinesBy. --- src/Split.hs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 91f574182..b88bbc4a9 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -285,11 +285,8 @@ openLineBy _ [] = Nothing openLineBy f (EmptyLine : rest) = openLineBy f rest openLineBy f (line : _) = const line <$> (f =<< (maybeLast $ unLine line)) -adjoin2Lines :: [Line a] -> Line a -> [Line a] -adjoin2Lines [] line = [line] -adjoin2Lines (EmptyLine : xs) line | Just _ <- openLine xs = EmptyLine : adjoin2Lines xs line -adjoin2Lines (prev:rest) line | Just _ <- openLine [ prev ] = (prev <> line) : rest -adjoin2Lines lines line = line : lines +adjoin2Lines :: [Line HTML] -> Line HTML -> [Line HTML] +adjoin2Lines = adjoin2LinesBy openElement adjoin2LinesBy :: (a -> Maybe a) -> [Line a] -> Line a -> [Line a] adjoin2LinesBy _ [] line = [line] From b8e843a50548406878b8eda81b06267da5761482 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 09:53:49 -0500 Subject: [PATCH 011/259] Spacing. --- src/Split.hs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Split.hs b/src/Split.hs index b88bbc4a9..f475933d2 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -5,7 +5,6 @@ import Diff import Patch import Term import Syntax - import Control.Comonad.Cofree import Range import Control.Monad.Free From a9c744a54c5eb14fc4765081345279e1258a9b7b Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 09:54:03 -0500 Subject: [PATCH 012/259] Eta-reduce the openLine definition. --- src/Split.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Split.hs b/src/Split.hs index f475933d2..c6f059d88 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -277,7 +277,7 @@ openElement (Div _ elements) = openElement =<< maybeLast elements openElement h = Just h openLine :: [Line HTML] -> Maybe (Line HTML) -openLine lines = openLineBy openElement lines +openLine = openLineBy openElement openLineBy :: (a -> Maybe a) -> [Line a] -> Maybe (Line a) openLineBy _ [] = Nothing From f714e83b62805184b294139be74f01f35db307b7 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 09:56:33 -0500 Subject: [PATCH 013/259] Define adjoin2 in terms of its generalization over the selection of an open element. --- src/Split.hs | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index c6f059d88..9bbf408a9 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -236,28 +236,31 @@ rowFromMaybeRows a b = Row (maybe EmptyLine (Line False . (:[])) a) (maybe Empty maybeLast :: [a] -> Maybe a maybeLast list = listToMaybe $ reverse list -adjoin2 :: [Row a] -> Row a -> [Row a] -adjoin2 [] row = [row] +adjoin2 :: [Row HTML] -> Row HTML -> [Row HTML] +adjoin2 = adjoin2By openElement -adjoin2 rows (Row left' right') | Just _ <- openLine $ leftLines rows, Just _ <- openLine $ rightLines rows = zipWith Row lefts rights - where lefts = adjoin2Lines (leftLines rows) left' - rights = adjoin2Lines (rightLines rows) right' +adjoin2By :: (a -> Maybe a) -> [Row a] -> Row a -> [Row a] +adjoin2By _ [] row = [row] -adjoin2 rows (Row left' right') | Just _ <- openLine $ leftLines rows = case right' of +adjoin2By f rows (Row left' right') | Just _ <- openLineBy f $ leftLines rows, Just _ <- openLineBy f $ rightLines rows = zipWith Row lefts rights + where lefts = adjoin2LinesBy f (leftLines rows) left' + rights = adjoin2LinesBy f (rightLines rows) right' + +adjoin2By f rows (Row left' right') | Just _ <- openLineBy f $ leftLines rows = case right' of EmptyLine -> rest _ -> Row EmptyLine right' : rest where rest = zipWith Row lefts rights - lefts = adjoin2Lines (leftLines rows) left' + lefts = adjoin2LinesBy f (leftLines rows) left' rights = rightLines rows -adjoin2 rows (Row left' right') | Just _ <- openLine $ rightLines rows = case left' of +adjoin2By f rows (Row left' right') | Just _ <- openLineBy f $ rightLines rows = case left' of EmptyLine -> rest _ -> Row left' EmptyLine : rest where rest = zipWith Row lefts rights lefts = leftLines rows - rights = adjoin2Lines (rightLines rows) right' + rights = adjoin2LinesBy f (rightLines rows) right' -adjoin2 rows row = row : rows +adjoin2By _ rows row = row : rows leftLines :: [Row a] -> [Line a] leftLines rows = left <$> rows From 3424df075acb7f44fe9828b3f92a56f90d3bea99 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 09:58:02 -0500 Subject: [PATCH 014/259] Generalize Line and unLine over a. --- src/Split.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 9bbf408a9..861dbbafe 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -112,11 +112,11 @@ instance ToMarkup a => ToMarkup (Line a) where toMarkup (Line changed html) = codeTd changed . Just . mconcat $ toMarkup <$> html data Line a = - Line Bool [HTML] + Line Bool [a] | EmptyLine deriving Eq -unLine :: Line a -> [HTML] +unLine :: Line a -> [a] unLine EmptyLine = [] unLine (Line _ elements) = elements From c9f13f2f413c3741599e99c6770535c91823f16c Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 09:58:20 -0500 Subject: [PATCH 015/259] Define the arbitrary instances for Row and Line in terms of an Arbitrary type a. --- test/SplitSpec.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index a7f29bbfc..f5c5810c3 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -12,7 +12,7 @@ import Control.Monad.Free hiding (unfold) import Patch import Syntax -instance Arbitrary (Row a) where +instance Arbitrary a => Arbitrary (Row a) where arbitrary = oneof [ Row <$> arbitrary <*> arbitrary ] @@ -22,7 +22,7 @@ instance Arbitrary HTML where Span <$> arbitrary <*> arbitrary, const Break <$> (arbitrary :: Gen ()) ] -instance Arbitrary (Line a) where +instance Arbitrary a => Arbitrary (Line a) where arbitrary = oneof [ Line <$> arbitrary <*> arbitrary, const EmptyLine <$> (arbitrary :: Gen ()) ] From 9404ee75c3537d65d0eef504c3319ec26f7c9870 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 10:01:00 -0500 Subject: [PATCH 016/259] Test openLineBy, not openLine. --- test/SplitSpec.hs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index f5c5810c3..4d698da23 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -142,16 +142,16 @@ spec = do Line True [ span "*/" ] ], Range 0 5) - describe "openLine" $ do + describe "openLineBy" $ do it "should produce the earliest non-empty line in a list, if open" $ - openLine [ + openLineBy openElement [ Line True [ Div (Just "delete") [ span "*/" ] ], Line True [ Div (Just "delete") [ span " * Debugging", Break ] ], Line True [ Div (Just "delete") [ span "/*", Break ] ] ] `shouldBe` (Just $ Line True [ Div (Just "delete") [ span "*/" ] ]) it "should return Nothing if the earliest non-empty line is closed" $ - openLine [ + openLineBy openElement [ Line True [ Div (Just "delete") [ span " * Debugging", Break ] ] ] `shouldBe` Nothing @@ -167,6 +167,6 @@ spec = do offsetInfo by (Info (Range start end) categories) = Info (Range (start + by) (end + by)) categories offsetAnnotated by1 by2 (Annotated (left, right) syntax) = Annotated (offsetInfo by1 left, offsetInfo by2 right) syntax span = Span (Just "category-leaf") - isOpen (Row a b) = (maybe False (const True) $ openLine [ a ]) && (maybe False (const True) $ openLine [ b ]) - isClosed (Row a@(Line _ _) b@(Line _ _)) = (maybe True (const False) $ openLine [ a ]) && (maybe True (const False) $ openLine [ b ]) + isOpen (Row a b) = (maybe False (const True) $ openLineBy openElement [ a ]) && (maybe False (const True) $ openLineBy openElement [ b ]) + isClosed (Row a@(Line _ _) b@(Line _ _)) = (maybe True (const False) $ openLineBy openElement [ a ]) && (maybe True (const False) $ openLineBy openElement [ b ]) isClosed (Row _ _) = False From e92d4037fd9685b4755769bbc40acfa4168a907e Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 10:01:03 -0500 Subject: [PATCH 017/259] Remove openLine. --- src/Split.hs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 861dbbafe..7aa38982b 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -279,9 +279,6 @@ openElement (Dl _ elements) = openElement =<< maybeLast elements openElement (Div _ elements) = openElement =<< maybeLast elements openElement h = Just h -openLine :: [Line HTML] -> Maybe (Line HTML) -openLine = openLineBy openElement - openLineBy :: (a -> Maybe a) -> [Line a] -> Maybe (Line a) openLineBy _ [] = Nothing openLineBy f (EmptyLine : rest) = openLineBy f rest From 422dad44a910899c0ad4b2b1ae3c274d98308500 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 10:03:03 -0500 Subject: [PATCH 018/259] Define termToLines in terms of adjoin2LinesBy. --- src/Split.hs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 7aa38982b..55f2fdf39 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -165,7 +165,7 @@ diffToRows (Pure (Replace a b)) _ before after = (replacedRows, (leftRange, righ termToLines :: Term a Info -> String -> ([Line HTML], Range) termToLines (Info range categories :< syntax) source = (rows syntax, range) where - rows (Leaf _) = reverse $ foldl adjoin2Lines [] $ Line True . (:[]) <$> elements + rows (Leaf _) = reverse $ foldl (adjoin2LinesBy openElement) [] $ Line True . (:[]) <$> elements rows (Indexed i) = rewrapLineContentsIn Ul <$> childLines i rows (Fixed f) = rewrapLineContentsIn Ul <$> childLines f rows (Keyed k) = rewrapLineContentsIn Dl <$> childLines k @@ -174,12 +174,12 @@ termToLines (Info range categories :< syntax) source = (rows syntax, range) rewrapLineContentsIn _ EmptyLine = EmptyLine lineElements r s = Line True . (:[]) <$> textElements r s childLines i = appendRemainder $ foldl sumLines ([], start range) i - appendRemainder (lines, previous) = reverse . foldl adjoin2Lines [] $ lines ++ lineElements (Range previous (end range)) source + appendRemainder (lines, previous) = reverse . foldl (adjoin2LinesBy openElement) [] $ lines ++ lineElements (Range previous (end range)) source sumLines (lines, previous) child = (allLines, end childRange) where separatorLines = lineElements (Range previous $ start childRange) source unadjoinedLines = lines ++ separatorLines ++ childLines - allLines = reverse $ foldl adjoin2Lines [] unadjoinedLines + allLines = reverse $ foldl (adjoin2LinesBy openElement) [] unadjoinedLines (childLines, childRange) = termToLines child source elements = (elementAndBreak $ Span (classify categories)) =<< actualLines (substring range source) From c19dbc27b0935ce1ceec19398a5df8af933ac50c Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 10:03:08 -0500 Subject: [PATCH 019/259] Remove adjoin2Lines. --- src/Split.hs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 55f2fdf39..17a43ddaf 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -284,9 +284,6 @@ openLineBy _ [] = Nothing openLineBy f (EmptyLine : rest) = openLineBy f rest openLineBy f (line : _) = const line <$> (f =<< (maybeLast $ unLine line)) -adjoin2Lines :: [Line HTML] -> Line HTML -> [Line HTML] -adjoin2Lines = adjoin2LinesBy openElement - adjoin2LinesBy :: (a -> Maybe a) -> [Line a] -> Line a -> [Line a] adjoin2LinesBy _ [] line = [line] adjoin2LinesBy f (EmptyLine : xs) line | Just _ <- openLineBy f xs = EmptyLine : adjoin2LinesBy f xs line From 9ef0242ac824a1d3bfa9f6654f627061f4749775 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 10:04:02 -0500 Subject: [PATCH 020/259] Define annotatedToRows in terms of adjoin2By. --- src/Split.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Split.hs b/src/Split.hs index 17a43ddaf..0ecfe564e 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -201,7 +201,7 @@ annotatedToRows (Annotated (Info left leftCategories, Info right rightCategories ranges = (left, right) sources = (before, after) childRows = appendRemainder . foldl sumRows ([], starts ranges) - appendRemainder (rows, previousIndices) = reverse . foldl adjoin2 [] $ rows ++ (contextRows (ends ranges) previousIndices sources) + appendRemainder (rows, previousIndices) = reverse . foldl (adjoin2By openElement) [] $ rows ++ (contextRows (ends ranges) previousIndices sources) sumRows (rows, previousIndices) child = (allRows, ends childRanges) where separatorRows = contextRows (starts childRanges) previousIndices sources From 446383565c99c9d759b56f8159ee6785ab1116ad Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 10:04:47 -0500 Subject: [PATCH 021/259] Test adjoin2By. --- test/SplitSpec.hs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index 4d698da23..898849971 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -112,26 +112,26 @@ spec = do ([ Row (Line False [ span "t\776" ]) (Line False [ span "\7831"]) ], (Range 0 2, Range 0 1)) - describe "adjoin2" $ do + describe "adjoin2By" $ do prop "is identity on top of no rows" $ - \ a -> adjoin2 [] a == [ a ] + \ a -> adjoin2By openElement [] a == [ a ] prop "appends onto open rows" $ forAll ((arbitrary `suchThat` isOpen) >>= \ a -> ((,) a) <$> (arbitrary `suchThat` isOpen)) $ \ (a@(Row (Line ac1 as1) (Line bc1 bs1)), b@(Row (Line ac2 as2) (Line bc2 bs2))) -> - adjoin2 [ a ] b `shouldBe` [ Row (Line (ac1 || ac2) $ as1 ++ as2) (Line (bc1 || bc2) $ bs1 ++ bs2) ] + adjoin2By openElement [ a ] b `shouldBe` [ Row (Line (ac1 || ac2) $ as1 ++ as2) (Line (bc1 || bc2) $ bs1 ++ bs2) ] prop "does not append onto closed rows" $ forAll ((arbitrary `suchThat` isClosed) >>= \ a -> ((,) a) <$> (arbitrary `suchThat` isClosed)) $ - \ (a, b) -> adjoin2 [ a ] b `shouldBe` [ b, a ] + \ (a, b) -> adjoin2By openElement [ a ] b `shouldBe` [ b, a ] prop "does not promote elements through empty lines onto closed lines" $ forAll ((arbitrary `suchThat` isClosed) >>= \ a -> ((,) a) <$> (arbitrary `suchThat` isClosed)) $ - \ (a, b) -> adjoin2 [ Row EmptyLine EmptyLine, a ] b `shouldBe` [ b, Row EmptyLine EmptyLine, a ] + \ (a, b) -> adjoin2By openElement [ Row EmptyLine EmptyLine, a ] b `shouldBe` [ b, Row EmptyLine EmptyLine, a ] prop "promotes elements through empty lines onto open lines" $ forAll ((arbitrary `suchThat` isOpen) >>= \ a -> ((,) a) <$> (arbitrary `suchThat` isOpen)) $ - \ (a, b) -> adjoin2 [ Row EmptyLine EmptyLine, a ] b `shouldBe` Row EmptyLine EmptyLine : adjoin2 [ a ] b + \ (a, b) -> adjoin2By openElement [ Row EmptyLine EmptyLine, a ] b `shouldBe` Row EmptyLine EmptyLine : adjoin2By openElement [ a ] b describe "termToLines" $ do it "splits multi-line terms into multiple lines" $ From 4b487669a968784d7de737f9fd0e0246a90bec0a Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 10:04:51 -0500 Subject: [PATCH 022/259] Remove adjoin2. --- src/Split.hs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 0ecfe564e..26a023348 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -236,9 +236,6 @@ rowFromMaybeRows a b = Row (maybe EmptyLine (Line False . (:[])) a) (maybe Empty maybeLast :: [a] -> Maybe a maybeLast list = listToMaybe $ reverse list -adjoin2 :: [Row HTML] -> Row HTML -> [Row HTML] -adjoin2 = adjoin2By openElement - adjoin2By :: (a -> Maybe a) -> [Row a] -> Row a -> [Row a] adjoin2By _ [] row = [row] From 09fb6238c4b73731e4eb76d19600159a63a5f9aa Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 10:05:49 -0500 Subject: [PATCH 023/259] Remove isChanged. --- src/Split.hs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 26a023348..2127d2758 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -120,10 +120,6 @@ unLine :: Line a -> [a] unLine EmptyLine = [] unLine (Line _ elements) = elements -isChanged :: Line a -> Bool -isChanged EmptyLine = False -isChanged (Line isChanged _) = isChanged - instance Show a => Show (Line a) where show (Line change elements) = show change ++ " [" ++ (concat . intersperse ", " $ show <$> elements) ++ "]" show EmptyLine = "EmptyLine" From 3d17c9a8f0e3f3a86a2a1c37dc5778e7d215c425 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 10:12:14 -0500 Subject: [PATCH 024/259] Use an operator section to avoid some awkwardness. --- src/Split.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Split.hs b/src/Split.hs index 2127d2758..adb16a4d8 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -58,7 +58,7 @@ split diff before after = return . renderHtml . ((head $ link ! A.rel (stringValue "stylesheet") ! A.href (stringValue "style.css")) <>) . body . (table ! A.class_ (stringValue "diff")) $ - ((<>) (colgroup $ (col ! A.width (stringValue . show $ columnWidth)) <> col <> (col ! A.width (stringValue . show $ columnWidth)) <> col)) + ((colgroup $ (col ! A.width (stringValue . show $ columnWidth)) <> col <> (col ! A.width (stringValue . show $ columnWidth)) <> col) <>) . mconcat $ toMarkup <$> reverse numbered where rows = fst $ diffToRows diff (0, 0) before after From 058d8d89f966528338b78bf4af77c296d1facb01 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 10:14:12 -0500 Subject: [PATCH 025/259] Use logBase. --- src/Split.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Split.hs b/src/Split.hs index adb16a4d8..6d6844f9a 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -69,7 +69,7 @@ split diff before after = return . renderHtml digits :: Int -> Int digits n = let base = 10 :: Int in - ceiling (log(fromIntegral n) / log(fromIntegral base) :: Double) + ceiling (logBase (fromIntegral base) (fromIntegral n) :: Double) columnWidth = max (20 + digits maxNumber * 8) 40 From 5f01b38d53da48ecc0877cfb44f0138515e876f3 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 10:15:26 -0500 Subject: [PATCH 026/259] Intercalate! --- src/Split.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 6d6844f9a..c03def46e 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -17,7 +17,7 @@ import qualified OrderedMap as Map import Data.Maybe import Data.Monoid import qualified Data.Set as Set -import Data.List (intersperse) +import Data.List (intercalate) type ClassName = String @@ -121,7 +121,7 @@ unLine EmptyLine = [] unLine (Line _ elements) = elements instance Show a => Show (Line a) where - show (Line change elements) = show change ++ " [" ++ (concat . intersperse ", " $ show <$> elements) ++ "]" + show (Line change elements) = show change ++ " [" ++ (intercalate ", " $ show <$> elements) ++ "]" show EmptyLine = "EmptyLine" instance Monoid (Line a) where From b8c21e96af28a836a3f53ee9d1e36594f699cdee Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 10:16:42 -0500 Subject: [PATCH 027/259] Apply all the linter feedback. --- src/Split.hs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index c03def46e..77b6a4233 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -121,7 +121,7 @@ unLine EmptyLine = [] unLine (Line _ elements) = elements instance Show a => Show (Line a) where - show (Line change elements) = show change ++ " [" ++ (intercalate ", " $ show <$> elements) ++ "]" + show (Line change elements) = show change ++ " [" ++ intercalate ", " (show <$> elements) ++ "]" show EmptyLine = "EmptyLine" instance Monoid (Line a) where @@ -177,7 +177,7 @@ termToLines (Info range categories :< syntax) source = (rows syntax, range) unadjoinedLines = lines ++ separatorLines ++ childLines allLines = reverse $ foldl (adjoin2LinesBy openElement) [] unadjoinedLines (childLines, childRange) = termToLines child source - elements = (elementAndBreak $ Span (classify categories)) =<< actualLines (substring range source) + elements = elementAndBreak (Span $ classify categories) =<< actualLines (substring range source) -- | Given an Annotated and before/after strings, returns a list of `Row`s representing the newline-separated diff. annotatedToRows :: Annotated a (Info, Info) (Diff a Info) -> String -> String -> ([Row HTML], (Range, Range)) @@ -188,8 +188,8 @@ annotatedToRows (Annotated (Info left leftCategories, Info right rightCategories rows (Fixed f) = rewrapRowContentsIn Ul <$> childRows f rows (Keyed k) = rewrapRowContentsIn Dl <$> childRows (snd <$> Map.toList k) - leftElements = (elementAndBreak $ Span (classify leftCategories)) =<< actualLines (substring left before) - rightElements = (elementAndBreak $ Span (classify rightCategories)) =<< actualLines (substring right after) + leftElements = elementAndBreak (Span $ classify leftCategories) =<< actualLines (substring left before) + rightElements = elementAndBreak (Span $ classify rightCategories) =<< actualLines (substring right after) wrap _ EmptyLine = EmptyLine wrap f (Line c elements) = Line c [ f elements ] @@ -197,7 +197,7 @@ annotatedToRows (Annotated (Info left leftCategories, Info right rightCategories ranges = (left, right) sources = (before, after) childRows = appendRemainder . foldl sumRows ([], starts ranges) - appendRemainder (rows, previousIndices) = reverse . foldl (adjoin2By openElement) [] $ rows ++ (contextRows (ends ranges) previousIndices sources) + appendRemainder (rows, previousIndices) = reverse . foldl (adjoin2By openElement) [] $ rows ++ contextRows (ends ranges) previousIndices sources sumRows (rows, previousIndices) child = (allRows, ends childRanges) where separatorRows = contextRows (starts childRanges) previousIndices sources @@ -217,7 +217,7 @@ elementAndBreak constructor x | '\n' <- last x = [ constructor $ init x, Break ] elementAndBreak constructor x = [ constructor x ] textElements :: Range -> String -> [HTML] -textElements range source = (elementAndBreak Text) =<< actualLines s +textElements range source = elementAndBreak Text =<< actualLines s where s = substring range source starts :: (Range , Range) -> (Int, Int) @@ -226,7 +226,7 @@ starts (left, right) = (start left, start right) ends :: (Range, Range) -> (Int, Int) ends (left, right) = (end left, end right) -rowFromMaybeRows :: Maybe HTML -> Maybe HTML -> (Row HTML) +rowFromMaybeRows :: Maybe HTML -> Maybe HTML -> Row HTML rowFromMaybeRows a b = Row (maybe EmptyLine (Line False . (:[])) a) (maybe EmptyLine (Line False . (:[])) b) maybeLast :: [a] -> Maybe a @@ -275,7 +275,7 @@ openElement h = Just h openLineBy :: (a -> Maybe a) -> [Line a] -> Maybe (Line a) openLineBy _ [] = Nothing openLineBy f (EmptyLine : rest) = openLineBy f rest -openLineBy f (line : _) = const line <$> (f =<< (maybeLast $ unLine line)) +openLineBy f (line : _) = const line <$> (f =<< maybeLast (unLine line)) adjoin2LinesBy :: (a -> Maybe a) -> [Line a] -> Line a -> [Line a] adjoin2LinesBy _ [] line = [line] @@ -287,8 +287,8 @@ zipWithMaybe :: (Maybe a -> Maybe b -> c) -> [a] -> [b] -> [c] zipWithMaybe f la lb = take len $ zipWith f la' lb' where len = max (length la) (length lb) - la' = (Just <$> la) ++ (repeat Nothing) - lb' = (Just <$> lb) ++ (repeat Nothing) + la' = (Just <$> la) ++ repeat Nothing + lb' = (Just <$> lb) ++ repeat Nothing classify :: Set.Set Category -> Maybe ClassName classify = foldr (const . Just . ("category-" ++)) Nothing @@ -296,6 +296,6 @@ classify = foldr (const . Just . ("category-" ++)) Nothing actualLines :: String -> [String] actualLines "" = [""] actualLines lines = case break (== '\n') lines of - (l, lines') -> (case lines' of - [] -> [ l ] - _:lines' -> (l ++ "\n") : actualLines lines') + (l, lines') -> case lines' of + [] -> [ l ] + _:lines' -> (l ++ "\n") : actualLines lines' From 0823ca7f698bdb426e87f782c68e6bb5a0506b30 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 11:01:44 -0500 Subject: [PATCH 028/259] Move starts/ends into the where clause. --- src/Split.hs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 77b6a4233..a8e5efb6d 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -198,6 +198,8 @@ annotatedToRows (Annotated (Info left leftCategories, Info right rightCategories sources = (before, after) childRows = appendRemainder . foldl sumRows ([], starts ranges) appendRemainder (rows, previousIndices) = reverse . foldl (adjoin2By openElement) [] $ rows ++ contextRows (ends ranges) previousIndices sources + starts (left, right) = (start left, start right) + ends (left, right) = (end left, end right) sumRows (rows, previousIndices) child = (allRows, ends childRanges) where separatorRows = contextRows (starts childRanges) previousIndices sources @@ -220,12 +222,6 @@ textElements :: Range -> String -> [HTML] textElements range source = elementAndBreak Text =<< actualLines s where s = substring range source -starts :: (Range , Range) -> (Int, Int) -starts (left, right) = (start left, start right) - -ends :: (Range, Range) -> (Int, Int) -ends (left, right) = (end left, end right) - rowFromMaybeRows :: Maybe HTML -> Maybe HTML -> Row HTML rowFromMaybeRows a b = Row (maybe EmptyLine (Line False . (:[])) a) (maybe EmptyLine (Line False . (:[])) b) From 03fcd995797ea21bbff6add4acf150895bdc1f4e Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 11:50:49 -0500 Subject: [PATCH 029/259] Generalize maybeLast to arbitrary Foldable. --- src/Split.hs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index a8e5efb6d..3bd9a7af1 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -14,7 +14,6 @@ import Text.Blaze.Html5 hiding (map) import qualified Text.Blaze.Html5.Attributes as A import Text.Blaze.Html.Renderer.Utf8 import qualified OrderedMap as Map -import Data.Maybe import Data.Monoid import qualified Data.Set as Set import Data.List (intercalate) @@ -225,8 +224,8 @@ textElements range source = elementAndBreak Text =<< actualLines s rowFromMaybeRows :: Maybe HTML -> Maybe HTML -> Row HTML rowFromMaybeRows a b = Row (maybe EmptyLine (Line False . (:[])) a) (maybe EmptyLine (Line False . (:[])) b) -maybeLast :: [a] -> Maybe a -maybeLast list = listToMaybe $ reverse list +maybeLast :: Foldable f => f a -> Maybe a +maybeLast = foldl (flip $ const . Just) Nothing adjoin2By :: (a -> Maybe a) -> [Row a] -> Row a -> [Row a] adjoin2By _ [] row = [row] From e823fb6281e954280ca5bfd86ff23c5bd3f72034 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 12:22:20 -0500 Subject: [PATCH 030/259] Add a maybeLastIndex function over Range. This is a better option than making Range Foldable at the moment. --- src/Range.hs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Range.hs b/src/Range.hs index e02451b34..1a6806b64 100644 --- a/src/Range.hs +++ b/src/Range.hs @@ -34,6 +34,9 @@ rangesAndWordsFrom startIndex string = maybe [] id $ takeAndContinue <$> (word < -- | > A member of one of the following Unicode general category _Letter_, _Mark_, _Number_, _Connector_Punctuation_ isWord c = Char.isLetter c || Char.isNumber c || Char.isMark c || Char.generalCategory c == Char.ConnectorPunctuation +maybeLastIndex :: Range -> Maybe Int +maybeLastIndex (Range start end) | start == end = Nothing +maybeLastIndex (Range _ end) = Just $ end - 1 instance Ord Range where a <= b = start a <= start b From 1e2c1979ee326133873c3bf0abdf783ff026ebb6 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 12:22:52 -0500 Subject: [PATCH 031/259] Document maybeLastIndex. --- src/Range.hs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Range.hs b/src/Range.hs index 1a6806b64..58dede3d1 100644 --- a/src/Range.hs +++ b/src/Range.hs @@ -34,6 +34,7 @@ rangesAndWordsFrom startIndex string = maybe [] id $ takeAndContinue <$> (word < -- | > A member of one of the following Unicode general category _Letter_, _Mark_, _Number_, _Connector_Punctuation_ isWord c = Char.isLetter c || Char.isNumber c || Char.isMark c || Char.generalCategory c == Char.ConnectorPunctuation +-- | Return Just the last index from a non-empty range, or if the range is empty, Nothing. maybeLastIndex :: Range -> Maybe Int maybeLastIndex (Range start end) | start == end = Nothing maybeLastIndex (Range _ end) = Just $ end - 1 From 7f1079e0ca2be980123314d69a18779b96793b91 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 12:23:21 -0500 Subject: [PATCH 032/259] Document Range. --- src/Range.hs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Range.hs b/src/Range.hs index 58dede3d1..55fa997a8 100644 --- a/src/Range.hs +++ b/src/Range.hs @@ -3,6 +3,7 @@ module Range where import Control.Applicative ((<|>)) import qualified Data.Char as Char +-- | A half-open interval of integers, defined by start & end indices. data Range = Range { start :: Int, end :: Int } deriving (Eq, Show) From a4d30ec3ff297286a9a95350a36003b09dc51c8a Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 12:34:21 -0500 Subject: [PATCH 033/259] Add an openTerm function. --- src/Split.hs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Split.hs b/src/Split.hs index 3bd9a7af1..68a85b11e 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -267,6 +267,11 @@ openElement (Dl _ elements) = openElement =<< maybeLast elements openElement (Div _ elements) = openElement =<< maybeLast elements openElement h = Just h +openTerm :: String -> Term a Info -> Maybe (Term a Info) +openTerm source term@(Info range _ :< _) = case (source !!) <$> maybeLastIndex range of + Just '\n' -> Just term + _ -> Nothing + openLineBy :: (a -> Maybe a) -> [Line a] -> Maybe (Line a) openLineBy _ [] = Nothing openLineBy f (EmptyLine : rest) = openLineBy f rest From 706e3c499a9a0242da7d60cec5e23b31d244abba Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 12:35:34 -0500 Subject: [PATCH 034/259] Generalize numberRows. --- src/Split.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Split.hs b/src/Split.hs index 68a85b11e..07407e3c7 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -72,7 +72,7 @@ split diff before after = return . renderHtml columnWidth = max (20 + digits maxNumber * 8) 40 - numberRows :: [(Int, Line HTML, Int, Line HTML)] -> Row HTML -> [(Int, Line HTML, Int, Line HTML)] + numberRows :: [(Int, Line a, Int, Line a)] -> Row a -> [(Int, Line a, Int, Line a)] numberRows [] (Row EmptyLine EmptyLine) = [] numberRows [] (Row left@(Line _ _) EmptyLine) = [(1, left, 0, EmptyLine)] numberRows [] (Row EmptyLine right@(Line _ _)) = [(0, EmptyLine, 1, right)] From 3a159f1ae98863e856dc182234377f1acb288c45 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 12:39:36 -0500 Subject: [PATCH 035/259] rewrapLineContentsIn does not classify terms. --- src/Split.hs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 07407e3c7..821f6b866 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -161,11 +161,11 @@ termToLines :: Term a Info -> String -> ([Line HTML], Range) termToLines (Info range categories :< syntax) source = (rows syntax, range) where rows (Leaf _) = reverse $ foldl (adjoin2LinesBy openElement) [] $ Line True . (:[]) <$> elements - rows (Indexed i) = rewrapLineContentsIn Ul <$> childLines i - rows (Fixed f) = rewrapLineContentsIn Ul <$> childLines f - rows (Keyed k) = rewrapLineContentsIn Dl <$> childLines k + rows (Indexed i) = rewrapLineContentsIn (Ul $ classify categories) <$> childLines i + rows (Fixed f) = rewrapLineContentsIn (Ul $ classify categories) <$> childLines f + rows (Keyed k) = rewrapLineContentsIn (Dl $ classify categories) <$> childLines k - rewrapLineContentsIn f (Line _ elements) = Line True [ f (classify categories) elements ] + rewrapLineContentsIn f (Line _ elements) = Line True [ f elements ] rewrapLineContentsIn _ EmptyLine = EmptyLine lineElements r s = Line True . (:[]) <$> textElements r s childLines i = appendRemainder $ foldl sumLines ([], start range) i From cbf334481aa1ecf574566771c88f89ebfdc08222 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 12:48:54 -0500 Subject: [PATCH 036/259] Rename lineElements to contextLines. --- src/Split.hs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 821f6b866..968c775f8 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -167,12 +167,12 @@ termToLines (Info range categories :< syntax) source = (rows syntax, range) rewrapLineContentsIn f (Line _ elements) = Line True [ f elements ] rewrapLineContentsIn _ EmptyLine = EmptyLine - lineElements r s = Line True . (:[]) <$> textElements r s + contextLines r s = Line True . (:[]) <$> textElements r s childLines i = appendRemainder $ foldl sumLines ([], start range) i - appendRemainder (lines, previous) = reverse . foldl (adjoin2LinesBy openElement) [] $ lines ++ lineElements (Range previous (end range)) source + appendRemainder (lines, previous) = reverse . foldl (adjoin2LinesBy openElement) [] $ lines ++ contextLines (Range previous (end range)) source sumLines (lines, previous) child = (allLines, end childRange) where - separatorLines = lineElements (Range previous $ start childRange) source + separatorLines = contextLines (Range previous $ start childRange) source unadjoinedLines = lines ++ separatorLines ++ childLines allLines = reverse $ foldl (adjoin2LinesBy openElement) [] unadjoinedLines (childLines, childRange) = termToLines child source From 66376d202a25c63d359023541e7d4d91e664ed0d Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 12:50:58 -0500 Subject: [PATCH 037/259] Tighten up the definition of childLines a little. --- src/Split.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 968c775f8..8b07efb2c 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -168,8 +168,8 @@ termToLines (Info range categories :< syntax) source = (rows syntax, range) rewrapLineContentsIn f (Line _ elements) = Line True [ f elements ] rewrapLineContentsIn _ EmptyLine = EmptyLine contextLines r s = Line True . (:[]) <$> textElements r s - childLines i = appendRemainder $ foldl sumLines ([], start range) i - appendRemainder (lines, previous) = reverse . foldl (adjoin2LinesBy openElement) [] $ lines ++ contextLines (Range previous (end range)) source + childLines i = let (lines, previous) = foldl sumLines ([], start range) i in + reverse . foldl (adjoin2LinesBy openElement) [] $ lines ++ contextLines (Range previous (end range)) source sumLines (lines, previous) child = (allLines, end childRange) where separatorLines = contextLines (Range previous $ start childRange) source From ed6d6fffa128ae70dda1f0401ff41824b0024632 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 12:57:04 -0500 Subject: [PATCH 038/259] =?UTF-8?q?Rename=20adjoin2LinesBy=20=E2=86=92=20a?= =?UTF-8?q?djoinLinesBy.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Split.hs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 8b07efb2c..3f4825c8a 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -160,7 +160,7 @@ diffToRows (Pure (Replace a b)) _ before after = (replacedRows, (leftRange, righ termToLines :: Term a Info -> String -> ([Line HTML], Range) termToLines (Info range categories :< syntax) source = (rows syntax, range) where - rows (Leaf _) = reverse $ foldl (adjoin2LinesBy openElement) [] $ Line True . (:[]) <$> elements + rows (Leaf _) = reverse $ foldl (adjoinLinesBy openElement) [] $ Line True . (:[]) <$> elements rows (Indexed i) = rewrapLineContentsIn (Ul $ classify categories) <$> childLines i rows (Fixed f) = rewrapLineContentsIn (Ul $ classify categories) <$> childLines f rows (Keyed k) = rewrapLineContentsIn (Dl $ classify categories) <$> childLines k @@ -169,12 +169,12 @@ termToLines (Info range categories :< syntax) source = (rows syntax, range) rewrapLineContentsIn _ EmptyLine = EmptyLine contextLines r s = Line True . (:[]) <$> textElements r s childLines i = let (lines, previous) = foldl sumLines ([], start range) i in - reverse . foldl (adjoin2LinesBy openElement) [] $ lines ++ contextLines (Range previous (end range)) source + reverse . foldl (adjoinLinesBy openElement) [] $ lines ++ contextLines (Range previous (end range)) source sumLines (lines, previous) child = (allLines, end childRange) where separatorLines = contextLines (Range previous $ start childRange) source unadjoinedLines = lines ++ separatorLines ++ childLines - allLines = reverse $ foldl (adjoin2LinesBy openElement) [] unadjoinedLines + allLines = reverse $ foldl (adjoinLinesBy openElement) [] unadjoinedLines (childLines, childRange) = termToLines child source elements = elementAndBreak (Span $ classify categories) =<< actualLines (substring range source) @@ -231,14 +231,14 @@ adjoin2By :: (a -> Maybe a) -> [Row a] -> Row a -> [Row a] adjoin2By _ [] row = [row] adjoin2By f rows (Row left' right') | Just _ <- openLineBy f $ leftLines rows, Just _ <- openLineBy f $ rightLines rows = zipWith Row lefts rights - where lefts = adjoin2LinesBy f (leftLines rows) left' - rights = adjoin2LinesBy f (rightLines rows) right' + where lefts = adjoinLinesBy f (leftLines rows) left' + rights = adjoinLinesBy f (rightLines rows) right' adjoin2By f rows (Row left' right') | Just _ <- openLineBy f $ leftLines rows = case right' of EmptyLine -> rest _ -> Row EmptyLine right' : rest where rest = zipWith Row lefts rights - lefts = adjoin2LinesBy f (leftLines rows) left' + lefts = adjoinLinesBy f (leftLines rows) left' rights = rightLines rows adjoin2By f rows (Row left' right') | Just _ <- openLineBy f $ rightLines rows = case left' of @@ -246,7 +246,7 @@ adjoin2By f rows (Row left' right') | Just _ <- openLineBy f $ rightLines rows = _ -> Row left' EmptyLine : rest where rest = zipWith Row lefts rights lefts = leftLines rows - rights = adjoin2LinesBy f (rightLines rows) right' + rights = adjoinLinesBy f (rightLines rows) right' adjoin2By _ rows row = row : rows @@ -277,11 +277,11 @@ openLineBy _ [] = Nothing openLineBy f (EmptyLine : rest) = openLineBy f rest openLineBy f (line : _) = const line <$> (f =<< maybeLast (unLine line)) -adjoin2LinesBy :: (a -> Maybe a) -> [Line a] -> Line a -> [Line a] -adjoin2LinesBy _ [] line = [line] -adjoin2LinesBy f (EmptyLine : xs) line | Just _ <- openLineBy f xs = EmptyLine : adjoin2LinesBy f xs line -adjoin2LinesBy f (prev:rest) line | Just _ <- openLineBy f [ prev ] = (prev <> line) : rest -adjoin2LinesBy _ lines line = line : lines +adjoinLinesBy :: (a -> Maybe a) -> [Line a] -> Line a -> [Line a] +adjoinLinesBy _ [] line = [line] +adjoinLinesBy f (EmptyLine : xs) line | Just _ <- openLineBy f xs = EmptyLine : adjoinLinesBy f xs line +adjoinLinesBy f (prev:rest) line | Just _ <- openLineBy f [ prev ] = (prev <> line) : rest +adjoinLinesBy _ lines line = line : lines zipWithMaybe :: (Maybe a -> Maybe b -> c) -> [a] -> [b] -> [c] zipWithMaybe f la lb = take len $ zipWith f la' lb' From d4cfb276a45c2277080876a6d6de8d3cfb530bd9 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 12:57:11 -0500 Subject: [PATCH 039/259] =?UTF-8?q?Rename=20adjoin2By=20=E2=86=92=20adjoin?= =?UTF-8?q?By.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Split.hs | 14 +++++++------- test/SplitSpec.hs | 12 ++++++------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 3f4825c8a..986f1452d 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -196,7 +196,7 @@ annotatedToRows (Annotated (Info left leftCategories, Info right rightCategories ranges = (left, right) sources = (before, after) childRows = appendRemainder . foldl sumRows ([], starts ranges) - appendRemainder (rows, previousIndices) = reverse . foldl (adjoin2By openElement) [] $ rows ++ contextRows (ends ranges) previousIndices sources + appendRemainder (rows, previousIndices) = reverse . foldl (adjoinBy openElement) [] $ rows ++ contextRows (ends ranges) previousIndices sources starts (left, right) = (start left, start right) ends (left, right) = (end left, end right) sumRows (rows, previousIndices) child = (allRows, ends childRanges) @@ -227,28 +227,28 @@ rowFromMaybeRows a b = Row (maybe EmptyLine (Line False . (:[])) a) (maybe Empty maybeLast :: Foldable f => f a -> Maybe a maybeLast = foldl (flip $ const . Just) Nothing -adjoin2By :: (a -> Maybe a) -> [Row a] -> Row a -> [Row a] -adjoin2By _ [] row = [row] +adjoinBy :: (a -> Maybe a) -> [Row a] -> Row a -> [Row a] +adjoinBy _ [] row = [row] -adjoin2By f rows (Row left' right') | Just _ <- openLineBy f $ leftLines rows, Just _ <- openLineBy f $ rightLines rows = zipWith Row lefts rights +adjoinBy f rows (Row left' right') | Just _ <- openLineBy f $ leftLines rows, Just _ <- openLineBy f $ rightLines rows = zipWith Row lefts rights where lefts = adjoinLinesBy f (leftLines rows) left' rights = adjoinLinesBy f (rightLines rows) right' -adjoin2By f rows (Row left' right') | Just _ <- openLineBy f $ leftLines rows = case right' of +adjoinBy f rows (Row left' right') | Just _ <- openLineBy f $ leftLines rows = case right' of EmptyLine -> rest _ -> Row EmptyLine right' : rest where rest = zipWith Row lefts rights lefts = adjoinLinesBy f (leftLines rows) left' rights = rightLines rows -adjoin2By f rows (Row left' right') | Just _ <- openLineBy f $ rightLines rows = case left' of +adjoinBy f rows (Row left' right') | Just _ <- openLineBy f $ rightLines rows = case left' of EmptyLine -> rest _ -> Row left' EmptyLine : rest where rest = zipWith Row lefts rights lefts = leftLines rows rights = adjoinLinesBy f (rightLines rows) right' -adjoin2By _ rows row = row : rows +adjoinBy _ rows row = row : rows leftLines :: [Row a] -> [Line a] leftLines rows = left <$> rows diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index 898849971..315ad56bb 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -112,26 +112,26 @@ spec = do ([ Row (Line False [ span "t\776" ]) (Line False [ span "\7831"]) ], (Range 0 2, Range 0 1)) - describe "adjoin2By" $ do + describe "adjoinBy" $ do prop "is identity on top of no rows" $ - \ a -> adjoin2By openElement [] a == [ a ] + \ a -> adjoinBy openElement [] a == [ a ] prop "appends onto open rows" $ forAll ((arbitrary `suchThat` isOpen) >>= \ a -> ((,) a) <$> (arbitrary `suchThat` isOpen)) $ \ (a@(Row (Line ac1 as1) (Line bc1 bs1)), b@(Row (Line ac2 as2) (Line bc2 bs2))) -> - adjoin2By openElement [ a ] b `shouldBe` [ Row (Line (ac1 || ac2) $ as1 ++ as2) (Line (bc1 || bc2) $ bs1 ++ bs2) ] + adjoinBy openElement [ a ] b `shouldBe` [ Row (Line (ac1 || ac2) $ as1 ++ as2) (Line (bc1 || bc2) $ bs1 ++ bs2) ] prop "does not append onto closed rows" $ forAll ((arbitrary `suchThat` isClosed) >>= \ a -> ((,) a) <$> (arbitrary `suchThat` isClosed)) $ - \ (a, b) -> adjoin2By openElement [ a ] b `shouldBe` [ b, a ] + \ (a, b) -> adjoinBy openElement [ a ] b `shouldBe` [ b, a ] prop "does not promote elements through empty lines onto closed lines" $ forAll ((arbitrary `suchThat` isClosed) >>= \ a -> ((,) a) <$> (arbitrary `suchThat` isClosed)) $ - \ (a, b) -> adjoin2By openElement [ Row EmptyLine EmptyLine, a ] b `shouldBe` [ b, Row EmptyLine EmptyLine, a ] + \ (a, b) -> adjoinBy openElement [ Row EmptyLine EmptyLine, a ] b `shouldBe` [ b, Row EmptyLine EmptyLine, a ] prop "promotes elements through empty lines onto open lines" $ forAll ((arbitrary `suchThat` isOpen) >>= \ a -> ((,) a) <$> (arbitrary `suchThat` isOpen)) $ - \ (a, b) -> adjoin2By openElement [ Row EmptyLine EmptyLine, a ] b `shouldBe` Row EmptyLine EmptyLine : adjoin2By openElement [ a ] b + \ (a, b) -> adjoinBy openElement [ Row EmptyLine EmptyLine, a ] b `shouldBe` Row EmptyLine EmptyLine : adjoinBy openElement [ a ] b describe "termToLines" $ do it "splits multi-line terms into multiple lines" $ From 64362581c4f324ea2f581ee27fc895f39916e6ca Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 12:57:50 -0500 Subject: [PATCH 040/259] =?UTF-8?q?Rename=20adjoinBy=20=E2=86=92=20adjoinR?= =?UTF-8?q?owsBy.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Split.hs | 14 +++++++------- test/SplitSpec.hs | 12 ++++++------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 986f1452d..9c77e4d41 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -196,7 +196,7 @@ annotatedToRows (Annotated (Info left leftCategories, Info right rightCategories ranges = (left, right) sources = (before, after) childRows = appendRemainder . foldl sumRows ([], starts ranges) - appendRemainder (rows, previousIndices) = reverse . foldl (adjoinBy openElement) [] $ rows ++ contextRows (ends ranges) previousIndices sources + appendRemainder (rows, previousIndices) = reverse . foldl (adjoinRowsBy openElement) [] $ rows ++ contextRows (ends ranges) previousIndices sources starts (left, right) = (start left, start right) ends (left, right) = (end left, end right) sumRows (rows, previousIndices) child = (allRows, ends childRanges) @@ -227,28 +227,28 @@ rowFromMaybeRows a b = Row (maybe EmptyLine (Line False . (:[])) a) (maybe Empty maybeLast :: Foldable f => f a -> Maybe a maybeLast = foldl (flip $ const . Just) Nothing -adjoinBy :: (a -> Maybe a) -> [Row a] -> Row a -> [Row a] -adjoinBy _ [] row = [row] +adjoinRowsBy :: (a -> Maybe a) -> [Row a] -> Row a -> [Row a] +adjoinRowsBy _ [] row = [row] -adjoinBy f rows (Row left' right') | Just _ <- openLineBy f $ leftLines rows, Just _ <- openLineBy f $ rightLines rows = zipWith Row lefts rights +adjoinRowsBy f rows (Row left' right') | Just _ <- openLineBy f $ leftLines rows, Just _ <- openLineBy f $ rightLines rows = zipWith Row lefts rights where lefts = adjoinLinesBy f (leftLines rows) left' rights = adjoinLinesBy f (rightLines rows) right' -adjoinBy f rows (Row left' right') | Just _ <- openLineBy f $ leftLines rows = case right' of +adjoinRowsBy f rows (Row left' right') | Just _ <- openLineBy f $ leftLines rows = case right' of EmptyLine -> rest _ -> Row EmptyLine right' : rest where rest = zipWith Row lefts rights lefts = adjoinLinesBy f (leftLines rows) left' rights = rightLines rows -adjoinBy f rows (Row left' right') | Just _ <- openLineBy f $ rightLines rows = case left' of +adjoinRowsBy f rows (Row left' right') | Just _ <- openLineBy f $ rightLines rows = case left' of EmptyLine -> rest _ -> Row left' EmptyLine : rest where rest = zipWith Row lefts rights lefts = leftLines rows rights = adjoinLinesBy f (rightLines rows) right' -adjoinBy _ rows row = row : rows +adjoinRowsBy _ rows row = row : rows leftLines :: [Row a] -> [Line a] leftLines rows = left <$> rows diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index 315ad56bb..56a5bd7f6 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -112,26 +112,26 @@ spec = do ([ Row (Line False [ span "t\776" ]) (Line False [ span "\7831"]) ], (Range 0 2, Range 0 1)) - describe "adjoinBy" $ do + describe "adjoinRowsBy" $ do prop "is identity on top of no rows" $ - \ a -> adjoinBy openElement [] a == [ a ] + \ a -> adjoinRowsBy openElement [] a == [ a ] prop "appends onto open rows" $ forAll ((arbitrary `suchThat` isOpen) >>= \ a -> ((,) a) <$> (arbitrary `suchThat` isOpen)) $ \ (a@(Row (Line ac1 as1) (Line bc1 bs1)), b@(Row (Line ac2 as2) (Line bc2 bs2))) -> - adjoinBy openElement [ a ] b `shouldBe` [ Row (Line (ac1 || ac2) $ as1 ++ as2) (Line (bc1 || bc2) $ bs1 ++ bs2) ] + adjoinRowsBy openElement [ a ] b `shouldBe` [ Row (Line (ac1 || ac2) $ as1 ++ as2) (Line (bc1 || bc2) $ bs1 ++ bs2) ] prop "does not append onto closed rows" $ forAll ((arbitrary `suchThat` isClosed) >>= \ a -> ((,) a) <$> (arbitrary `suchThat` isClosed)) $ - \ (a, b) -> adjoinBy openElement [ a ] b `shouldBe` [ b, a ] + \ (a, b) -> adjoinRowsBy openElement [ a ] b `shouldBe` [ b, a ] prop "does not promote elements through empty lines onto closed lines" $ forAll ((arbitrary `suchThat` isClosed) >>= \ a -> ((,) a) <$> (arbitrary `suchThat` isClosed)) $ - \ (a, b) -> adjoinBy openElement [ Row EmptyLine EmptyLine, a ] b `shouldBe` [ b, Row EmptyLine EmptyLine, a ] + \ (a, b) -> adjoinRowsBy openElement [ Row EmptyLine EmptyLine, a ] b `shouldBe` [ b, Row EmptyLine EmptyLine, a ] prop "promotes elements through empty lines onto open lines" $ forAll ((arbitrary `suchThat` isOpen) >>= \ a -> ((,) a) <$> (arbitrary `suchThat` isOpen)) $ - \ (a, b) -> adjoinBy openElement [ Row EmptyLine EmptyLine, a ] b `shouldBe` Row EmptyLine EmptyLine : adjoinBy openElement [ a ] b + \ (a, b) -> adjoinRowsBy openElement [ Row EmptyLine EmptyLine, a ] b `shouldBe` Row EmptyLine EmptyLine : adjoinRowsBy openElement [ a ] b describe "termToLines" $ do it "splits multi-line terms into multiple lines" $ From 3c85d4d0aff404987223e4c610c761c55277b62e Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 13:00:46 -0500 Subject: [PATCH 041/259] =?UTF-8?q?Use=20Data.Maybe=E2=80=99s=20isJust=20&?= =?UTF-8?q?=20isNothing=20to=20test=20for=20open=20elements.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/SplitSpec.hs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index 56a5bd7f6..fa02a3be9 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -9,6 +9,7 @@ import Test.Hspec.QuickCheck import Test.QuickCheck hiding (Fixed) import Control.Comonad.Cofree import Control.Monad.Free hiding (unfold) +import qualified Data.Maybe as Maybe import Patch import Syntax @@ -167,6 +168,6 @@ spec = do offsetInfo by (Info (Range start end) categories) = Info (Range (start + by) (end + by)) categories offsetAnnotated by1 by2 (Annotated (left, right) syntax) = Annotated (offsetInfo by1 left, offsetInfo by2 right) syntax span = Span (Just "category-leaf") - isOpen (Row a b) = (maybe False (const True) $ openLineBy openElement [ a ]) && (maybe False (const True) $ openLineBy openElement [ b ]) - isClosed (Row a@(Line _ _) b@(Line _ _)) = (maybe True (const False) $ openLineBy openElement [ a ]) && (maybe True (const False) $ openLineBy openElement [ b ]) + isOpen (Row a b) = (Maybe.isJust $ openLineBy openElement [ a ]) && (Maybe.isJust $ openLineBy openElement [ b ]) + isClosed (Row a@(Line _ _) b@(Line _ _)) = (Maybe.isNothing $ openLineBy openElement [ a ]) && (Maybe.isNothing $ openLineBy openElement [ b ]) isClosed (Row _ _) = False From c0a566be4af465c038e35e90d145c1d4d1009a8b Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 13:01:38 -0500 Subject: [PATCH 042/259] Eta-reduce the definition of `unchanged`. --- test/SplitSpec.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index fa02a3be9..b59d4048b 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -163,7 +163,7 @@ spec = do leftRow xs = Row (Line False xs) EmptyLine rowText a b = Row (Line False [ Text a ]) (Line False [ Text b ]) info source category = Info (totalRange source) (Set.fromList [ category ]) - unchanged source category = formatted source source category + unchanged source = formatted source source formatted source1 source2 category = Annotated (info source1 category, info source2 category) offsetInfo by (Info (Range start end) categories) = Info (Range (start + by) (end + by)) categories offsetAnnotated by1 by2 (Annotated (left, right) syntax) = Annotated (offsetInfo by1 left, offsetInfo by2 right) syntax From 671904cf61441bde52ce3a62ce8475dd378e3f60 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 13:01:46 -0500 Subject: [PATCH 043/259] Remove redundant parentheses. --- test/SplitSpec.hs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index b59d4048b..9df882307 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -95,7 +95,7 @@ spec = do it "should split multi-line deletions across multiple rows" $ let (sourceA, sourceB) = ("/*\n*/\na", "a") in annotatedToRows (formatted sourceA sourceB "branch" (Indexed [ - Pure . Delete $ (Info (Range 0 5) (Set.fromList ["leaf"]) :< (Leaf "")), + Pure . Delete $ (Info (Range 0 5) (Set.fromList ["leaf"]) :< Leaf ""), Free . offsetAnnotated 6 0 $ unchanged "a" "leaf" (Leaf "") ])) sourceA sourceB `shouldBe` ([ @@ -107,7 +107,7 @@ spec = do describe "unicode" $ it "equivalent precomposed and decomposed characters are not equal" $ let (sourceA, sourceB) = ("t\776", "\7831") - syntax = Leaf . Pure $ Replace (info sourceA "leaf" :< (Leaf "")) (info sourceB "leaf" :< (Leaf "")) + syntax = Leaf . Pure $ Replace (info sourceA "leaf" :< Leaf "") (info sourceB "leaf" :< Leaf "") in annotatedToRows (formatted sourceA sourceB "leaf" syntax) sourceA sourceB `shouldBe` ([ Row (Line False [ span "t\776" ]) (Line False [ span "\7831"]) ], (Range 0 2, Range 0 1)) @@ -118,25 +118,25 @@ spec = do \ a -> adjoinRowsBy openElement [] a == [ a ] prop "appends onto open rows" $ - forAll ((arbitrary `suchThat` isOpen) >>= \ a -> ((,) a) <$> (arbitrary `suchThat` isOpen)) $ + forAll ((arbitrary `suchThat` isOpen) >>= \ a -> (,) a <$> (arbitrary `suchThat` isOpen)) $ \ (a@(Row (Line ac1 as1) (Line bc1 bs1)), b@(Row (Line ac2 as2) (Line bc2 bs2))) -> adjoinRowsBy openElement [ a ] b `shouldBe` [ Row (Line (ac1 || ac2) $ as1 ++ as2) (Line (bc1 || bc2) $ bs1 ++ bs2) ] prop "does not append onto closed rows" $ - forAll ((arbitrary `suchThat` isClosed) >>= \ a -> ((,) a) <$> (arbitrary `suchThat` isClosed)) $ + forAll ((arbitrary `suchThat` isClosed) >>= \ a -> (,) a <$> (arbitrary `suchThat` isClosed)) $ \ (a, b) -> adjoinRowsBy openElement [ a ] b `shouldBe` [ b, a ] prop "does not promote elements through empty lines onto closed lines" $ - forAll ((arbitrary `suchThat` isClosed) >>= \ a -> ((,) a) <$> (arbitrary `suchThat` isClosed)) $ + forAll ((arbitrary `suchThat` isClosed) >>= \ a -> (,) a <$> (arbitrary `suchThat` isClosed)) $ \ (a, b) -> adjoinRowsBy openElement [ Row EmptyLine EmptyLine, a ] b `shouldBe` [ b, Row EmptyLine EmptyLine, a ] prop "promotes elements through empty lines onto open lines" $ - forAll ((arbitrary `suchThat` isOpen) >>= \ a -> ((,) a) <$> (arbitrary `suchThat` isOpen)) $ + forAll ((arbitrary `suchThat` isOpen) >>= \ a -> (,) a <$> (arbitrary `suchThat` isOpen)) $ \ (a, b) -> adjoinRowsBy openElement [ Row EmptyLine EmptyLine, a ] b `shouldBe` Row EmptyLine EmptyLine : adjoinRowsBy openElement [ a ] b describe "termToLines" $ do it "splits multi-line terms into multiple lines" $ - termToLines (Info (Range 0 5) (Set.singleton "leaf") :< (Leaf "")) "/*\n*/" + termToLines (Info (Range 0 5) (Set.singleton "leaf") :< Leaf "") "/*\n*/" `shouldBe` ([ Line True [ span "/*", Break ], From cbc1240946583547bfad8a5041ed257a78f7df39 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 13:03:08 -0500 Subject: [PATCH 044/259] Avoid needless $s. --- test/SplitSpec.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index 9df882307..f462dec0a 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -168,6 +168,6 @@ spec = do offsetInfo by (Info (Range start end) categories) = Info (Range (start + by) (end + by)) categories offsetAnnotated by1 by2 (Annotated (left, right) syntax) = Annotated (offsetInfo by1 left, offsetInfo by2 right) syntax span = Span (Just "category-leaf") - isOpen (Row a b) = (Maybe.isJust $ openLineBy openElement [ a ]) && (Maybe.isJust $ openLineBy openElement [ b ]) - isClosed (Row a@(Line _ _) b@(Line _ _)) = (Maybe.isNothing $ openLineBy openElement [ a ]) && (Maybe.isNothing $ openLineBy openElement [ b ]) + isOpen (Row a b) = Maybe.isJust (openLineBy openElement [ a ]) && Maybe.isJust (openLineBy openElement [ b ]) + isClosed (Row a@(Line _ _) b@(Line _ _)) = Maybe.isNothing (openLineBy openElement [ a ]) && Maybe.isNothing (openLineBy openElement [ b ]) isClosed (Row _ _) = False From b351f1b29dbdb8fbe083433bae5df13908753870 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 13:10:11 -0500 Subject: [PATCH 045/259] Generalize rowFromMaybeRows. --- src/Split.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Split.hs b/src/Split.hs index 9c77e4d41..b740b2135 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -221,7 +221,7 @@ textElements :: Range -> String -> [HTML] textElements range source = elementAndBreak Text =<< actualLines s where s = substring range source -rowFromMaybeRows :: Maybe HTML -> Maybe HTML -> Row HTML +rowFromMaybeRows :: Maybe a -> Maybe a -> Row a rowFromMaybeRows a b = Row (maybe EmptyLine (Line False . (:[])) a) (maybe EmptyLine (Line False . (:[])) b) maybeLast :: Foldable f => f a -> Maybe a From ea161cdd4a48c5c393d47a41a93f921fc841cdba Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 13:11:01 -0500 Subject: [PATCH 046/259] Generalize the other rowFromMaybeRows. --- src/Split.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Split.hs b/src/Split.hs index b740b2135..71e022c98 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -150,7 +150,7 @@ diffToRows (Pure (Replace a b)) _ before after = (replacedRows, (leftRange, righ where replacedRows = zipWithMaybe rowFromMaybeRows (replace <$> leftElements) (replace <$> rightElements) replace = (:[]) . Div (Just "replace") . unLine - rowFromMaybeRows :: Maybe [HTML] -> Maybe [HTML] -> Row HTML + rowFromMaybeRows :: Maybe [a] -> Maybe [a] -> Row a rowFromMaybeRows a b = Row (maybe EmptyLine (Line True) a) (maybe EmptyLine (Line True) b) (leftElements, leftRange) = termToLines a before (rightElements, rightRange) = termToLines b after From 2c703b30e40f84f73845e7840f2eb53f908f3dd7 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 13:12:35 -0500 Subject: [PATCH 047/259] Remove the inner rowFromMaybeRows. --- src/Split.hs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 71e022c98..0f3a9c4b6 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -149,9 +149,7 @@ diffToRows (Pure (Delete term)) (_, previousIndex) before _ = (rowWithDeletedLin diffToRows (Pure (Replace a b)) _ before after = (replacedRows, (leftRange, rightRange)) where replacedRows = zipWithMaybe rowFromMaybeRows (replace <$> leftElements) (replace <$> rightElements) - replace = (:[]) . Div (Just "replace") . unLine - rowFromMaybeRows :: Maybe [a] -> Maybe [a] -> Row a - rowFromMaybeRows a b = Row (maybe EmptyLine (Line True) a) (maybe EmptyLine (Line True) b) + replace = Div (Just "replace") . unLine (leftElements, leftRange) = termToLines a before (rightElements, rightRange) = termToLines b after From 568df9937b7678bde5744fd795cee687e14b624b Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 13:15:37 -0500 Subject: [PATCH 048/259] Define `classify` in terms of maybeLast. --- src/Split.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Split.hs b/src/Split.hs index 0f3a9c4b6..1c0419d06 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -289,7 +289,7 @@ zipWithMaybe f la lb = take len $ zipWith f la' lb' lb' = (Just <$> lb) ++ repeat Nothing classify :: Set.Set Category -> Maybe ClassName -classify = foldr (const . Just . ("category-" ++)) Nothing +classify categories = ("category-" ++) <$> maybeLast categories actualLines :: String -> [String] actualLines "" = [""] From 693028f70c40d9bf4d4c7cc10c736af93b1007be Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 13:18:41 -0500 Subject: [PATCH 049/259] Define field accessors for the left & right lines in a Row. --- src/Split.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Split.hs b/src/Split.hs index 1c0419d06..6ba67cb22 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -83,7 +83,7 @@ split diff before after = return . renderHtml numberRows rows@((leftCount, _, rightCount, _):_) (Row left right) = (leftCount + 1, left, rightCount + 1, right):rows -data Row a = Row (Line a) (Line a) +data Row a = Row { unLeft :: Line a, unRight :: Line a } deriving Eq instance Show a => Show (Row a) where From 71ca4fc147c4e54b4490f76cfa3aeae23ebafc3c Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 13:19:45 -0500 Subject: [PATCH 050/259] Define leftLines in terms of unLeft. --- src/Split.hs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 6ba67cb22..0ba59d5ca 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -249,9 +249,7 @@ adjoinRowsBy f rows (Row left' right') | Just _ <- openLineBy f $ rightLines row adjoinRowsBy _ rows row = row : rows leftLines :: [Row a] -> [Line a] -leftLines rows = left <$> rows - where - left (Row left _) = left +leftLines rows = unLeft <$> rows rightLines :: [Row a] -> [Line a] rightLines rows = right <$> rows From 6e76f3e6187a81e07737c50cf764bc34454433c2 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 13:19:51 -0500 Subject: [PATCH 051/259] Define rightLines in terms of unRight. --- src/Split.hs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 0ba59d5ca..651527c3b 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -252,9 +252,7 @@ leftLines :: [Row a] -> [Line a] leftLines rows = unLeft <$> rows rightLines :: [Row a] -> [Line a] -rightLines rows = right <$> rows - where - right (Row _ right) = right +rightLines rows = unRight <$> rows openElement :: HTML -> Maybe HTML openElement Break = Nothing From 7b0ea6678e5f919e151be701fd917663e833ca5a Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 13:20:47 -0500 Subject: [PATCH 052/259] fmap unLeft over rows directly. --- src/Split.hs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 651527c3b..daaa5775b 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -228,22 +228,22 @@ maybeLast = foldl (flip $ const . Just) Nothing adjoinRowsBy :: (a -> Maybe a) -> [Row a] -> Row a -> [Row a] adjoinRowsBy _ [] row = [row] -adjoinRowsBy f rows (Row left' right') | Just _ <- openLineBy f $ leftLines rows, Just _ <- openLineBy f $ rightLines rows = zipWith Row lefts rights - where lefts = adjoinLinesBy f (leftLines rows) left' +adjoinRowsBy f rows (Row left' right') | Just _ <- openLineBy f $ unLeft <$> rows, Just _ <- openLineBy f $ rightLines rows = zipWith Row lefts rights + where lefts = adjoinLinesBy f (unLeft <$> rows) left' rights = adjoinLinesBy f (rightLines rows) right' -adjoinRowsBy f rows (Row left' right') | Just _ <- openLineBy f $ leftLines rows = case right' of +adjoinRowsBy f rows (Row left' right') | Just _ <- openLineBy f $ unLeft <$> rows = case right' of EmptyLine -> rest _ -> Row EmptyLine right' : rest where rest = zipWith Row lefts rights - lefts = adjoinLinesBy f (leftLines rows) left' + lefts = adjoinLinesBy f (unLeft <$> rows) left' rights = rightLines rows adjoinRowsBy f rows (Row left' right') | Just _ <- openLineBy f $ rightLines rows = case left' of EmptyLine -> rest _ -> Row left' EmptyLine : rest where rest = zipWith Row lefts rights - lefts = leftLines rows + lefts = unLeft <$> rows rights = adjoinLinesBy f (rightLines rows) right' adjoinRowsBy _ rows row = row : rows From 2b5712cd58d8bc0b4ac5b0036aab260812b26331 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 13:21:09 -0500 Subject: [PATCH 053/259] fmap unRight over rows directly. --- src/Split.hs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index daaa5775b..a5d352070 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -228,23 +228,23 @@ maybeLast = foldl (flip $ const . Just) Nothing adjoinRowsBy :: (a -> Maybe a) -> [Row a] -> Row a -> [Row a] adjoinRowsBy _ [] row = [row] -adjoinRowsBy f rows (Row left' right') | Just _ <- openLineBy f $ unLeft <$> rows, Just _ <- openLineBy f $ rightLines rows = zipWith Row lefts rights +adjoinRowsBy f rows (Row left' right') | Just _ <- openLineBy f $ unLeft <$> rows, Just _ <- openLineBy f $ unRight <$> rows = zipWith Row lefts rights where lefts = adjoinLinesBy f (unLeft <$> rows) left' - rights = adjoinLinesBy f (rightLines rows) right' + rights = adjoinLinesBy f (unRight <$> rows) right' adjoinRowsBy f rows (Row left' right') | Just _ <- openLineBy f $ unLeft <$> rows = case right' of EmptyLine -> rest _ -> Row EmptyLine right' : rest where rest = zipWith Row lefts rights lefts = adjoinLinesBy f (unLeft <$> rows) left' - rights = rightLines rows + rights = unRight <$> rows -adjoinRowsBy f rows (Row left' right') | Just _ <- openLineBy f $ rightLines rows = case left' of +adjoinRowsBy f rows (Row left' right') | Just _ <- openLineBy f $ unRight <$> rows = case left' of EmptyLine -> rest _ -> Row left' EmptyLine : rest where rest = zipWith Row lefts rights lefts = unLeft <$> rows - rights = adjoinLinesBy f (rightLines rows) right' + rights = adjoinLinesBy f (unRight <$> rows) right' adjoinRowsBy _ rows row = row : rows From d38f94df8ccc79b9e9a7f9c56f97d83f1ae1b42c Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 13:21:23 -0500 Subject: [PATCH 054/259] Remove leftLines. --- src/Split.hs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index a5d352070..0c1ced863 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -248,9 +248,6 @@ adjoinRowsBy f rows (Row left' right') | Just _ <- openLineBy f $ unRight <$> ro adjoinRowsBy _ rows row = row : rows -leftLines :: [Row a] -> [Line a] -leftLines rows = unLeft <$> rows - rightLines :: [Row a] -> [Line a] rightLines rows = unRight <$> rows From fc819fb48d5cbbc912dbfe6fa7b784990cc2d5f1 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 13:21:31 -0500 Subject: [PATCH 055/259] Remove rightLines. --- src/Split.hs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 0c1ced863..03e74efd0 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -248,9 +248,6 @@ adjoinRowsBy f rows (Row left' right') | Just _ <- openLineBy f $ unRight <$> ro adjoinRowsBy _ rows row = row : rows -rightLines :: [Row a] -> [Line a] -rightLines rows = unRight <$> rows - openElement :: HTML -> Maybe HTML openElement Break = Nothing openElement (Ul _ elements) = openElement =<< maybeLast elements From b857464c44249fc1b90f82c154dd0adb364788a5 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 13:25:32 -0500 Subject: [PATCH 056/259] Reformat a comment. --- src/Split.hs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 03e74efd0..348a4f687 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -153,8 +153,7 @@ diffToRows (Pure (Replace a b)) _ before after = (replacedRows, (leftRange, righ (leftElements, leftRange) = termToLines a before (rightElements, rightRange) = termToLines b after --- | Takes a term and a `source` and returns a list of HTML lines --- | and their range within `source`. +-- | Takes a term and a `source` and returns a list of lines and their range within `source`. termToLines :: Term a Info -> String -> ([Line HTML], Range) termToLines (Info range categories :< syntax) source = (rows syntax, range) where From cefbdd400e77d0b7646a6a722057a96e3537059a Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 13:26:51 -0500 Subject: [PATCH 057/259] Simplify mappend over Lines. --- src/Split.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 348a4f687..029cff002 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -126,8 +126,8 @@ instance Show a => Show (Line a) where instance Monoid (Line a) where mempty = EmptyLine mappend EmptyLine EmptyLine = EmptyLine - mappend EmptyLine (Line c ys) = Line c ys - mappend (Line c xs) EmptyLine = Line c xs + mappend EmptyLine line = line + mappend line EmptyLine = line mappend (Line c1 xs) (Line c2 ys) = Line (c1 || c2) (xs <> ys) instance Monoid (Row a) where From ce5911b9b6ee1f98fb99c926b4534317ea0c6b99 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 13:26:59 -0500 Subject: [PATCH 058/259] Remove a redundant mappend case. --- src/Split.hs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Split.hs b/src/Split.hs index 029cff002..190aee1d5 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -125,7 +125,6 @@ instance Show a => Show (Line a) where instance Monoid (Line a) where mempty = EmptyLine - mappend EmptyLine EmptyLine = EmptyLine mappend EmptyLine line = line mappend line EmptyLine = line mappend (Line c1 xs) (Line c2 ys) = Line (c1 || c2) (xs <> ys) From e1b15b7bdc0ed785844393cb16935c72221116f8 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 13:29:04 -0500 Subject: [PATCH 059/259] Handle empty rows without reference to the Monoid instance for Row. --- src/Split.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 190aee1d5..8e1cd0747 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -139,12 +139,12 @@ diffToRows (Pure (Insert term)) (previousIndex, _) _ after = (rowWithInsertedLin where (afterLines, range) = termToLines term after rowWithInsertedLine (Line _ elements) = Row EmptyLine $ Line True [ Div (Just "insert") elements ] - rowWithInsertedLine EmptyLine = mempty + rowWithInsertedLine line = Row line line diffToRows (Pure (Delete term)) (_, previousIndex) before _ = (rowWithDeletedLine <$> lines, (range, Range previousIndex previousIndex)) where (lines, range) = termToLines term before rowWithDeletedLine (Line _ elements) = Row (Line True [ Div (Just "delete") elements ]) EmptyLine - rowWithDeletedLine EmptyLine = mempty + rowWithDeletedLine line = Row line line diffToRows (Pure (Replace a b)) _ before after = (replacedRows, (leftRange, rightRange)) where replacedRows = zipWithMaybe rowFromMaybeRows (replace <$> leftElements) (replace <$> rightElements) From 3ef66954b6462ddd73aa7a36b034128b43c609a1 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 13:29:21 -0500 Subject: [PATCH 060/259] Remove the Monoid instance for `Row a`. --- src/Split.hs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 8e1cd0747..84fe42610 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -129,10 +129,6 @@ instance Monoid (Line a) where mappend line EmptyLine = line mappend (Line c1 xs) (Line c2 ys) = Line (c1 || c2) (xs <> ys) -instance Monoid (Row a) where - mempty = Row EmptyLine EmptyLine - mappend (Row x1 y1) (Row x2 y2) = Row (x1 <> x2) (y1 <> y2) - diffToRows :: Diff a Info -> (Int, Int) -> String -> String -> ([Row HTML], (Range, Range)) diffToRows (Free annotated) _ before after = annotatedToRows annotated before after diffToRows (Pure (Insert term)) (previousIndex, _) _ after = (rowWithInsertedLine <$> afterLines, (Range previousIndex previousIndex, range)) From 31afc5de115acb843225e09c8215b512e9beda88 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 13:36:08 -0500 Subject: [PATCH 061/259] Replace some $s with some .s. --- src/Split.hs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 84fe42610..b37d6159c 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -152,7 +152,7 @@ diffToRows (Pure (Replace a b)) _ before after = (replacedRows, (leftRange, righ termToLines :: Term a Info -> String -> ([Line HTML], Range) termToLines (Info range categories :< syntax) source = (rows syntax, range) where - rows (Leaf _) = reverse $ foldl (adjoinLinesBy openElement) [] $ Line True . (:[]) <$> elements + rows (Leaf _) = reverse . foldl (adjoinLinesBy openElement) [] $ Line True . (:[]) <$> elements rows (Indexed i) = rewrapLineContentsIn (Ul $ classify categories) <$> childLines i rows (Fixed f) = rewrapLineContentsIn (Ul $ classify categories) <$> childLines f rows (Keyed k) = rewrapLineContentsIn (Dl $ classify categories) <$> childLines k @@ -165,8 +165,7 @@ termToLines (Info range categories :< syntax) source = (rows syntax, range) sumLines (lines, previous) child = (allLines, end childRange) where separatorLines = contextLines (Range previous $ start childRange) source - unadjoinedLines = lines ++ separatorLines ++ childLines - allLines = reverse $ foldl (adjoinLinesBy openElement) [] unadjoinedLines + allLines = reverse . foldl (adjoinLinesBy openElement) [] $ lines ++ separatorLines ++ childLines (childLines, childRange) = termToLines child source elements = elementAndBreak (Span $ classify categories) =<< actualLines (substring range source) From d500810f90ade95575aee7827f4cfc9ccfdfd9d5 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 14:20:13 -0500 Subject: [PATCH 062/259] Define a splitTermsByLines function over leaves. --- src/Split.hs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Split.hs b/src/Split.hs index b37d6159c..1fc568950 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -148,6 +148,13 @@ diffToRows (Pure (Replace a b)) _ before after = (replacedRows, (leftRange, righ (leftElements, leftRange) = termToLines a before (rightElements, rightRange) = termToLines b after +-- | Takes a term and a `source` and returns a list of lines and their range within `source`. +splitTermByLines :: Term a Info -> String -> ([Line (Term a Info)], Range) +splitTermByLines (Info range categories :< syntax) source = flip (,) range $ case syntax of + Leaf a -> reverse . foldl (adjoinLinesBy $ openTerm source) [] $ + Line True . (:[]) . (:< Leaf a) . (`Info` categories) <$> scanl toRange (Range (start range) (start range)) (actualLines $ substring range source) + where toRange previous string = Range (end previous) $ end previous + length string + -- | Takes a term and a `source` and returns a list of lines and their range within `source`. termToLines :: Term a Info -> String -> ([Line HTML], Range) termToLines (Info range categories :< syntax) source = (rows syntax, range) From 6088777b69d471b2854fb80746bfe160b516ee4c Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 14:24:14 -0500 Subject: [PATCH 063/259] Add an actualLineRanges function. --- src/Split.hs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Split.hs b/src/Split.hs index 1fc568950..653dc99ff 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -287,3 +287,8 @@ actualLines lines = case break (== '\n') lines of (l, lines') -> case lines' of [] -> [ l ] _:lines' -> (l ++ "\n") : actualLines lines' + +-- | Compute the line ranges within a given range of a string. +actualLineRanges :: Range -> String -> [Range] +actualLineRanges range = scanl toRange (Range (start range) (start range)) . actualLines . substring range + where toRange previous string = Range (end previous) $ end previous + length string From aa0dd5d2caaab6e78c5b3daefc3bac3b6575c7a0 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 14:24:32 -0500 Subject: [PATCH 064/259] Define splitTermByLines over actualLineRanges. --- src/Split.hs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 653dc99ff..9f258085b 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -152,8 +152,7 @@ diffToRows (Pure (Replace a b)) _ before after = (replacedRows, (leftRange, righ splitTermByLines :: Term a Info -> String -> ([Line (Term a Info)], Range) splitTermByLines (Info range categories :< syntax) source = flip (,) range $ case syntax of Leaf a -> reverse . foldl (adjoinLinesBy $ openTerm source) [] $ - Line True . (:[]) . (:< Leaf a) . (`Info` categories) <$> scanl toRange (Range (start range) (start range)) (actualLines $ substring range source) - where toRange previous string = Range (end previous) $ end previous + length string + Line True . (:[]) . (:< Leaf a) . (`Info` categories) <$> actualLineRanges range source -- | Takes a term and a `source` and returns a list of lines and their range within `source`. termToLines :: Term a Info -> String -> ([Line HTML], Range) From fb78fa7535389ccacbead019b0993b9132f344ec Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 14:30:20 -0500 Subject: [PATCH 065/259] Extract an `adjoin` binding in `termToLines`. --- src/Split.hs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 9f258085b..cd1669448 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -158,20 +158,21 @@ splitTermByLines (Info range categories :< syntax) source = flip (,) range $ cas termToLines :: Term a Info -> String -> ([Line HTML], Range) termToLines (Info range categories :< syntax) source = (rows syntax, range) where - rows (Leaf _) = reverse . foldl (adjoinLinesBy openElement) [] $ Line True . (:[]) <$> elements + rows (Leaf _) = adjoin $ Line True . (:[]) <$> elements rows (Indexed i) = rewrapLineContentsIn (Ul $ classify categories) <$> childLines i rows (Fixed f) = rewrapLineContentsIn (Ul $ classify categories) <$> childLines f rows (Keyed k) = rewrapLineContentsIn (Dl $ classify categories) <$> childLines k + adjoin = reverse . foldl (adjoinLinesBy openElement) [] rewrapLineContentsIn f (Line _ elements) = Line True [ f elements ] rewrapLineContentsIn _ EmptyLine = EmptyLine contextLines r s = Line True . (:[]) <$> textElements r s childLines i = let (lines, previous) = foldl sumLines ([], start range) i in - reverse . foldl (adjoinLinesBy openElement) [] $ lines ++ contextLines (Range previous (end range)) source + adjoin $ lines ++ contextLines (Range previous (end range)) source sumLines (lines, previous) child = (allLines, end childRange) where separatorLines = contextLines (Range previous $ start childRange) source - allLines = reverse . foldl (adjoinLinesBy openElement) [] $ lines ++ separatorLines ++ childLines + allLines = adjoin $ lines ++ separatorLines ++ childLines (childLines, childRange) = termToLines child source elements = elementAndBreak (Span $ classify categories) =<< actualLines (substring range source) From 50d82831cd370864da237635fa75e0095bae9268 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 14:30:55 -0500 Subject: [PATCH 066/259] Inline the definition of separatorLines. --- src/Split.hs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index cd1669448..9fb5fea34 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -171,8 +171,7 @@ termToLines (Info range categories :< syntax) source = (rows syntax, range) adjoin $ lines ++ contextLines (Range previous (end range)) source sumLines (lines, previous) child = (allLines, end childRange) where - separatorLines = contextLines (Range previous $ start childRange) source - allLines = adjoin $ lines ++ separatorLines ++ childLines + allLines = adjoin $ lines ++ contextLines (Range previous $ start childRange) source ++ childLines (childLines, childRange) = termToLines child source elements = elementAndBreak (Span $ classify categories) =<< actualLines (substring range source) From dc2c130936664436a0b58936e3497401e07516e5 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 14:31:56 -0500 Subject: [PATCH 067/259] Tidy up the sumLines definition. --- src/Split.hs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 9fb5fea34..f18dd7b8c 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -169,10 +169,8 @@ termToLines (Info range categories :< syntax) source = (rows syntax, range) contextLines r s = Line True . (:[]) <$> textElements r s childLines i = let (lines, previous) = foldl sumLines ([], start range) i in adjoin $ lines ++ contextLines (Range previous (end range)) source - sumLines (lines, previous) child = (allLines, end childRange) - where - allLines = adjoin $ lines ++ contextLines (Range previous $ start childRange) source ++ childLines - (childLines, childRange) = termToLines child source + sumLines (lines, previous) child = let (childLines, childRange) = termToLines child source in + (adjoin $ lines ++ contextLines (Range previous $ start childRange) source ++ childLines, end childRange) elements = elementAndBreak (Span $ classify categories) =<< actualLines (substring range source) -- | Given an Annotated and before/after strings, returns a list of `Row`s representing the newline-separated diff. From ab79e9d99f9a767535f00b031ab09de5f4c9a51e Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 14:32:59 -0500 Subject: [PATCH 068/259] Extract the adjoining fold into an `adjoin` binding. --- src/Split.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index f18dd7b8c..1a5ef9daa 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -151,8 +151,8 @@ diffToRows (Pure (Replace a b)) _ before after = (replacedRows, (leftRange, righ -- | Takes a term and a `source` and returns a list of lines and their range within `source`. splitTermByLines :: Term a Info -> String -> ([Line (Term a Info)], Range) splitTermByLines (Info range categories :< syntax) source = flip (,) range $ case syntax of - Leaf a -> reverse . foldl (adjoinLinesBy $ openTerm source) [] $ - Line True . (:[]) . (:< Leaf a) . (`Info` categories) <$> actualLineRanges range source + Leaf a -> adjoin $ Line True . (:[]) . (:< Leaf a) . (`Info` categories) <$> actualLineRanges range source + where adjoin = reverse . foldl (adjoinLinesBy $ openTerm source) [] -- | Takes a term and a `source` and returns a list of lines and their range within `source`. termToLines :: Term a Info -> String -> ([Line HTML], Range) From 8e652e80ee2722053d45a296193e10a309d75e41 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 14:56:55 -0500 Subject: [PATCH 069/259] Add a `contextLines` function. --- src/Split.hs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Split.hs b/src/Split.hs index 1a5ef9daa..d56414000 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -153,6 +153,7 @@ splitTermByLines :: Term a Info -> String -> ([Line (Term a Info)], Range) splitTermByLines (Info range categories :< syntax) source = flip (,) range $ case syntax of Leaf a -> adjoin $ Line True . (:[]) . (:< Leaf a) . (`Info` categories) <$> actualLineRanges range source where adjoin = reverse . foldl (adjoinLinesBy $ openTerm source) [] + contextLines constructor range source = Line True . (:[]) . (:< constructor []) . (`Info` categories) <$> actualLineRanges range source -- | Takes a term and a `source` and returns a list of lines and their range within `source`. termToLines :: Term a Info -> String -> ([Line HTML], Range) From 8fa370cb62b224e13b1bef4cec24a2992001ca7d Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 14:57:22 -0500 Subject: [PATCH 070/259] Add a childLines function. This serves the same purpose as `sumLines` does in `termToLines`, but I find the name preferable for this use case. --- src/Split.hs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Split.hs b/src/Split.hs index d56414000..4ff3627d0 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -154,6 +154,8 @@ splitTermByLines (Info range categories :< syntax) source = flip (,) range $ cas Leaf a -> adjoin $ Line True . (:[]) . (:< Leaf a) . (`Info` categories) <$> actualLineRanges range source where adjoin = reverse . foldl (adjoinLinesBy $ openTerm source) [] contextLines constructor range source = Line True . (:[]) . (:< constructor []) . (`Info` categories) <$> actualLineRanges range source + childLines constructor (lines, previous) child = let (childLines, childRange) = splitTermByLines child source in + (adjoin $ lines ++ contextLines constructor (Range previous $ start childRange) source ++ childLines, end childRange) -- | Takes a term and a `source` and returns a list of lines and their range within `source`. termToLines :: Term a Info -> String -> ([Line HTML], Range) From 426d83a60a9d6859859d982132e24c49b7379541 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 14:57:33 -0500 Subject: [PATCH 071/259] Define `splitTermByLines` over `Indexed` terms. --- src/Split.hs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Split.hs b/src/Split.hs index 4ff3627d0..452cde677 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -152,6 +152,8 @@ diffToRows (Pure (Replace a b)) _ before after = (replacedRows, (leftRange, righ splitTermByLines :: Term a Info -> String -> ([Line (Term a Info)], Range) splitTermByLines (Info range categories :< syntax) source = flip (,) range $ case syntax of Leaf a -> adjoin $ Line True . (:[]) . (:< Leaf a) . (`Info` categories) <$> actualLineRanges range source + Indexed children -> let (lines, previous) = foldl (childLines Indexed) ([], start range) children in + adjoin $ lines ++ contextLines Indexed (Range previous $ end range) source where adjoin = reverse . foldl (adjoinLinesBy $ openTerm source) [] contextLines constructor range source = Line True . (:[]) . (:< constructor []) . (`Info` categories) <$> actualLineRanges range source childLines constructor (lines, previous) child = let (childLines, childRange) = splitTermByLines child source in From cf6f96dcd2ae91727cc43b53086027f5e4a8fb50 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 14:59:43 -0500 Subject: [PATCH 072/259] Extract a function to adjoin the lines in child terms. --- src/Split.hs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Split.hs b/src/Split.hs index 452cde677..ac8a873ec 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -155,6 +155,8 @@ splitTermByLines (Info range categories :< syntax) source = flip (,) range $ cas Indexed children -> let (lines, previous) = foldl (childLines Indexed) ([], start range) children in adjoin $ lines ++ contextLines Indexed (Range previous $ end range) source where adjoin = reverse . foldl (adjoinLinesBy $ openTerm source) [] + adjoinTermLines constructor children = let (lines, previous) = foldl (childLines constructor) ([], start range) children in + adjoin $ lines ++ contextLines constructor (Range previous $ end range) source contextLines constructor range source = Line True . (:[]) . (:< constructor []) . (`Info` categories) <$> actualLineRanges range source childLines constructor (lines, previous) child = let (childLines, childRange) = splitTermByLines child source in (adjoin $ lines ++ contextLines constructor (Range previous $ start childRange) source ++ childLines, end childRange) From 29c136c80f13f52fe599d0d3da821469d4c3fa78 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 15:00:03 -0500 Subject: [PATCH 073/259] Define `splitTermByLines` over `Indexed` terms using `adjoinTermLines`. --- src/Split.hs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index ac8a873ec..17b2d7ccc 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -152,8 +152,7 @@ diffToRows (Pure (Replace a b)) _ before after = (replacedRows, (leftRange, righ splitTermByLines :: Term a Info -> String -> ([Line (Term a Info)], Range) splitTermByLines (Info range categories :< syntax) source = flip (,) range $ case syntax of Leaf a -> adjoin $ Line True . (:[]) . (:< Leaf a) . (`Info` categories) <$> actualLineRanges range source - Indexed children -> let (lines, previous) = foldl (childLines Indexed) ([], start range) children in - adjoin $ lines ++ contextLines Indexed (Range previous $ end range) source + Indexed children -> adjoinTermLines Indexed children where adjoin = reverse . foldl (adjoinLinesBy $ openTerm source) [] adjoinTermLines constructor children = let (lines, previous) = foldl (childLines constructor) ([], start range) children in adjoin $ lines ++ contextLines constructor (Range previous $ end range) source From 4030b8d9e2bf66223d45666c06c3c5a3c0b17fae Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 15:00:40 -0500 Subject: [PATCH 074/259] Define splitTermByLines over Fixed terms. --- src/Split.hs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Split.hs b/src/Split.hs index 17b2d7ccc..c0fb59759 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -153,6 +153,7 @@ splitTermByLines :: Term a Info -> String -> ([Line (Term a Info)], Range) splitTermByLines (Info range categories :< syntax) source = flip (,) range $ case syntax of Leaf a -> adjoin $ Line True . (:[]) . (:< Leaf a) . (`Info` categories) <$> actualLineRanges range source Indexed children -> adjoinTermLines Indexed children + Fixed children -> adjoinTermLines Fixed children where adjoin = reverse . foldl (adjoinLinesBy $ openTerm source) [] adjoinTermLines constructor children = let (lines, previous) = foldl (childLines constructor) ([], start range) children in adjoin $ lines ++ contextLines constructor (Range previous $ end range) source From 4a15e11f3b2c9b88b99d71aa0d94d0e15f7efdac Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 15:09:39 -0500 Subject: [PATCH 075/259] OrderedMaps of Eq keys are Monoids. --- src/OrderedMap.hs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/OrderedMap.hs b/src/OrderedMap.hs index bb62738b9..04fa13c5f 100644 --- a/src/OrderedMap.hs +++ b/src/OrderedMap.hs @@ -16,6 +16,10 @@ module OrderedMap ( data OrderedMap key value = OrderedMap { toList :: [(key, value)] } deriving (Show, Eq, Functor, Foldable, Traversable) +instance Eq key => Monoid (OrderedMap key value) where + mempty = fromList [] + mappend = union + fromList :: [(key, value)] -> OrderedMap key value fromList list = OrderedMap list From fcfe258014d4360fb284d2f3b305584398a0ec16 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 15:11:59 -0500 Subject: [PATCH 076/259] Implement `!` using `fromMaybe`. --- src/OrderedMap.hs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/OrderedMap.hs b/src/OrderedMap.hs index 04fa13c5f..116b4d61c 100644 --- a/src/OrderedMap.hs +++ b/src/OrderedMap.hs @@ -13,6 +13,8 @@ module OrderedMap ( , difference ) where +import qualified Data.Maybe as Maybe + data OrderedMap key value = OrderedMap { toList :: [(key, value)] } deriving (Show, Eq, Functor, Foldable, Traversable) @@ -29,9 +31,7 @@ keys (OrderedMap pairs) = fst <$> pairs infixl 9 ! (!) :: Eq key => OrderedMap key value -> key -> value -map ! key = case OrderedMap.lookup key map of - Just value -> value - Nothing -> error "no value found for key" +map ! key = Maybe.fromMaybe (error "no value found for key") $ OrderedMap.lookup key map lookup :: Eq key => key -> OrderedMap key value -> Maybe value lookup key = Prelude.lookup key . toList From bba1dd7f4baac69bb551c88e820b5c560b50cadb Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 15:12:05 -0500 Subject: [PATCH 077/259] Eta reduce fromList. --- src/OrderedMap.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OrderedMap.hs b/src/OrderedMap.hs index 116b4d61c..198b014dd 100644 --- a/src/OrderedMap.hs +++ b/src/OrderedMap.hs @@ -23,7 +23,7 @@ instance Eq key => Monoid (OrderedMap key value) where mappend = union fromList :: [(key, value)] -> OrderedMap key value -fromList list = OrderedMap list +fromList = OrderedMap keys :: OrderedMap key value -> [key] keys (OrderedMap pairs) = fst <$> pairs From d2e4646b5b7eef3170e490e10e0d45825d1beb21 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 15:12:26 -0500 Subject: [PATCH 078/259] Drop redundant parentheses. --- src/OrderedMap.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OrderedMap.hs b/src/OrderedMap.hs index 198b014dd..9076e5b5e 100644 --- a/src/OrderedMap.hs +++ b/src/OrderedMap.hs @@ -50,7 +50,7 @@ unions :: Eq key => [OrderedMap key value] -> OrderedMap key value unions = foldl union empty intersectionWith :: Eq key => (a -> b -> c) -> OrderedMap key a -> OrderedMap key b -> OrderedMap key c -intersectionWith combine (OrderedMap a) (OrderedMap b) = OrderedMap $ a >>= (\ (key, value) -> maybe [] (pure . ((,) key) . combine value) $ Prelude.lookup key b) +intersectionWith combine (OrderedMap a) (OrderedMap b) = OrderedMap $ a >>= (\ (key, value) -> maybe [] (pure . (,) key . combine value) $ Prelude.lookup key b) difference :: Eq key => OrderedMap key a -> OrderedMap key b -> OrderedMap key a difference (OrderedMap a) (OrderedMap b) = OrderedMap $ filter (not . (`elem` extant) . fst) a From 66e6c0d69b4fb9125742c3da0c44df4b3b7d68a4 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 15:13:37 -0500 Subject: [PATCH 079/259] Define `contextLines` over `Monoid`s using `mempty`. --- src/Split.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Split.hs b/src/Split.hs index c0fb59759..76bf7d61f 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -157,7 +157,7 @@ splitTermByLines (Info range categories :< syntax) source = flip (,) range $ cas where adjoin = reverse . foldl (adjoinLinesBy $ openTerm source) [] adjoinTermLines constructor children = let (lines, previous) = foldl (childLines constructor) ([], start range) children in adjoin $ lines ++ contextLines constructor (Range previous $ end range) source - contextLines constructor range source = Line True . (:[]) . (:< constructor []) . (`Info` categories) <$> actualLineRanges range source + contextLines constructor range source = Line True . (:[]) . (:< constructor mempty) . (`Info` categories) <$> actualLineRanges range source childLines constructor (lines, previous) child = let (childLines, childRange) = splitTermByLines child source in (adjoin $ lines ++ contextLines constructor (Range previous $ start childRange) source ++ childLines, end childRange) From bd680b966dd7b81f5b022e3f325f5b56ec96de79 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 15:13:57 -0500 Subject: [PATCH 080/259] Define splitTermByLines over Keyed terms. --- src/Split.hs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Split.hs b/src/Split.hs index 76bf7d61f..f636a2f07 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -154,6 +154,7 @@ splitTermByLines (Info range categories :< syntax) source = flip (,) range $ cas Leaf a -> adjoin $ Line True . (:[]) . (:< Leaf a) . (`Info` categories) <$> actualLineRanges range source Indexed children -> adjoinTermLines Indexed children Fixed children -> adjoinTermLines Fixed children + Keyed children -> adjoinTermLines Keyed children where adjoin = reverse . foldl (adjoinLinesBy $ openTerm source) [] adjoinTermLines constructor children = let (lines, previous) = foldl (childLines constructor) ([], start range) children in adjoin $ lines ++ contextLines constructor (Range previous $ end range) source From 5bd9684a1dd9b5b5a142722d7fd9c186e748f953 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 15:14:26 -0500 Subject: [PATCH 081/259] Remove weird backticks. --- src/Split.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index f636a2f07..d6296db89 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -148,7 +148,7 @@ diffToRows (Pure (Replace a b)) _ before after = (replacedRows, (leftRange, righ (leftElements, leftRange) = termToLines a before (rightElements, rightRange) = termToLines b after --- | Takes a term and a `source` and returns a list of lines and their range within `source`. +-- | Takes a term and a source and returns a list of lines and their range within source. splitTermByLines :: Term a Info -> String -> ([Line (Term a Info)], Range) splitTermByLines (Info range categories :< syntax) source = flip (,) range $ case syntax of Leaf a -> adjoin $ Line True . (:[]) . (:< Leaf a) . (`Info` categories) <$> actualLineRanges range source @@ -162,7 +162,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) source ++ childLines, end childRange) --- | Takes a term and a `source` and returns a list of lines and their range within `source`. +-- | Takes a term and a source and returns a list of lines and their range within source. termToLines :: Term a Info -> String -> ([Line HTML], Range) termToLines (Info range categories :< syntax) source = (rows syntax, range) where From 955874560e4f298c901b68e03409c174f66c42a9 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 18:55:54 -0500 Subject: [PATCH 082/259] Move the ranges from annotatedToRows into diffToRows. --- src/Split.hs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index d6296db89..d2c31eea5 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -130,7 +130,7 @@ instance Monoid (Line a) where mappend (Line c1 xs) (Line c2 ys) = Line (c1 || c2) (xs <> ys) diffToRows :: Diff a Info -> (Int, Int) -> String -> String -> ([Row HTML], (Range, Range)) -diffToRows (Free annotated) _ before after = annotatedToRows annotated before after +diffToRows (Free annotated@(Annotated (Info left _, Info right _) _)) _ before after = (annotatedToRows annotated before after, (left, right)) diffToRows (Pure (Insert term)) (previousIndex, _) _ after = (rowWithInsertedLine <$> afterLines, (Range previousIndex previousIndex, range)) where (afterLines, range) = termToLines term after @@ -182,8 +182,8 @@ termToLines (Info range categories :< syntax) source = (rows syntax, range) elements = elementAndBreak (Span $ classify categories) =<< actualLines (substring range source) -- | Given an Annotated and before/after strings, returns a list of `Row`s representing the newline-separated diff. -annotatedToRows :: Annotated a (Info, Info) (Diff a Info) -> String -> String -> ([Row HTML], (Range, Range)) -annotatedToRows (Annotated (Info left leftCategories, Info right rightCategories) syntax) before after = (rows syntax, ranges) +annotatedToRows :: Annotated a (Info, Info) (Diff a Info) -> String -> String -> [Row HTML] +annotatedToRows (Annotated (Info left leftCategories, Info right rightCategories) syntax) before after = rows syntax where rows (Leaf _) = zipWithMaybe rowFromMaybeRows leftElements rightElements rows (Indexed i) = rewrapRowContentsIn Ul <$> childRows i From 07a90b7d09d616de0a6c32fd15c923111895ca81 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 19:20:53 -0500 Subject: [PATCH 083/259] Apply the constructor to mempty outside of contextLines. --- src/Split.hs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index d2c31eea5..5c0db9b1b 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -156,9 +156,9 @@ splitTermByLines (Info range categories :< syntax) source = flip (,) range $ cas Fixed children -> adjoinTermLines Fixed children Keyed children -> adjoinTermLines Keyed children where adjoin = reverse . foldl (adjoinLinesBy $ openTerm source) [] - adjoinTermLines constructor children = let (lines, previous) = foldl (childLines constructor) ([], start range) children in - adjoin $ lines ++ contextLines constructor (Range previous $ end range) source - contextLines constructor range source = Line True . (:[]) . (:< constructor mempty) . (`Info` categories) <$> actualLineRanges range source + adjoinTermLines constructor children = let (lines, previous) = foldl (childLines $ constructor mempty) ([], start range) children in + adjoin $ lines ++ contextLines (constructor mempty) (Range previous $ end range) source + contextLines constructor range source = Line True . (:[]) . (:< constructor) . (`Info` categories) <$> actualLineRanges range source childLines constructor (lines, previous) child = let (childLines, childRange) = splitTermByLines child source in (adjoin $ lines ++ contextLines constructor (Range previous $ start childRange) source ++ childLines, end childRange) From 6a80813d191181b3800b5acc5149cb9bd2e035f1 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 19:21:29 -0500 Subject: [PATCH 084/259] Use contextLines to define splitTermByLines over leaves. --- src/Split.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Split.hs b/src/Split.hs index 5c0db9b1b..1b558e360 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -151,7 +151,7 @@ diffToRows (Pure (Replace a b)) _ before after = (replacedRows, (leftRange, righ -- | Takes a term and a source and returns a list of lines and their range within source. splitTermByLines :: Term a Info -> String -> ([Line (Term a Info)], Range) splitTermByLines (Info range categories :< syntax) source = flip (,) range $ case syntax of - Leaf a -> adjoin $ Line True . (:[]) . (:< Leaf a) . (`Info` categories) <$> actualLineRanges range source + Leaf a -> adjoin $ contextLines (Leaf a) range source Indexed children -> adjoinTermLines Indexed children Fixed children -> adjoinTermLines Fixed children Keyed children -> adjoinTermLines Keyed children From 65cb2837cba9101bddd53f8fb27fe4a3064b5bf4 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 19:38:11 -0500 Subject: [PATCH 085/259] Add a zipWithDefaults function. --- src/Split.hs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Split.hs b/src/Split.hs index 1b558e360..e0bd34765 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -283,6 +283,9 @@ zipWithMaybe f la lb = take len $ zipWith f la' lb' la' = (Just <$> la) ++ repeat Nothing lb' = (Just <$> lb) ++ repeat Nothing +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) + classify :: Set.Set Category -> Maybe ClassName classify categories = ("category-" ++) <$> maybeLast categories From 4486cb90a3f169b41f7ea65d0c4ee4664141a4ef Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 19:38:57 -0500 Subject: [PATCH 086/259] Define zipWithMaybe in terms of zipWithDefaults. --- src/Split.hs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index e0bd34765..fb4edbe5e 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -277,11 +277,7 @@ adjoinLinesBy f (prev:rest) line | Just _ <- openLineBy f [ prev ] = (prev <> li adjoinLinesBy _ lines line = line : lines zipWithMaybe :: (Maybe a -> Maybe b -> c) -> [a] -> [b] -> [c] -zipWithMaybe f la lb = take len $ zipWith f la' lb' - where - len = max (length la) (length lb) - la' = (Just <$> la) ++ repeat Nothing - lb' = (Just <$> lb) ++ repeat Nothing +zipWithMaybe f a b = zipWithDefaults f Nothing Nothing (Just <$> a) (Just <$> b) 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) From 8cdb0a582a3a1b431739a02ae72e15b4caa24603 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 19:40:00 -0500 Subject: [PATCH 087/259] Add a splitAnnotatedByLines function defined over leaves. --- src/Split.hs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Split.hs b/src/Split.hs index fb4edbe5e..6b92c1b0a 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -181,6 +181,11 @@ termToLines (Info range categories :< syntax) source = (rows syntax, range) (adjoin $ lines ++ contextLines (Range previous $ start childRange) source ++ childLines, end childRange) elements = elementAndBreak (Span $ classify categories) =<< actualLines (substring range source) +splitAnnotatedByLines :: (String, String) -> (Range, Range) -> (Set.Set Category, Set.Set Category) -> Syntax a (Diff a Info) -> [Row (Term a Info)] +splitAnnotatedByLines sources ranges categories syntax = case syntax of + Leaf a -> zipWithDefaults Row EmptyLine EmptyLine (contextLines (Leaf a) (fst ranges) (fst categories) (fst sources)) (contextLines (Leaf a) (snd ranges) (snd categories) (snd sources)) + where contextLines constructor range categories source = Line False . (:[]) . (:< constructor) . (`Info` categories) <$> actualLineRanges range source + -- | Given an Annotated and before/after strings, returns a list of `Row`s representing the newline-separated diff. annotatedToRows :: Annotated a (Info, Info) (Diff a Info) -> String -> String -> [Row HTML] annotatedToRows (Annotated (Info left leftCategories, Info right rightCategories) syntax) before after = rows syntax From 61067a6f2ae2560c132610d3be5f07993ce26c68 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 19:44:07 -0500 Subject: [PATCH 088/259] Remove the ranges from the annotatedToRows tests. --- test/SplitSpec.hs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index f462dec0a..7d0f238df 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -32,48 +32,48 @@ spec :: Spec spec = do describe "annotatedToRows" $ do it "outputs one row for single-line unchanged leaves" $ - annotatedToRows (unchanged "a" "leaf" (Leaf "")) "a" "a" `shouldBe` ([ Row (Line False [ span "a" ]) (Line False [ span "a" ]) ], (Range 0 1, Range 0 1)) + annotatedToRows (unchanged "a" "leaf" (Leaf "")) "a" "a" `shouldBe` [ Row (Line False [ span "a" ]) (Line False [ span "a" ]) ] it "outputs one row for single-line empty unchanged indexed nodes" $ - annotatedToRows (unchanged "[]" "branch" (Indexed [])) "[]" "[]" `shouldBe` ([ Row (Line False [ Ul (Just "category-branch") [ Text "[]" ] ]) (Line False [ Ul (Just "category-branch") [ Text "[]" ] ]) ], (Range 0 2, Range 0 2)) + annotatedToRows (unchanged "[]" "branch" (Indexed [])) "[]" "[]" `shouldBe` [ Row (Line False [ Ul (Just "category-branch") [ Text "[]" ] ]) (Line False [ Ul (Just "category-branch") [ Text "[]" ] ]) ] it "outputs one row for single-line non-empty unchanged indexed nodes" $ annotatedToRows (unchanged "[ a, b ]" "branch" (Indexed [ Free . offsetAnnotated 2 2 $ unchanged "a" "leaf" (Leaf ""), Free . offsetAnnotated 5 5 $ unchanged "b" "leaf" (Leaf "") - ])) "[ a, b ]" "[ a, b ]" `shouldBe` ([ Row (Line False [ Ul (Just "category-branch") [ Text "[ ", span "a", Text ", ", span "b", Text " ]" ] ]) (Line False [ Ul (Just "category-branch") [ Text "[ ", span "a", Text ", ", span "b", Text " ]" ] ]) ], (Range 0 8, Range 0 8)) + ])) "[ a, b ]" "[ a, b ]" `shouldBe` [ Row (Line False [ Ul (Just "category-branch") [ Text "[ ", span "a", Text ", ", span "b", Text " ]" ] ]) (Line False [ Ul (Just "category-branch") [ Text "[ ", span "a", Text ", ", span "b", Text " ]" ] ]) ] it "outputs one row for single-line non-empty formatted indexed nodes" $ annotatedToRows (formatted "[ a, b ]" "[ a, b ]" "branch" (Indexed [ Free . offsetAnnotated 2 2 $ unchanged "a" "leaf" (Leaf ""), Free . offsetAnnotated 5 6 $ unchanged "b" "leaf" (Leaf "") - ])) "[ a, b ]" "[ a, b ]" `shouldBe` ([ Row (Line False [ Ul (Just "category-branch") [ Text "[ ", span "a", Text ", ", span "b", Text " ]" ] ]) (Line False [ Ul (Just "category-branch") [ Text "[ ", span "a", Text ", ", span "b", Text " ]" ] ]) ], (Range 0 8, Range 0 9)) + ])) "[ a, b ]" "[ a, b ]" `shouldBe` [ Row (Line False [ Ul (Just "category-branch") [ Text "[ ", span "a", Text ", ", span "b", Text " ]" ] ]) (Line False [ Ul (Just "category-branch") [ Text "[ ", span "a", Text ", ", span "b", Text " ]" ] ]) ] it "outputs two rows for two-line non-empty unchanged indexed nodes" $ annotatedToRows (unchanged "[ a,\nb ]" "branch" (Indexed [ Free . offsetAnnotated 2 2 $ unchanged "a" "leaf" (Leaf ""), Free . offsetAnnotated 5 5 $ unchanged "b" "leaf" (Leaf "") ])) "[ a,\nb ]" "[ a,\nb ]" `shouldBe` - ([ + [ Row (Line False [ Ul (Just "category-branch") [ Text "[ ", span "a", Text ",", Break ] ]) (Line False [ Ul (Just "category-branch") [ Text "[ ", span "a", Text ",", Break] ]), Row (Line False [ Ul (Just "category-branch") [ span "b", Text " ]" ] ]) (Line False [ Ul (Just "category-branch") [ span "b", Text " ]" ] ]) - ], (Range 0 8, Range 0 8)) + ] it "outputs two rows for two-line non-empty formatted indexed nodes" $ annotatedToRows (formatted "[ a,\nb ]" "[\na,\nb ]" "branch" (Indexed [ Free . offsetAnnotated 2 2 $ unchanged "a" "leaf" (Leaf ""), Free . offsetAnnotated 5 5 $ unchanged "b" "leaf" (Leaf "") ])) "[ a,\nb ]" "[\na,\nb ]" `shouldBe` - ([ + [ Row (Line False [ Ul (Just "category-branch") [ Text "[ ", span "a", Text ",", Break ] ]) (Line False [ Ul (Just "category-branch") [ Text "[", Break ] ]), Row EmptyLine (Line False [ Ul (Just "category-branch") [ span "a", Text ",", Break ] ]), Row (Line False [ Ul (Just "category-branch") [ span "b", Text " ]" ] ]) (Line False [ Ul (Just "category-branch") [ span "b", Text " ]" ] ]) - ], (Range 0 8, Range 0 8)) + ] it "" $ let (sourceA, sourceB) = ("[\na\n,\nb]", "[a,b]") in @@ -81,7 +81,7 @@ spec = do Free . offsetAnnotated 2 1 $ unchanged "a" "leaf" (Leaf ""), Free . offsetAnnotated 6 3 $ unchanged "b" "leaf" (Leaf "") ])) sourceA sourceB `shouldBe` - ([ + [ Row (Line False [ Ul (Just "category-branch") [ Text "[", Break ] ]) (Line False [ Ul (Just "category-branch") [ Text "[", span "a", Text ",", span "b", Text "]" ] ]), Row (Line False [ Ul (Just "category-branch") [ span "a", Break ] ]) @@ -90,7 +90,7 @@ spec = do EmptyLine, Row (Line False [ Ul (Just "category-branch") [ span "b", Text "]" ] ]) EmptyLine - ], (Range 0 8, Range 0 5)) + ] it "should split multi-line deletions across multiple rows" $ let (sourceA, sourceB) = ("/*\n*/\na", "a") in @@ -98,11 +98,11 @@ spec = do Pure . Delete $ (Info (Range 0 5) (Set.fromList ["leaf"]) :< Leaf ""), Free . offsetAnnotated 6 0 $ unchanged "a" "leaf" (Leaf "") ])) sourceA sourceB `shouldBe` - ([ + [ Row (Line True [ Ul (Just "category-branch") [ Div (Just "delete") [ span "/*", Break ] ] ]) EmptyLine, Row (Line True [ Ul (Just "category-branch") [ Div (Just "delete") [ span "*/" ], Break ] ]) EmptyLine, Row (Line False [ Ul (Just "category-branch") [ span "a" ] ]) (Line False [ Ul (Just "category-branch") [ span "a" ] ]) - ], (Range 0 7, Range 0 1)) + ] describe "unicode" $ it "equivalent precomposed and decomposed characters are not equal" $ @@ -110,7 +110,7 @@ spec = do syntax = Leaf . Pure $ Replace (info sourceA "leaf" :< Leaf "") (info sourceB "leaf" :< Leaf "") in annotatedToRows (formatted sourceA sourceB "leaf" syntax) sourceA sourceB `shouldBe` - ([ Row (Line False [ span "t\776" ]) (Line False [ span "\7831"]) ], (Range 0 2, Range 0 1)) + [ Row (Line False [ span "t\776" ]) (Line False [ span "\7831"]) ] describe "adjoinRowsBy" $ do From b45e10eb92e740923493279800ac6b52a3a799bf Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 19:54:40 -0500 Subject: [PATCH 089/259] Port the termToLines test to splitTermByLines. --- test/SplitSpec.hs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index 7d0f238df..97252f4d1 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -143,6 +143,15 @@ spec = do Line True [ span "*/" ] ], Range 0 5) + describe "splitTermByLines" $ do + it "splits multi-line terms into multiple lines" $ + let categories = Set.singleton "leaf" in splitTermByLines (Info (Range 0 5) categories :< Leaf "") "/*\n*/" + `shouldBe` + ([ + Line True [ Info (Range 0 3) categories :< Leaf "" ], + Line True [ Info (Range 3 5) categories :< Leaf "" ] + ], Range 0 5) + describe "openLineBy" $ do it "should produce the earliest non-empty line in a list, if open" $ openLineBy openElement [ From 60edd3b19a59444de832d22d10c0950bc08dfc0a Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 20:02:17 -0500 Subject: [PATCH 090/259] Omit the categories in the splitTermByLines test. --- test/SplitSpec.hs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index 97252f4d1..6448a15dc 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -145,11 +145,11 @@ spec = do describe "splitTermByLines" $ do it "splits multi-line terms into multiple lines" $ - let categories = Set.singleton "leaf" in splitTermByLines (Info (Range 0 5) categories :< Leaf "") "/*\n*/" + splitTermByLines (Info (Range 0 5) mempty :< Leaf "") "/*\n*/" `shouldBe` ([ - Line True [ Info (Range 0 3) categories :< Leaf "" ], - Line True [ Info (Range 3 5) categories :< Leaf "" ] + Line True [ Info (Range 0 3) mempty :< Leaf "" ], + Line True [ Info (Range 3 5) mempty :< Leaf "" ] ], Range 0 5) describe "openLineBy" $ do From d1abf65cdd7f670e70df18141ec05ecbb8772038 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 20:04:05 -0500 Subject: [PATCH 091/259] Test openLineBy over openTerm. --- test/SplitSpec.hs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index 6448a15dc..2eebb92e9 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -160,11 +160,22 @@ spec = do Line True [ Div (Just "delete") [ span "/*", Break ] ] ] `shouldBe` (Just $ Line True [ Div (Just "delete") [ span "*/" ] ]) + it "should produce the earliest non-empty line in a list, if open" $ + openLineBy (openTerm "\n ") [ + Line True [ Info (Range 1 2) mempty :< Leaf "" ], + Line True [ Info (Range 0 1) mempty :< Leaf "" ] + ] `shouldBe` (Just $ Line True [ Info (Range 1 2) mempty :< Leaf "" ]) + it "should return Nothing if the earliest non-empty line is closed" $ openLineBy openElement [ Line True [ Div (Just "delete") [ span " * Debugging", Break ] ] ] `shouldBe` Nothing + it "should return Nothing if the earliest non-empty line is closed" $ + openLineBy (openTerm "\n") [ + Line True [ Info (Range 0 1) mempty :< Leaf "" ] + ] `shouldBe` Nothing + where rightRowText text = rightRow [ Text text ] rightRow xs = Row EmptyLine (Line False xs) From 7ee39b2d404479f7cfe794fb30a70d8d44cb423b Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 20:06:19 -0500 Subject: [PATCH 092/259] Test that openTerm classifies strings ending with newlines as closed. --- test/SplitSpec.hs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index 2eebb92e9..66c56efe4 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -176,6 +176,10 @@ spec = do Line True [ Info (Range 0 1) mempty :< Leaf "" ] ] `shouldBe` Nothing + describe "openTerm" $ do + it "should return Nothing for terms whose substring ends with a newline" $ + openTerm " \n" (Info (Range 0 2) mempty :< Leaf "") `shouldBe` Nothing + where rightRowText text = rightRow [ Text text ] rightRow xs = Row EmptyLine (Line False xs) From 41e03beb85e4f978f4cd32379c71d72879bc91ef Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 20:07:53 -0500 Subject: [PATCH 093/259] =?UTF-8?q?Tweak=20the=20test=20name=E2=80=99s=20w?= =?UTF-8?q?ording.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/SplitSpec.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index 66c56efe4..a11b9bbbc 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -177,7 +177,7 @@ spec = do ] `shouldBe` Nothing describe "openTerm" $ do - it "should return Nothing for terms whose substring ends with a newline" $ + it "returns Nothing for terms whose substring ends with a newline" $ openTerm " \n" (Info (Range 0 2) mempty :< Leaf "") `shouldBe` Nothing where From 1f6440e7a1f744c42fa3cef58e37b01e74407483 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 20:08:05 -0500 Subject: [PATCH 094/259] Test that openTerm returns Just for open terms. --- test/SplitSpec.hs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index a11b9bbbc..241c2706c 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -177,6 +177,9 @@ spec = do ] `shouldBe` Nothing describe "openTerm" $ do + it "returns Just the term if its substring does not end with a newline" $ + let term = Info (Range 0 2) mempty :< Leaf "" in openTerm " " term `shouldBe` Just term + it "returns Nothing for terms whose substring ends with a newline" $ openTerm " \n" (Info (Range 0 2) mempty :< Leaf "") `shouldBe` Nothing From d99be907d6930c37471dfec903975584666804ab Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 20:08:47 -0500 Subject: [PATCH 095/259] Fix the inverted sense of openTerm. --- src/Split.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 6b92c1b0a..56e3b4e89 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -267,8 +267,8 @@ openElement h = Just h openTerm :: String -> Term a Info -> Maybe (Term a Info) openTerm source term@(Info range _ :< _) = case (source !!) <$> maybeLastIndex range of - Just '\n' -> Just term - _ -> Nothing + Just '\n' -> Nothing + _ -> Just term openLineBy :: (a -> Maybe a) -> [Line a] -> Maybe (Line a) openLineBy _ [] = Nothing From a69366cf4b7da2f019d144abc347756a2fbfec66 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 20:21:55 -0500 Subject: [PATCH 096/259] Always drop the initial range. --- src/Split.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Split.hs b/src/Split.hs index 56e3b4e89..c5999b1fe 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -299,5 +299,5 @@ actualLines lines = case break (== '\n') lines of -- | Compute the line ranges within a given range of a string. actualLineRanges :: Range -> String -> [Range] -actualLineRanges range = scanl toRange (Range (start range) (start range)) . actualLines . substring range +actualLineRanges range = drop 1 . scanl toRange (Range (start range) (start range)) . actualLines . substring range where toRange previous string = Range (end previous) $ end previous + length string From 2c3ff54dc6a1916b819ea748b2c5a703a9c2d125 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 20:23:56 -0500 Subject: [PATCH 097/259] Assertive assertions. --- test/SplitSpec.hs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index 241c2706c..8de15986b 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -92,7 +92,7 @@ spec = do EmptyLine ] - it "should split multi-line deletions across multiple rows" $ + it "splits multi-line deletions across multiple rows" $ let (sourceA, sourceB) = ("/*\n*/\na", "a") in annotatedToRows (formatted sourceA sourceB "branch" (Indexed [ Pure . Delete $ (Info (Range 0 5) (Set.fromList ["leaf"]) :< Leaf ""), @@ -153,25 +153,25 @@ spec = do ], Range 0 5) describe "openLineBy" $ do - it "should produce the earliest non-empty line in a list, if open" $ + it "produces the earliest non-empty line in a list, if open" $ openLineBy openElement [ Line True [ Div (Just "delete") [ span "*/" ] ], Line True [ Div (Just "delete") [ span " * Debugging", Break ] ], Line True [ Div (Just "delete") [ span "/*", Break ] ] ] `shouldBe` (Just $ Line True [ Div (Just "delete") [ span "*/" ] ]) - it "should produce the earliest non-empty line in a list, if open" $ + it "produces the earliest non-empty line in a list, if open" $ openLineBy (openTerm "\n ") [ Line True [ Info (Range 1 2) mempty :< Leaf "" ], Line True [ Info (Range 0 1) mempty :< Leaf "" ] ] `shouldBe` (Just $ Line True [ Info (Range 1 2) mempty :< Leaf "" ]) - it "should return Nothing if the earliest non-empty line is closed" $ + it "returns Nothing if the earliest non-empty line is closed" $ openLineBy openElement [ Line True [ Div (Just "delete") [ span " * Debugging", Break ] ] ] `shouldBe` Nothing - it "should return Nothing if the earliest non-empty line is closed" $ + it "returns Nothing if the earliest non-empty line is closed" $ openLineBy (openTerm "\n") [ Line True [ Info (Range 0 1) mempty :< Leaf "" ] ] `shouldBe` Nothing From 09034a8fdaa2b5e64546c6daaca5c7c2e9205761 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 20:39:51 -0500 Subject: [PATCH 098/259] We never need to adjoin leaf lines. --- src/Split.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Split.hs b/src/Split.hs index c5999b1fe..7454c36f1 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -151,7 +151,7 @@ diffToRows (Pure (Replace a b)) _ before after = (replacedRows, (leftRange, righ -- | Takes a term and a source and returns a list of lines and their range within source. splitTermByLines :: Term a Info -> String -> ([Line (Term a Info)], Range) splitTermByLines (Info range categories :< syntax) source = flip (,) range $ case syntax of - Leaf a -> adjoin $ contextLines (Leaf a) range source + Leaf a -> contextLines (Leaf a) range source Indexed children -> adjoinTermLines Indexed children Fixed children -> adjoinTermLines Fixed children Keyed children -> adjoinTermLines Keyed children From 45cf3683565156747fd3b8dba60e299972f9aea5 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 20:46:03 -0500 Subject: [PATCH 099/259] =?UTF-8?q?Rename=20adjoinTermLines=20=E2=86=92=20?= =?UTF-8?q?adjoinChildLines.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Split.hs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 7454c36f1..068493fab 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -152,11 +152,11 @@ diffToRows (Pure (Replace a b)) _ before after = (replacedRows, (leftRange, righ splitTermByLines :: Term a Info -> String -> ([Line (Term a Info)], Range) splitTermByLines (Info range categories :< syntax) source = flip (,) range $ case syntax of Leaf a -> contextLines (Leaf a) range source - Indexed children -> adjoinTermLines Indexed children - Fixed children -> adjoinTermLines Fixed children - Keyed children -> adjoinTermLines Keyed children + Indexed children -> adjoinChildLines Indexed children + Fixed children -> adjoinChildLines Fixed children + Keyed children -> adjoinChildLines Keyed children where adjoin = reverse . foldl (adjoinLinesBy $ openTerm source) [] - adjoinTermLines constructor children = let (lines, previous) = foldl (childLines $ constructor mempty) ([], start range) children in + adjoinChildLines constructor children = let (lines, previous) = foldl (childLines $ constructor mempty) ([], start range) children in adjoin $ lines ++ contextLines (constructor mempty) (Range previous $ end range) source contextLines constructor range source = Line True . (:[]) . (:< constructor) . (`Info` categories) <$> actualLineRanges range source childLines constructor (lines, previous) child = let (childLines, childRange) = splitTermByLines child source in From 739e9992338a5776fe56b35638deabc3c7c40e00 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 20:48:55 -0500 Subject: [PATCH 100/259] Extract a contextRows binding. --- src/Split.hs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Split.hs b/src/Split.hs index 068493fab..3106bb10b 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -183,8 +183,9 @@ termToLines (Info range categories :< syntax) source = (rows syntax, range) splitAnnotatedByLines :: (String, String) -> (Range, Range) -> (Set.Set Category, Set.Set Category) -> Syntax a (Diff a Info) -> [Row (Term a Info)] splitAnnotatedByLines sources ranges categories syntax = case syntax of - Leaf a -> zipWithDefaults Row EmptyLine EmptyLine (contextLines (Leaf a) (fst ranges) (fst categories) (fst sources)) (contextLines (Leaf a) (snd ranges) (snd categories) (snd sources)) + Leaf a -> contextRows (Leaf a) ranges categories sources where contextLines constructor range categories source = Line False . (:[]) . (:< constructor) . (`Info` categories) <$> actualLineRanges range source + contextRows constructor ranges categoriess sources = zipWithDefaults Row EmptyLine EmptyLine (contextLines (Leaf a) (fst ranges) (fst categories) (fst sources)) (contextLines (Leaf a) (snd ranges) (snd categories) (snd sources)) -- | Given an Annotated and before/after strings, returns a list of `Row`s representing the newline-separated diff. annotatedToRows :: Annotated a (Info, Info) (Diff a Info) -> String -> String -> [Row HTML] From a78ae5a8de7a3e55d1d7049ca6dc2532d2cdc1c8 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 21:00:53 -0500 Subject: [PATCH 101/259] =?UTF-8?q?Correct=20the=20indentation=20of=20Line?= =?UTF-8?q?=E2=80=99s=20Monoid=20instance.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Split.hs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 3106bb10b..3b288b350 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -124,10 +124,10 @@ instance Show a => Show (Line a) where show EmptyLine = "EmptyLine" instance Monoid (Line a) where - mempty = EmptyLine - mappend EmptyLine line = line - mappend line EmptyLine = line - mappend (Line c1 xs) (Line c2 ys) = Line (c1 || c2) (xs <> ys) + mempty = EmptyLine + mappend EmptyLine line = line + mappend line EmptyLine = line + mappend (Line c1 xs) (Line c2 ys) = Line (c1 || c2) (xs <> ys) diffToRows :: Diff a Info -> (Int, Int) -> String -> String -> ([Row HTML], (Range, Range)) diffToRows (Free annotated@(Annotated (Info left _, Info right _) _)) _ before after = (annotatedToRows annotated before after, (left, right)) From 2d383b57c8cc8f95f268aba3de44c0fdd9681c6d Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 22:26:26 -0500 Subject: [PATCH 102/259] Abbreviate sumRows. --- src/Split.hs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 3b288b350..401b1a23d 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -208,11 +208,8 @@ annotatedToRows (Annotated (Info left leftCategories, Info right rightCategories appendRemainder (rows, previousIndices) = reverse . foldl (adjoinRowsBy openElement) [] $ rows ++ contextRows (ends ranges) previousIndices sources starts (left, right) = (start left, start right) ends (left, right) = (end left, end right) - sumRows (rows, previousIndices) child = (allRows, ends childRanges) - where - separatorRows = contextRows (starts childRanges) previousIndices sources - allRows = rows ++ separatorRows ++ childRows - (childRows, childRanges) = diffToRows child previousIndices before after + sumRows (rows, previousIndices) child = let (childRows, childRanges) = diffToRows child previousIndices before after in + (rows ++ contextRows (starts childRanges) previousIndices sources ++ childRows, ends childRanges) contextRows :: (Int, Int) -> (Int, Int) -> (String, String) -> [Row HTML] contextRows childIndices previousIndices sources = zipWithMaybe rowFromMaybeRows leftElements rightElements From aa42b88df50fef3fb2e4a7192277275263a7ad70 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 22:26:43 -0500 Subject: [PATCH 103/259] adjoinRowsBy takes two different adjoining functions. --- src/Split.hs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 401b1a23d..2fea6e2ad 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -205,7 +205,7 @@ annotatedToRows (Annotated (Info left leftCategories, Info right rightCategories ranges = (left, right) sources = (before, after) childRows = appendRemainder . foldl sumRows ([], starts ranges) - appendRemainder (rows, previousIndices) = reverse . foldl (adjoinRowsBy openElement) [] $ rows ++ contextRows (ends ranges) previousIndices sources + appendRemainder (rows, previousIndices) = reverse . foldl (adjoinRowsBy openElement openElement) [] $ rows ++ contextRows (ends ranges) previousIndices sources starts (left, right) = (start left, start right) ends (left, right) = (end left, end right) sumRows (rows, previousIndices) child = let (childRows, childRanges) = diffToRows child previousIndices before after in @@ -233,28 +233,28 @@ rowFromMaybeRows a b = Row (maybe EmptyLine (Line False . (:[])) a) (maybe Empty maybeLast :: Foldable f => f a -> Maybe a maybeLast = foldl (flip $ const . Just) Nothing -adjoinRowsBy :: (a -> Maybe a) -> [Row a] -> Row a -> [Row a] -adjoinRowsBy _ [] row = [row] +adjoinRowsBy :: (a -> Maybe a) -> (a -> Maybe a) -> [Row a] -> Row a -> [Row a] +adjoinRowsBy _ _ [] row = [row] -adjoinRowsBy f rows (Row left' right') | Just _ <- openLineBy f $ unLeft <$> rows, Just _ <- openLineBy f $ unRight <$> rows = zipWith Row lefts rights +adjoinRowsBy f g rows (Row left' right') | Just _ <- openLineBy f $ unLeft <$> rows, Just _ <- openLineBy g $ unRight <$> rows = zipWith Row lefts rights where lefts = adjoinLinesBy f (unLeft <$> rows) left' - rights = adjoinLinesBy f (unRight <$> rows) right' + rights = adjoinLinesBy g (unRight <$> rows) right' -adjoinRowsBy f rows (Row left' right') | Just _ <- openLineBy f $ unLeft <$> rows = case right' of +adjoinRowsBy f _ rows (Row left' right') | Just _ <- openLineBy f $ unLeft <$> rows = case right' of EmptyLine -> rest _ -> Row EmptyLine right' : rest where rest = zipWith Row lefts rights lefts = adjoinLinesBy f (unLeft <$> rows) left' rights = unRight <$> rows -adjoinRowsBy f rows (Row left' right') | Just _ <- openLineBy f $ unRight <$> rows = case left' of +adjoinRowsBy _ g rows (Row left' right') | Just _ <- openLineBy g $ unRight <$> rows = case left' of EmptyLine -> rest _ -> Row left' EmptyLine : rest where rest = zipWith Row lefts rights lefts = unLeft <$> rows - rights = adjoinLinesBy f (unRight <$> rows) right' + rights = adjoinLinesBy g (unRight <$> rows) right' -adjoinRowsBy _ rows row = row : rows +adjoinRowsBy _ _ rows row = row : rows openElement :: HTML -> Maybe HTML openElement Break = Nothing From 27c66b558880cc5289abae9b4a84f6d9f21cf4a4 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 22:27:10 -0500 Subject: [PATCH 104/259] Add an `adjoin` binding. --- src/Split.hs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Split.hs b/src/Split.hs index 2fea6e2ad..5b1f77a1d 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -187,6 +187,8 @@ splitAnnotatedByLines sources ranges categories syntax = case syntax of where contextLines constructor range categories source = Line False . (:[]) . (:< constructor) . (`Info` categories) <$> actualLineRanges range source contextRows constructor ranges categoriess sources = zipWithDefaults Row EmptyLine EmptyLine (contextLines (Leaf a) (fst ranges) (fst categories) (fst sources)) (contextLines (Leaf a) (snd ranges) (snd categories) (snd sources)) + adjoin = reverse . foldl (adjoinRowsBy (openTerm $ fst sources) (openTerm $ snd sources)) [] + -- | Given an Annotated and before/after strings, returns a list of `Row`s representing the newline-separated diff. annotatedToRows :: Annotated a (Info, Info) (Diff a Info) -> String -> String -> [Row HTML] annotatedToRows (Annotated (Info left leftCategories, Info right rightCategories) syntax) before after = rows syntax From 5f7b33db85cbb867a2444acba566f83b683357de Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 22:27:19 -0500 Subject: [PATCH 105/259] Add some range-handling bindings. --- src/Split.hs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Split.hs b/src/Split.hs index 5b1f77a1d..4d714804c 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -189,6 +189,10 @@ splitAnnotatedByLines sources ranges categories syntax = case syntax of adjoin = reverse . foldl (adjoinRowsBy (openTerm $ fst sources) (openTerm $ snd sources)) [] + starts (left, right) = (start left, start right) + ends (left, right) = (end left, end right) + makeRanges (leftStart, rightStart) (leftEnd, rightEnd) = (Range leftStart leftEnd, Range rightStart rightEnd) + -- | Given an Annotated and before/after strings, returns a list of `Row`s representing the newline-separated diff. annotatedToRows :: Annotated a (Info, Info) (Diff a Info) -> String -> String -> [Row HTML] annotatedToRows (Annotated (Info left leftCategories, Info right rightCategories) syntax) before after = rows syntax From b9ed84b7b6e062f9be33824d7164c4caf3fb443c Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 22:34:08 -0500 Subject: [PATCH 106/259] Pass categories to contextLines explicitly. --- src/Split.hs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 4d714804c..4d2b1f4e4 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -151,16 +151,16 @@ diffToRows (Pure (Replace a b)) _ before after = (replacedRows, (leftRange, righ -- | Takes a term and a source and returns a list of lines and their range within source. splitTermByLines :: Term a Info -> String -> ([Line (Term a Info)], Range) splitTermByLines (Info range categories :< syntax) source = flip (,) range $ case syntax of - Leaf a -> contextLines (Leaf a) range source + Leaf a -> contextLines (Leaf a) range categories source Indexed children -> adjoinChildLines Indexed children Fixed children -> adjoinChildLines Fixed children Keyed children -> adjoinChildLines Keyed children where adjoin = reverse . foldl (adjoinLinesBy $ openTerm source) [] adjoinChildLines constructor children = let (lines, previous) = foldl (childLines $ constructor mempty) ([], start range) children in - adjoin $ lines ++ contextLines (constructor mempty) (Range previous $ end range) source - contextLines constructor range source = Line True . (:[]) . (:< constructor) . (`Info` categories) <$> actualLineRanges range source + adjoin $ lines ++ contextLines (constructor mempty) (Range previous $ end range) categories source + contextLines constructor range categories source = Line True . (:[]) . (:< constructor) . (`Info` categories) <$> actualLineRanges range source childLines constructor (lines, previous) child = let (childLines, childRange) = splitTermByLines child source in - (adjoin $ lines ++ contextLines constructor (Range previous $ start childRange) source ++ childLines, end childRange) + (adjoin $ lines ++ contextLines constructor (Range previous $ start childRange) categories source ++ childLines, end childRange) -- | Takes a term and a source and returns a list of lines and their range within source. termToLines :: Term a Info -> String -> ([Line HTML], Range) From f43bbe415bf2191d88a21aad0bb0f2df659697fb Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 22:34:20 -0500 Subject: [PATCH 107/259] Add a global contextLines definition. --- src/Split.hs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Split.hs b/src/Split.hs index 4d2b1f4e4..e5be38d20 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -217,6 +217,9 @@ annotatedToRows (Annotated (Info left leftCategories, Info right rightCategories sumRows (rows, previousIndices) child = let (childRows, childRanges) = diffToRows child previousIndices before after in (rows ++ contextRows (starts childRanges) previousIndices sources ++ childRows, ends childRanges) +contextLines :: Syntax a (Term a Info) -> Range -> Set.Set Category -> String -> [Line (Term a Info)] +contextLines constructor range categories source = Line True . (:[]) . (:< constructor) . (`Info` categories) <$> actualLineRanges range source + contextRows :: (Int, Int) -> (Int, Int) -> (String, String) -> [Row HTML] contextRows childIndices previousIndices sources = zipWithMaybe rowFromMaybeRows leftElements rightElements where From ac01a7939c0c0aa13dca9e32a66028bebb4932c0 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 22:34:47 -0500 Subject: [PATCH 108/259] Use the global contextLines definition in splitTermByLines. --- src/Split.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Split.hs b/src/Split.hs index e5be38d20..003fcb81e 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -158,7 +158,7 @@ splitTermByLines (Info range categories :< syntax) source = flip (,) range $ cas where adjoin = reverse . foldl (adjoinLinesBy $ openTerm source) [] adjoinChildLines constructor children = let (lines, previous) = foldl (childLines $ constructor mempty) ([], start range) children in adjoin $ lines ++ contextLines (constructor mempty) (Range previous $ end range) categories source - contextLines constructor range categories source = Line True . (:[]) . (:< constructor) . (`Info` categories) <$> actualLineRanges range source + 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) From 9dba0887c850f9c702397307756a280b489a722e Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 22:37:38 -0500 Subject: [PATCH 109/259] Remove the local contextLines binding from splitAnnotatedByLines. --- src/Split.hs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 003fcb81e..485cb8d2d 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -184,8 +184,7 @@ termToLines (Info range categories :< syntax) source = (rows syntax, range) splitAnnotatedByLines :: (String, String) -> (Range, Range) -> (Set.Set Category, Set.Set Category) -> Syntax a (Diff a Info) -> [Row (Term a Info)] splitAnnotatedByLines sources ranges categories syntax = case syntax of Leaf a -> contextRows (Leaf a) ranges categories sources - where contextLines constructor range categories source = Line False . (:[]) . (:< constructor) . (`Info` categories) <$> actualLineRanges range source - contextRows constructor ranges categoriess sources = zipWithDefaults Row EmptyLine EmptyLine (contextLines (Leaf a) (fst ranges) (fst categories) (fst sources)) (contextLines (Leaf a) (snd ranges) (snd categories) (snd sources)) + where contextRows constructor ranges categoriess sources = zipWithDefaults Row EmptyLine EmptyLine (contextLines (Leaf a) (fst ranges) (fst categories) (fst sources)) (contextLines (Leaf a) (snd ranges) (snd categories) (snd sources)) adjoin = reverse . foldl (adjoinRowsBy (openTerm $ fst sources) (openTerm $ snd sources)) [] From 6c877fd0424db0f410b047991eb2ee01fbe4c4c0 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 22:41:19 -0500 Subject: [PATCH 110/259] =?UTF-8?q?contextRows=20uses=20the=20constructor?= =?UTF-8?q?=20it=E2=80=99s=20passed.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Split.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Split.hs b/src/Split.hs index 485cb8d2d..44f8571fd 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -184,7 +184,7 @@ termToLines (Info range categories :< syntax) source = (rows syntax, range) splitAnnotatedByLines :: (String, String) -> (Range, Range) -> (Set.Set Category, Set.Set Category) -> Syntax a (Diff a Info) -> [Row (Term a Info)] splitAnnotatedByLines sources ranges categories syntax = case syntax of Leaf a -> contextRows (Leaf a) ranges categories sources - where contextRows constructor ranges categoriess sources = zipWithDefaults Row EmptyLine EmptyLine (contextLines (Leaf a) (fst ranges) (fst categories) (fst sources)) (contextLines (Leaf a) (snd ranges) (snd categories) (snd sources)) + where contextRows constructor ranges categories sources = zipWithDefaults Row EmptyLine EmptyLine (contextLines constructor (fst ranges) (fst categories) (fst sources)) (contextLines constructor (snd ranges) (snd categories) (snd sources)) adjoin = reverse . foldl (adjoinRowsBy (openTerm $ fst sources) (openTerm $ snd sources)) [] From 08c9b842533ebc7625c8327d0a5b5c78b56578ca Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 22:42:08 -0500 Subject: [PATCH 111/259] Stub in splitDiffByLines over Free values. --- src/Split.hs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Split.hs b/src/Split.hs index 44f8571fd..fe64cfd75 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -129,6 +129,11 @@ instance Monoid (Line a) where mappend line EmptyLine = line mappend (Line c1 xs) (Line c2 ys) = Line (c1 || c2) (xs <> ys) +splitDiffByLines :: Diff a Info -> (Int, Int) -> (String, String) -> ([Row (Term a Info)], (Range, Range)) +splitDiffByLines (Free (Annotated annotation syntax)) _ sources = (splitAnnotatedByLines sources (ranges annotation) (categories annotation) syntax, ranges annotation) + where categories (Info _ left, Info _ right) = (left, right) + ranges (Info left _, Info right _) = (left, right) + diffToRows :: Diff a Info -> (Int, Int) -> String -> String -> ([Row HTML], (Range, Range)) diffToRows (Free annotated@(Annotated (Info left _, Info right _) _)) _ before after = (annotatedToRows annotated before after, (left, right)) diffToRows (Pure (Insert term)) (previousIndex, _) _ after = (rowWithInsertedLine <$> afterLines, (Range previousIndex previousIndex, range)) From 7414c09c1873afd5edc3e609b3598ad1e61ab097 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 22:42:27 -0500 Subject: [PATCH 112/259] Compute the rows for child diffs. --- src/Split.hs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Split.hs b/src/Split.hs index fe64cfd75..334804c4e 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -193,6 +193,9 @@ splitAnnotatedByLines sources ranges categories syntax = case syntax of adjoin = reverse . foldl (adjoinRowsBy (openTerm $ fst sources) (openTerm $ snd sources)) [] + childRows constructor (rows, previous) child = let (childRows, childRanges) = splitDiffByLines child previous sources in + (adjoin $ rows ++ contextRows constructor (makeRanges previous (starts childRanges)) categories sources ++ childRows, ends childRanges) + starts (left, right) = (start left, start right) ends (left, right) = (end left, end right) makeRanges (leftStart, rightStart) (leftEnd, rightEnd) = (Range leftStart leftEnd, Range rightStart rightEnd) From 97ec8a2e94eca40a564916a892a1e3ca8b318bbf Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 22:42:58 -0500 Subject: [PATCH 113/259] Compute the rows to the end of the range. --- src/Split.hs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Split.hs b/src/Split.hs index 334804c4e..2ff861e19 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -192,6 +192,8 @@ splitAnnotatedByLines sources ranges categories syntax = case syntax of where contextRows constructor ranges categories sources = zipWithDefaults Row EmptyLine EmptyLine (contextLines constructor (fst ranges) (fst categories) (fst sources)) (contextLines constructor (snd ranges) (snd categories) (snd sources)) adjoin = reverse . foldl (adjoinRowsBy (openTerm $ fst sources) (openTerm $ snd sources)) [] + adjoinChildRows constructor children = let (rows, previous) = foldl (childRows $ constructor mempty) ([], starts ranges) children in + adjoin $ rows ++ contextRows (constructor mempty) (makeRanges previous (ends ranges)) categories sources childRows constructor (rows, previous) child = let (childRows, childRanges) = splitDiffByLines child previous sources in (adjoin $ rows ++ contextRows constructor (makeRanges previous (starts childRanges)) categories sources ++ childRows, ends childRanges) From cdc01b499543508fb95a794c6a29f00b06e982ca Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 22:43:19 -0500 Subject: [PATCH 114/259] Define splitAnnotatedByLines over Indexed diffs. --- src/Split.hs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Split.hs b/src/Split.hs index 2ff861e19..3ae9e9ef7 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -189,6 +189,7 @@ termToLines (Info range categories :< syntax) source = (rows syntax, range) splitAnnotatedByLines :: (String, String) -> (Range, Range) -> (Set.Set Category, Set.Set Category) -> Syntax a (Diff a Info) -> [Row (Term a Info)] splitAnnotatedByLines sources ranges categories syntax = case syntax of Leaf a -> contextRows (Leaf a) ranges categories sources + Indexed children -> adjoinChildRows Indexed children where contextRows constructor ranges categories sources = zipWithDefaults Row EmptyLine EmptyLine (contextLines constructor (fst ranges) (fst categories) (fst sources)) (contextLines constructor (snd ranges) (snd categories) (snd sources)) adjoin = reverse . foldl (adjoinRowsBy (openTerm $ fst sources) (openTerm $ snd sources)) [] From e78f9cdbcff6da3187a5269d89a86111503cb2be Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 22:43:49 -0500 Subject: [PATCH 115/259] Define splitAnnotatedByLines over Fixed diffs. --- src/Split.hs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Split.hs b/src/Split.hs index 3ae9e9ef7..c05ff7bb8 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -190,6 +190,7 @@ splitAnnotatedByLines :: (String, String) -> (Range, Range) -> (Set.Set Category splitAnnotatedByLines sources ranges categories syntax = case syntax of Leaf a -> contextRows (Leaf a) ranges categories sources Indexed children -> adjoinChildRows Indexed children + Fixed children -> adjoinChildRows Fixed children where contextRows constructor ranges categories sources = zipWithDefaults Row EmptyLine EmptyLine (contextLines constructor (fst ranges) (fst categories) (fst sources)) (contextLines constructor (snd ranges) (snd categories) (snd sources)) adjoin = reverse . foldl (adjoinRowsBy (openTerm $ fst sources) (openTerm $ snd sources)) [] From cff017ccddac5e06c5b5c4c33f5c118fc576e8e7 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 22:45:21 -0500 Subject: [PATCH 116/259] Define splitAnnotatedByLines over Keyed diffs. --- src/Split.hs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Split.hs b/src/Split.hs index c05ff7bb8..fc68212bb 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -191,6 +191,7 @@ splitAnnotatedByLines sources ranges categories syntax = case syntax of Leaf a -> contextRows (Leaf a) ranges categories sources Indexed children -> adjoinChildRows Indexed children Fixed children -> adjoinChildRows Fixed children + Keyed children -> adjoinChildRows Keyed children where contextRows constructor ranges categories sources = zipWithDefaults Row EmptyLine EmptyLine (contextLines constructor (fst ranges) (fst categories) (fst sources)) (contextLines constructor (snd ranges) (snd categories) (snd sources)) adjoin = reverse . foldl (adjoinRowsBy (openTerm $ fst sources) (openTerm $ snd sources)) [] From cf13cb6488b2e254a32d06f8cde2a6b5f86d555a Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 22:48:59 -0500 Subject: [PATCH 117/259] Define splitDiffByLines by pattern matching. --- src/Split.hs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Split.hs b/src/Split.hs index fc68212bb..1666465b2 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -130,7 +130,8 @@ instance Monoid (Line a) where mappend (Line c1 xs) (Line c2 ys) = Line (c1 || c2) (xs <> ys) splitDiffByLines :: Diff a Info -> (Int, Int) -> (String, String) -> ([Row (Term a Info)], (Range, Range)) -splitDiffByLines (Free (Annotated annotation syntax)) _ sources = (splitAnnotatedByLines sources (ranges annotation) (categories annotation) syntax, ranges annotation) +splitDiffByLines diff _ sources = case diff of + Free (Annotated annotation syntax) -> (splitAnnotatedByLines sources (ranges annotation) (categories annotation) syntax, ranges annotation) where categories (Info _ left, Info _ right) = (left, right) ranges (Info left _, Info right _) = (left, right) From cea5193999deeb34a63d74545fd60d69f05b0694 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 22:58:12 -0500 Subject: [PATCH 118/259] Define splitDiffByLines over Insert patches. --- src/Split.hs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Split.hs b/src/Split.hs index 1666465b2..56762eb98 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -130,8 +130,10 @@ instance Monoid (Line a) where mappend (Line c1 xs) (Line c2 ys) = Line (c1 || c2) (xs <> ys) splitDiffByLines :: Diff a Info -> (Int, Int) -> (String, String) -> ([Row (Term a Info)], (Range, Range)) -splitDiffByLines diff _ sources = case diff of +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 + (Row EmptyLine <$> lines, (Range prevLeft prevLeft, range)) where categories (Info _ left, Info _ right) = (left, right) ranges (Info left _, Info right _) = (left, right) From c2a754bfa0f2b2319fca918b64c979f83d751459 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 22:59:34 -0500 Subject: [PATCH 119/259] Define splitDiffByLines over Delete patches. --- src/Split.hs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Split.hs b/src/Split.hs index 56762eb98..5bd6781e1 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -134,6 +134,8 @@ 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 (Row EmptyLine <$> lines, (Range prevLeft prevLeft, range)) + Pure (Delete term) -> let (lines, range) = splitTermByLines term (snd sources) in + (flip Row EmptyLine <$> lines, (range, Range prevRight prevRight)) where categories (Info _ left, Info _ right) = (left, right) ranges (Info left _, Info right _) = (left, right) From c471a5e7799b6e3fc7639a61c205dbbb579fee99 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 23:06:18 -0500 Subject: [PATCH 120/259] Correct the source used in the Delete case. --- src/Split.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Split.hs b/src/Split.hs index 5bd6781e1..8736b3c4a 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -134,7 +134,7 @@ 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 (Row EmptyLine <$> lines, (Range prevLeft prevLeft, range)) - Pure (Delete term) -> let (lines, range) = splitTermByLines term (snd sources) in + Pure (Delete term) -> let (lines, range) = splitTermByLines term (fst sources) in (flip Row EmptyLine <$> lines, (range, Range prevRight prevRight)) where categories (Info _ left, Info _ right) = (left, right) ranges (Info left _, Info right _) = (left, right) From c7e5690da4731f4ca95aaa63086a860732499466 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 23:06:27 -0500 Subject: [PATCH 121/259] Define splitDiffByLines over Replace patches. --- src/Split.hs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Split.hs b/src/Split.hs index 8736b3c4a..1b482fc68 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -136,6 +136,9 @@ splitDiffByLines diff (prevLeft, prevRight) sources = case diff of (Row EmptyLine <$> lines, (Range prevLeft prevLeft, range)) Pure (Delete term) -> let (lines, range) = splitTermByLines term (fst sources) in (flip Row EmptyLine <$> lines, (range, Range prevRight prevRight)) + Pure (Replace leftTerm rightTerm) -> let (leftLines, leftRange) = splitTermByLines leftTerm (fst sources) + (rightLines, rightRange) = splitTermByLines rightTerm (snd sources) in + (zipWithDefaults Row EmptyLine EmptyLine leftLines rightLines, (leftRange, rightRange)) where categories (Info _ left, Info _ right) = (left, right) ranges (Info left _, Info right _) = (left, right) From 597fe099bcaadaf911a8a24162d519e7f7c5e8a5 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 23:09:14 -0500 Subject: [PATCH 122/259] Pass an additional open predicate to adjoinRowsBy. --- test/SplitSpec.hs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index 8de15986b..95dcfea02 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -115,24 +115,24 @@ spec = do describe "adjoinRowsBy" $ do prop "is identity on top of no rows" $ - \ a -> adjoinRowsBy openElement [] a == [ a ] + \ a -> adjoinRowsBy openElement openElement [] a == [ a ] prop "appends onto open rows" $ forAll ((arbitrary `suchThat` isOpen) >>= \ a -> (,) a <$> (arbitrary `suchThat` isOpen)) $ \ (a@(Row (Line ac1 as1) (Line bc1 bs1)), b@(Row (Line ac2 as2) (Line bc2 bs2))) -> - adjoinRowsBy openElement [ a ] b `shouldBe` [ Row (Line (ac1 || ac2) $ as1 ++ as2) (Line (bc1 || bc2) $ bs1 ++ bs2) ] + adjoinRowsBy openElement openElement [ a ] b `shouldBe` [ Row (Line (ac1 || ac2) $ as1 ++ as2) (Line (bc1 || bc2) $ bs1 ++ bs2) ] prop "does not append onto closed rows" $ forAll ((arbitrary `suchThat` isClosed) >>= \ a -> (,) a <$> (arbitrary `suchThat` isClosed)) $ - \ (a, b) -> adjoinRowsBy openElement [ a ] b `shouldBe` [ b, a ] + \ (a, b) -> adjoinRowsBy openElement openElement [ a ] b `shouldBe` [ b, a ] prop "does not promote elements through empty lines onto closed lines" $ forAll ((arbitrary `suchThat` isClosed) >>= \ a -> (,) a <$> (arbitrary `suchThat` isClosed)) $ - \ (a, b) -> adjoinRowsBy openElement [ Row EmptyLine EmptyLine, a ] b `shouldBe` [ b, Row EmptyLine EmptyLine, a ] + \ (a, b) -> adjoinRowsBy openElement openElement [ Row EmptyLine EmptyLine, a ] b `shouldBe` [ b, Row EmptyLine EmptyLine, a ] prop "promotes elements through empty lines onto open lines" $ forAll ((arbitrary `suchThat` isOpen) >>= \ a -> (,) a <$> (arbitrary `suchThat` isOpen)) $ - \ (a, b) -> adjoinRowsBy openElement [ Row EmptyLine EmptyLine, a ] b `shouldBe` Row EmptyLine EmptyLine : adjoinRowsBy openElement [ a ] b + \ (a, b) -> adjoinRowsBy openElement openElement [ Row EmptyLine EmptyLine, a ] b `shouldBe` Row EmptyLine EmptyLine : adjoinRowsBy openElement openElement [ a ] b describe "termToLines" $ do it "splits multi-line terms into multiple lines" $ From eb12d72c36937fd643c7a643e8fa5f74441c3630 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 23:42:54 -0500 Subject: [PATCH 123/259] Line is a Functor. --- src/Split.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Split.hs b/src/Split.hs index 1b482fc68..629511c13 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -113,7 +113,7 @@ instance ToMarkup a => ToMarkup (Line a) where data Line a = Line Bool [a] | EmptyLine - deriving Eq + deriving (Eq, Functor) unLine :: Line a -> [a] unLine EmptyLine = [] From b4cd2c14c49491522b1f81930d9982966ff56e48 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Dec 2015 23:42:57 -0500 Subject: [PATCH 124/259] Row is a Functor. --- src/Split.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Split.hs b/src/Split.hs index 629511c13..e0015babf 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -84,7 +84,7 @@ split diff before after = return . renderHtml data Row a = Row { unLeft :: Line a, unRight :: Line a } - deriving Eq + deriving (Eq, Functor) instance Show a => Show (Row a) where show (Row left right) = "\n" ++ show left ++ " | " ++ show right From ffbd9b5b51a12dfaabbed6b5079ddee00694b3fc Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 09:37:41 -0500 Subject: [PATCH 125/259] Add a type synonym for a split diff. --- src/Split.hs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Split.hs b/src/Split.hs index e0015babf..1ff1460d5 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -129,6 +129,9 @@ instance Monoid (Line a) where mappend line EmptyLine = line mappend (Line c1 xs) (Line c2 ys) = Line (c1 || c2) (xs <> ys) +-- | A diff with only one side’s annotations. +type SplitDiff leaf annotation = Free (Annotated leaf annotation) (Patch (Term leaf annotation)) + splitDiffByLines :: Diff a Info -> (Int, Int) -> (String, String) -> ([Row (Term 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) From 3368857e2b69ab80cef8728ed6a2dca13f780a5a Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 09:52:55 -0500 Subject: [PATCH 126/259] Represent `SplitDiff` patches using `Maybe`. --- src/Split.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Split.hs b/src/Split.hs index 1ff1460d5..2aa80303e 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -130,7 +130,7 @@ instance Monoid (Line a) where mappend (Line c1 xs) (Line c2 ys) = Line (c1 || c2) (xs <> ys) -- | A diff with only one side’s annotations. -type SplitDiff leaf annotation = Free (Annotated leaf annotation) (Patch (Term leaf annotation)) +type SplitDiff leaf annotation = Free (Annotated leaf annotation) (Maybe (Term leaf annotation)) splitDiffByLines :: Diff a Info -> (Int, Int) -> (String, String) -> ([Row (Term a Info)], (Range, Range)) splitDiffByLines diff (prevLeft, prevRight) sources = case diff of From b1c5e3e305715178a68fe8ffc967867b6ee628ec Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 09:54:40 -0500 Subject: [PATCH 127/259] Represent `SplitDiff` patches totally. --- src/Split.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Split.hs b/src/Split.hs index 2aa80303e..19eb2716c 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -130,7 +130,7 @@ instance Monoid (Line a) where mappend (Line c1 xs) (Line c2 ys) = Line (c1 || c2) (xs <> ys) -- | A diff with only one side’s annotations. -type SplitDiff leaf annotation = Free (Annotated leaf annotation) (Maybe (Term leaf annotation)) +type SplitDiff leaf annotation = Free (Annotated leaf annotation) (Term leaf annotation) splitDiffByLines :: Diff a Info -> (Int, Int) -> (String, String) -> ([Row (Term a Info)], (Range, Range)) splitDiffByLines diff (prevLeft, prevRight) sources = case diff of From 37dcb3adead701b3d2cda207f36d9ee23cb856c5 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 09:56:11 -0500 Subject: [PATCH 128/259] Define an openDiff function over SplitDiff. --- src/Split.hs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Split.hs b/src/Split.hs index 19eb2716c..d4edf26c6 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -300,6 +300,12 @@ openTerm source term@(Info range _ :< _) = case (source !!) <$> maybeLastIndex r Just '\n' -> Nothing _ -> Just term +openDiff :: String -> SplitDiff a Info -> Maybe (SplitDiff a Info) +openDiff source diff@(Free (Annotated (Info range _) _)) = case (source !!) <$> maybeLastIndex range of + Just '\n' -> Nothing + _ -> Just diff +openDiff source diff@(Pure term) = const diff <$> openTerm source term + openLineBy :: (a -> Maybe a) -> [Line a] -> Maybe (Line a) openLineBy _ [] = Nothing openLineBy f (EmptyLine : rest) = openLineBy f rest From fbe3b8dbeb1d0589f1a0ceb7867f55b852bcbf36 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 09:58:07 -0500 Subject: [PATCH 129/259] Define openTerm & openDiff in terms of an openRange function. --- src/Split.hs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index d4edf26c6..cc5fb42e9 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -295,15 +295,16 @@ openElement (Dl _ elements) = openElement =<< maybeLast elements openElement (Div _ elements) = openElement =<< maybeLast elements openElement h = Just h -openTerm :: String -> Term a Info -> Maybe (Term a Info) -openTerm source term@(Info range _ :< _) = case (source !!) <$> maybeLastIndex range of +openRange :: String -> Range -> Maybe Range +openRange source range = case (source !!) <$> maybeLastIndex range of Just '\n' -> Nothing - _ -> Just term + _ -> Just range + +openTerm :: String -> Term a Info -> Maybe (Term a Info) +openTerm source term@(Info range _ :< _) = const term <$> openRange source range openDiff :: String -> SplitDiff a Info -> Maybe (SplitDiff a Info) -openDiff source diff@(Free (Annotated (Info range _) _)) = case (source !!) <$> maybeLastIndex range of - Just '\n' -> Nothing - _ -> Just diff +openDiff source diff@(Free (Annotated (Info range _) _)) = const diff <$> openRange source range openDiff source diff@(Pure term) = const diff <$> openTerm source term openLineBy :: (a -> Maybe a) -> [Line a] -> Maybe (Line a) From c7a7a7987ed4165a46856287e06b5ba183ca2748 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 10:02:17 -0500 Subject: [PATCH 130/259] splitDiffByLines & splitAnnotatedByLines produce rows of split diffs. --- src/Split.hs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index cc5fb42e9..02ef238ff 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -132,16 +132,16 @@ instance Monoid (Line a) where -- | A diff with only one side’s annotations. type SplitDiff leaf annotation = Free (Annotated leaf annotation) (Term leaf annotation) -splitDiffByLines :: Diff a Info -> (Int, Int) -> (String, String) -> ([Row (Term a Info)], (Range, Range)) +splitDiffByLines :: Diff a Info -> (Int, Int) -> (String, String) -> ([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 - (Row EmptyLine <$> lines, (Range prevLeft prevLeft, range)) + (Row EmptyLine . fmap Pure <$> lines, (Range prevLeft prevLeft, range)) Pure (Delete term) -> let (lines, range) = splitTermByLines term (fst sources) in - (flip Row EmptyLine <$> lines, (range, Range prevRight prevRight)) + (flip Row EmptyLine . fmap Pure <$> lines, (range, Range prevRight prevRight)) Pure (Replace leftTerm rightTerm) -> let (leftLines, leftRange) = splitTermByLines leftTerm (fst sources) (rightLines, rightRange) = splitTermByLines rightTerm (snd sources) in - (zipWithDefaults Row EmptyLine EmptyLine leftLines rightLines, (leftRange, rightRange)) + (zipWithDefaults Row EmptyLine EmptyLine (fmap Pure <$> leftLines) (fmap Pure <$> rightLines), (leftRange, rightRange)) where categories (Info _ left, Info _ right) = (left, right) ranges (Info left _, Info right _) = (left, right) @@ -197,15 +197,16 @@ termToLines (Info range categories :< syntax) source = (rows syntax, range) (adjoin $ lines ++ contextLines (Range previous $ start childRange) source ++ childLines, end childRange) elements = elementAndBreak (Span $ classify categories) =<< actualLines (substring range source) -splitAnnotatedByLines :: (String, String) -> (Range, Range) -> (Set.Set Category, Set.Set Category) -> Syntax a (Diff a Info) -> [Row (Term a Info)] +splitAnnotatedByLines :: (String, String) -> (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 Fixed children -> adjoinChildRows Fixed children Keyed children -> adjoinChildRows Keyed children where contextRows constructor ranges categories sources = zipWithDefaults Row EmptyLine EmptyLine (contextLines constructor (fst ranges) (fst categories) (fst sources)) (contextLines constructor (snd ranges) (snd categories) (snd sources)) + contextLines constructor range categories source = Line True . (:[]) . Free . (`Annotated` constructor) . (`Info` categories) <$> actualLineRanges range source - adjoin = reverse . foldl (adjoinRowsBy (openTerm $ fst sources) (openTerm $ snd sources)) [] + adjoin = reverse . foldl (adjoinRowsBy (openDiff $ fst sources) (openDiff $ snd sources)) [] adjoinChildRows constructor children = let (rows, previous) = foldl (childRows $ constructor mempty) ([], starts ranges) children in adjoin $ rows ++ contextRows (constructor mempty) (makeRanges previous (ends ranges)) categories sources From 37860544acef5d1c1296a009cf997f61288c169f Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 10:09:06 -0500 Subject: [PATCH 131/259] Generalize `contextLines` to return `[Line a]`. --- src/Split.hs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 02ef238ff..b1290d767 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -167,16 +167,16 @@ diffToRows (Pure (Replace a b)) _ before after = (replacedRows, (leftRange, righ -- | Takes a term and a source and returns a list of lines and their range within source. splitTermByLines :: Term a Info -> String -> ([Line (Term a Info)], Range) splitTermByLines (Info range categories :< syntax) source = flip (,) range $ case syntax of - Leaf a -> contextLines (Leaf a) range categories source + Leaf a -> contextLines (:< Leaf a) range categories source Indexed children -> adjoinChildLines Indexed children Fixed children -> adjoinChildLines Fixed children Keyed children -> adjoinChildLines Keyed children where adjoin = reverse . foldl (adjoinLinesBy $ openTerm source) [] adjoinChildLines constructor children = let (lines, previous) = foldl (childLines $ constructor mempty) ([], start range) children in - adjoin $ lines ++ contextLines (constructor mempty) (Range previous $ end range) categories source + adjoin $ lines ++ contextLines (:< constructor mempty) (Range previous $ end range) categories source 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) + (adjoin $ lines ++ contextLines (:< constructor) (Range previous $ start childRange) categories source ++ childLines, end childRange) -- | Takes a term and a source and returns a list of lines and their range within source. termToLines :: Term a Info -> String -> ([Line HTML], Range) @@ -241,8 +241,8 @@ annotatedToRows (Annotated (Info left leftCategories, Info right rightCategories sumRows (rows, previousIndices) child = let (childRows, childRanges) = diffToRows child previousIndices before after in (rows ++ contextRows (starts childRanges) previousIndices sources ++ childRows, ends childRanges) -contextLines :: Syntax a (Term a Info) -> Range -> Set.Set Category -> String -> [Line (Term a Info)] -contextLines constructor range categories source = Line True . (:[]) . (:< constructor) . (`Info` categories) <$> actualLineRanges range source +contextLines :: (Info -> a) -> Range -> Set.Set Category -> String -> [Line a] +contextLines constructor range categories source = Line True . (:[]) . constructor . (`Info` categories) <$> actualLineRanges range source contextRows :: (Int, Int) -> (Int, Int) -> (String, String) -> [Row HTML] contextRows childIndices previousIndices sources = zipWithMaybe rowFromMaybeRows leftElements rightElements From c70eb44f9049717a692eb85ada07349d28089452 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 10:09:26 -0500 Subject: [PATCH 132/259] Use the global `contextLines` function. --- src/Split.hs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index b1290d767..df827bbd5 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -203,8 +203,7 @@ splitAnnotatedByLines sources ranges categories syntax = case syntax of Indexed children -> adjoinChildRows Indexed children Fixed children -> adjoinChildRows Fixed children Keyed children -> adjoinChildRows Keyed children - where contextRows constructor ranges categories sources = zipWithDefaults Row EmptyLine EmptyLine (contextLines constructor (fst ranges) (fst categories) (fst sources)) (contextLines constructor (snd ranges) (snd categories) (snd sources)) - contextLines constructor range categories source = Line True . (:[]) . Free . (`Annotated` constructor) . (`Info` categories) <$> actualLineRanges range source + where contextRows constructor ranges categories sources = zipWithDefaults Row EmptyLine EmptyLine (contextLines (Free . (`Annotated` constructor)) (fst ranges) (fst categories) (fst sources)) (contextLines (Free . (`Annotated` constructor)) (snd ranges) (snd categories) (snd sources)) adjoin = reverse . foldl (adjoinRowsBy (openDiff $ fst sources) (openDiff $ snd sources)) [] adjoinChildRows constructor children = let (rows, previous) = foldl (childRows $ constructor mempty) ([], starts ranges) children in From 6703efceb61d7d8dcd40ae16179de7124d26b8ae Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 10:20:36 -0500 Subject: [PATCH 133/259] Stub in a RenderableSplitDiff type. --- src/Split.hs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Split.hs b/src/Split.hs index df827bbd5..435fb7b2d 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -132,6 +132,8 @@ instance Monoid (Line a) where -- | A diff with only one side’s annotations. type SplitDiff leaf annotation = Free (Annotated leaf annotation) (Term leaf annotation) +newtype RenderableSplitDiff leaf annotation = RenderableSplitDiff (String, SplitDiff leaf annotation) + splitDiffByLines :: Diff a Info -> (Int, Int) -> (String, String) -> ([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) From a04f57303c767bde1e52ade97099ef78b8dff681 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 10:24:37 -0500 Subject: [PATCH 134/259] Reduce `RenderableSplitDiff` to `Renderable`. --- src/Split.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Split.hs b/src/Split.hs index 435fb7b2d..dca6a170b 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -132,7 +132,7 @@ instance Monoid (Line a) where -- | A diff with only one side’s annotations. type SplitDiff leaf annotation = Free (Annotated leaf annotation) (Term leaf annotation) -newtype RenderableSplitDiff leaf annotation = RenderableSplitDiff (String, SplitDiff leaf annotation) +newtype Renderable a = Renderable (String, a) splitDiffByLines :: Diff a Info -> (Int, Int) -> (String, String) -> ([Row (SplitDiff a Info)], (Range, Range)) splitDiffByLines diff (prevLeft, prevRight) sources = case diff of From 8d0db8ed06a47d1f4643274585936b9cd60ad52f Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 10:28:57 -0500 Subject: [PATCH 135/259] Define a ToMarkup instance over Renderable leaf terms. --- src/Split.hs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Split.hs b/src/Split.hs index dca6a170b..bc0d8b294 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -134,6 +134,10 @@ type SplitDiff leaf annotation = Free (Annotated leaf annotation) (Term leaf ann newtype Renderable a = Renderable (String, a) +instance ToMarkup (Renderable (Term a Info)) where + toMarkup (Renderable (source, Info range categories :< syntax)) = case syntax of + Leaf _ -> classifyMarkup (maybeLast categories) . span . string $ substring range source + splitDiffByLines :: Diff a Info -> (Int, Int) -> (String, String) -> ([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) From b4ae80239afd2a9fb98904b956ac457bcab51d39 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 10:41:23 -0500 Subject: [PATCH 136/259] Classify the markup outside of the case expression. --- src/Split.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index bc0d8b294..b0e349e14 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -135,8 +135,8 @@ type SplitDiff leaf annotation = Free (Annotated leaf annotation) (Term leaf ann newtype Renderable a = Renderable (String, a) instance ToMarkup (Renderable (Term a Info)) where - toMarkup (Renderable (source, Info range categories :< syntax)) = case syntax of - Leaf _ -> classifyMarkup (maybeLast categories) . span . string $ substring range source + toMarkup (Renderable (source, Info range categories :< syntax)) = classifyMarkup (maybeLast categories) $ case syntax of + Leaf _ -> span . string $ substring range source splitDiffByLines :: Diff a Info -> (Int, Int) -> (String, String) -> ([Row (SplitDiff a Info)], (Range, Range)) splitDiffByLines diff (prevLeft, prevRight) sources = case diff of From a267cbdd7a78ab64125c3e98db1e07abe52d0830 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 10:52:22 -0500 Subject: [PATCH 137/259] Add a function to get the markup & separator for a given child term. --- src/Split.hs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Split.hs b/src/Split.hs index b0e349e14..3d730af70 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -137,6 +137,9 @@ newtype Renderable a = Renderable (String, a) instance ToMarkup (Renderable (Term a Info)) where toMarkup (Renderable (source, Info range categories :< syntax)) = classifyMarkup (maybeLast categories) $ case syntax of Leaf _ -> span . string $ substring range source + where markupForSeparatorAndChild :: ([Markup], Int) -> Term a Info -> ([Markup], Int) + markupForSeparatorAndChild (rows, previous) child = (rows ++ [ string (substring (Range previous $ start $ getRange child) source), toMarkup (Renderable (source, child)) ], end $ getRange child) + getRange (Info range _ :< _) = range splitDiffByLines :: Diff a Info -> (Int, Int) -> (String, String) -> ([Row (SplitDiff a Info)], (Range, Range)) splitDiffByLines diff (prevLeft, prevRight) sources = case diff of From 1197182f35b65312ff69d221e14d2e5627e6c4ca Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 10:52:36 -0500 Subject: [PATCH 138/259] Define toMarkup over Renderable indexed terms. --- src/Split.hs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Split.hs b/src/Split.hs index 3d730af70..74eb8a35b 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -137,6 +137,8 @@ newtype Renderable a = Renderable (String, a) instance ToMarkup (Renderable (Term a Info)) where toMarkup (Renderable (source, Info range categories :< syntax)) = classifyMarkup (maybeLast categories) $ case syntax of Leaf _ -> span . string $ substring range source + Indexed children -> ul . mconcat $ let (elements, previous) = foldl markupForSeparatorAndChild ([], start range) children in + elements ++ [ string $ substring (Range previous $ end range) source ] where markupForSeparatorAndChild :: ([Markup], Int) -> Term a Info -> ([Markup], Int) markupForSeparatorAndChild (rows, previous) child = (rows ++ [ string (substring (Range previous $ start $ getRange child) source), toMarkup (Renderable (source, child)) ], end $ getRange child) getRange (Info range _ :< _) = range From a0ac63f8b7f818d8911f0dad254b7d21b7cc83f8 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 10:54:31 -0500 Subject: [PATCH 139/259] Extract the handling of the contents into a binding. --- src/Split.hs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 74eb8a35b..f0d5010f5 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -137,10 +137,13 @@ newtype Renderable a = Renderable (String, a) instance ToMarkup (Renderable (Term a Info)) where toMarkup (Renderable (source, Info range categories :< syntax)) = classifyMarkup (maybeLast categories) $ case syntax of Leaf _ -> span . string $ substring range source - Indexed children -> ul . mconcat $ let (elements, previous) = foldl markupForSeparatorAndChild ([], start range) children in - elements ++ [ string $ substring (Range previous $ end range) source ] + Indexed children -> ul . mconcat $ contentElements children where markupForSeparatorAndChild :: ([Markup], Int) -> Term a Info -> ([Markup], Int) markupForSeparatorAndChild (rows, previous) child = (rows ++ [ string (substring (Range previous $ start $ getRange child) source), toMarkup (Renderable (source, child)) ], end $ getRange child) + + contentElements children = let (elements, previous) = foldl markupForSeparatorAndChild ([], start range) children in + elements ++ [ string $ substring (Range previous $ end range) source ] + getRange (Info range _ :< _) = range splitDiffByLines :: Diff a Info -> (Int, Int) -> (String, String) -> ([Row (SplitDiff a Info)], (Range, Range)) From 1bed6a771032254fdefced91dddfe713435f1f2f Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 10:54:54 -0500 Subject: [PATCH 140/259] Define toMarkup over Renderable fixed terms. --- src/Split.hs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Split.hs b/src/Split.hs index f0d5010f5..ba23c284d 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -138,6 +138,7 @@ instance ToMarkup (Renderable (Term a Info)) where toMarkup (Renderable (source, Info range categories :< syntax)) = classifyMarkup (maybeLast categories) $ case syntax of Leaf _ -> span . string $ substring range source Indexed children -> ul . mconcat $ contentElements children + Fixed children -> ul . mconcat $ contentElements children where markupForSeparatorAndChild :: ([Markup], Int) -> Term a Info -> ([Markup], Int) markupForSeparatorAndChild (rows, previous) child = (rows ++ [ string (substring (Range previous $ start $ getRange child) source), toMarkup (Renderable (source, child)) ], end $ getRange child) From 25a524ce22a0f5454c8b48d508ea27ee493b4b16 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 10:55:28 -0500 Subject: [PATCH 141/259] Define toMarkup over Renderable keyed terms. --- src/Split.hs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Split.hs b/src/Split.hs index ba23c284d..f5e886b10 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -139,6 +139,7 @@ instance ToMarkup (Renderable (Term a Info)) where Leaf _ -> span . string $ substring range source Indexed children -> ul . mconcat $ contentElements children Fixed children -> ul . mconcat $ contentElements children + Keyed children -> dl . mconcat $ contentElements children where markupForSeparatorAndChild :: ([Markup], Int) -> Term a Info -> ([Markup], Int) markupForSeparatorAndChild (rows, previous) child = (rows ++ [ string (substring (Range previous $ start $ getRange child) source), toMarkup (Renderable (source, child)) ], end $ getRange child) From eab354c5f9a57347f6fd7f1940a2eb3ab5bacb06 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 10:56:23 -0500 Subject: [PATCH 142/259] Define a ToMarkup instance over Renderable pure SplitDiffs. --- src/Split.hs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Split.hs b/src/Split.hs index f5e886b10..a904b1d20 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -148,6 +148,9 @@ instance ToMarkup (Renderable (Term a Info)) where getRange (Info range _ :< _) = range +instance ToMarkup (Renderable (SplitDiff a Info)) where + toMarkup (Renderable (source, Pure term)) = toMarkup (Renderable (source, term)) + splitDiffByLines :: Diff a Info -> (Int, Int) -> (String, String) -> ([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) From 5e361e75488a50c1a04ca21eb322c9b4881fc145 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 10:58:21 -0500 Subject: [PATCH 143/259] Stub in a definition of toMarkup over Renderable free SplitDiffs. --- src/Split.hs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Split.hs b/src/Split.hs index a904b1d20..5d593eb31 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -150,6 +150,8 @@ instance ToMarkup (Renderable (Term a Info)) where instance ToMarkup (Renderable (SplitDiff a Info)) where toMarkup (Renderable (source, Pure term)) = toMarkup (Renderable (source, term)) + toMarkup (Renderable (source, Free (Annotated (Info range categories) syntax))) = classifyMarkup (maybeLast categories) $ case syntax of + _ -> br splitDiffByLines :: Diff a Info -> (Int, Int) -> (String, String) -> ([Row (SplitDiff a Info)], (Range, Range)) splitDiffByLines diff (prevLeft, prevRight) sources = case diff of From 0c7a59f9c9996b23ac5d12cc2839d329afe021bd Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 11:26:29 -0500 Subject: [PATCH 144/259] Define toMarkup over Renderable ranged syntax. --- src/Split.hs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 5d593eb31..fb8e7de53 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -134,19 +134,18 @@ type SplitDiff leaf annotation = Free (Annotated leaf annotation) (Term leaf ann newtype Renderable a = Renderable (String, a) -instance ToMarkup (Renderable (Term a Info)) where - toMarkup (Renderable (source, Info range categories :< syntax)) = classifyMarkup (maybeLast categories) $ case syntax of +instance ToMarkup f => ToMarkup (Renderable (Info, Syntax a (f, Range))) where + toMarkup (Renderable (source, (Info range categories, syntax))) = classifyMarkup (maybeLast categories) $ case syntax of Leaf _ -> span . string $ substring range source Indexed children -> ul . mconcat $ contentElements children Fixed children -> ul . mconcat $ contentElements children Keyed children -> dl . mconcat $ contentElements children - where markupForSeparatorAndChild :: ([Markup], Int) -> Term a Info -> ([Markup], Int) - markupForSeparatorAndChild (rows, previous) child = (rows ++ [ string (substring (Range previous $ start $ getRange child) source), toMarkup (Renderable (source, child)) ], end $ getRange child) + where markupForSeparatorAndChild :: ToMarkup f => ([Markup], Int) -> (f, Range) -> ([Markup], Int) + markupForSeparatorAndChild (rows, previous) child = (rows ++ [ string (substring (Range previous $ start $ snd child) source), toMarkup $ fst child ], end $ snd child) contentElements children = let (elements, previous) = foldl markupForSeparatorAndChild ([], start range) children in elements ++ [ string $ substring (Range previous $ end range) source ] - getRange (Info range _ :< _) = range instance ToMarkup (Renderable (SplitDiff a Info)) where toMarkup (Renderable (source, Pure term)) = toMarkup (Renderable (source, term)) From 0af18aa16d53c0b829d61f161c83aef5885d60e6 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 11:28:20 -0500 Subject: [PATCH 145/259] Define toMarkup for Renderable terms via the Renderable syntax instance. --- src/Split.hs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Split.hs b/src/Split.hs index fb8e7de53..d2958be61 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -146,6 +146,8 @@ instance ToMarkup f => ToMarkup (Renderable (Info, Syntax a (f, Range))) where contentElements children = let (elements, previous) = foldl markupForSeparatorAndChild ([], start range) children in elements ++ [ string $ substring (Range previous $ end range) source ] +instance ToMarkup (Renderable (Term a Info)) where + toMarkup (Renderable (source, term)) = fst $ cata (\ info@(Info range _) syntax -> (toMarkup $ Renderable (source, (info, syntax)), range)) term instance ToMarkup (Renderable (SplitDiff a Info)) where toMarkup (Renderable (source, Pure term)) = toMarkup (Renderable (source, term)) From ab951a9c6b544e72aaabae7c8f6ae49b1aad0946 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 11:38:19 -0500 Subject: [PATCH 146/259] Define toMarkup over Renderable SplitDiffs by iteration. --- src/Split.hs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index d2958be61..cd14569f8 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -150,9 +150,9 @@ instance ToMarkup (Renderable (Term a Info)) where toMarkup (Renderable (source, term)) = fst $ cata (\ info@(Info range _) syntax -> (toMarkup $ Renderable (source, (info, syntax)), range)) term instance ToMarkup (Renderable (SplitDiff a Info)) where - toMarkup (Renderable (source, Pure term)) = toMarkup (Renderable (source, term)) - toMarkup (Renderable (source, Free (Annotated (Info range categories) syntax))) = classifyMarkup (maybeLast categories) $ case syntax of - _ -> br + toMarkup (Renderable (source, diff)) = fst $ iter (\ (Annotated info@(Info range _) syntax) -> (toMarkup $ Renderable (source, (info, syntax)), range)) $ toMarkupAndRange <$> diff + where toMarkupAndRange :: Term a Info -> (Markup, Range) + toMarkupAndRange term@(Info range _ :< _) = (toMarkup $ Renderable (source, term), range) splitDiffByLines :: Diff a Info -> (Int, Int) -> (String, String) -> ([Row (SplitDiff a Info)], (Range, Range)) splitDiffByLines diff (prevLeft, prevRight) sources = case diff of From d0460f8792d680b41158b79558a1a5f6e63fe823 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 11:41:14 -0500 Subject: [PATCH 147/259] Wrap patches in a div. --- src/Split.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Split.hs b/src/Split.hs index cd14569f8..39e413c55 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -152,7 +152,7 @@ instance ToMarkup (Renderable (Term a Info)) where instance ToMarkup (Renderable (SplitDiff a Info)) where toMarkup (Renderable (source, diff)) = fst $ iter (\ (Annotated info@(Info range _) syntax) -> (toMarkup $ Renderable (source, (info, syntax)), range)) $ toMarkupAndRange <$> diff where toMarkupAndRange :: Term a Info -> (Markup, Range) - toMarkupAndRange term@(Info range _ :< _) = (toMarkup $ Renderable (source, term), range) + toMarkupAndRange term@(Info range _ :< _) = ((div ! A.class_ (stringValue "patch")) . toMarkup $ Renderable (source, term), range) splitDiffByLines :: Diff a Info -> (Int, Int) -> (String, String) -> ([Row (SplitDiff a Info)], (Range, Range)) splitDiffByLines diff (prevLeft, prevRight) sources = case diff of From a72e6b868fd48c6e2f171a18e38fcc03fa48be43 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 12:14:26 -0500 Subject: [PATCH 148/259] Split into rows. --- src/Split.hs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Split.hs b/src/Split.hs index 39e413c55..007ae69e4 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -61,6 +61,7 @@ split diff before after = return . renderHtml . mconcat $ toMarkup <$> reverse numbered where rows = fst $ diffToRows diff (0, 0) before after + rows' = fst $ splitDiffByLines diff (0, 0) (before, after) numbered = foldl numberRows [] rows maxNumber = case numbered of [] -> 0 From b76be23b6ee7b10be1502853bf2543486eda3376 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 12:22:00 -0500 Subject: [PATCH 149/259] Map rows into renderables. --- src/Split.hs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Split.hs b/src/Split.hs index 007ae69e4..0e51ea9b0 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -61,7 +61,8 @@ split diff before after = return . renderHtml . mconcat $ toMarkup <$> reverse numbered where rows = fst $ diffToRows diff (0, 0) before after - rows' = fst $ splitDiffByLines diff (0, 0) (before, after) + rows' = toRenderable <$> fst (splitDiffByLines diff (0, 0) (before, after)) + toRenderable (Row a b) = Row (Renderable . (,) before <$> a) (Renderable . (,) after <$> b) numbered = foldl numberRows [] rows maxNumber = case numbered of [] -> 0 From fc053ffa13da3830d6d10f84ecab5cbf1476a819 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 12:26:43 -0500 Subject: [PATCH 150/259] Replace the old row rendering with the new row rendering. --- src/Split.hs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 0e51ea9b0..103adfd1a 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -60,8 +60,7 @@ split diff before after = return . renderHtml ((colgroup $ (col ! A.width (stringValue . show $ columnWidth)) <> col <> (col ! A.width (stringValue . show $ columnWidth)) <> col) <>) . mconcat $ toMarkup <$> reverse numbered where - rows = fst $ diffToRows diff (0, 0) before after - rows' = toRenderable <$> fst (splitDiffByLines diff (0, 0) (before, after)) + rows = toRenderable <$> fst (splitDiffByLines diff (0, 0) (before, after)) toRenderable (Row a b) = Row (Renderable . (,) before <$> a) (Renderable . (,) after <$> b) numbered = foldl numberRows [] rows maxNumber = case numbered of From 3b3a62a77725bcd68fa0cf79c245c844310b1c53 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 12:39:54 -0500 Subject: [PATCH 151/259] Test that single-line leaves are split correctly. --- test/SplitSpec.hs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index 95dcfea02..9cf2e2afa 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -30,6 +30,13 @@ instance Arbitrary a => Arbitrary (Line a) where spec :: Spec spec = do + describe "splitAnnotatedByLines" $ do + it "outputs one row for single-line unchanged leaves" $ + let sources = ("a", "a") + ranges = (Range 0 1, Range 0 1) + categories = (mempty, mempty) in + splitAnnotatedByLines sources ranges categories (Leaf "b") `shouldBe` [ Row (Line False [ Free $ Annotated (Info (fst ranges) (fst categories)) $ Leaf "b" ]) (Line False [ Free $ Annotated (Info (snd ranges) (snd categories)) $ Leaf "b" ]) ] + describe "annotatedToRows" $ do it "outputs one row for single-line unchanged leaves" $ annotatedToRows (unchanged "a" "leaf" (Leaf "")) "a" "a" `shouldBe` [ Row (Line False [ span "a" ]) (Line False [ span "a" ]) ] From fbe899be217f34711e92fb310e6b59eb58636559 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 12:47:12 -0500 Subject: [PATCH 152/259] Remove the changed flag from `Line`. --- src/Split.hs | 48 +++++++++++++------------- test/SplitSpec.hs | 86 +++++++++++++++++++++++------------------------ 2 files changed, 67 insertions(+), 67 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 103adfd1a..5e5bf888a 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -75,12 +75,12 @@ split diff before after = return . renderHtml numberRows :: [(Int, Line a, Int, Line a)] -> Row a -> [(Int, Line a, Int, Line a)] numberRows [] (Row EmptyLine EmptyLine) = [] - numberRows [] (Row left@(Line _ _) EmptyLine) = [(1, left, 0, EmptyLine)] - numberRows [] (Row EmptyLine right@(Line _ _)) = [(0, EmptyLine, 1, right)] + numberRows [] (Row left@(Line _) EmptyLine) = [(1, left, 0, EmptyLine)] + numberRows [] (Row EmptyLine right@(Line _)) = [(0, EmptyLine, 1, right)] numberRows [] (Row left right) = [(1, left, 1, right)] numberRows rows@((leftCount, _, rightCount, _):_) (Row EmptyLine EmptyLine) = (leftCount, EmptyLine, rightCount, EmptyLine):rows - numberRows rows@((leftCount, _, rightCount, _):_) (Row left@(Line _ _) EmptyLine) = (leftCount + 1, left, rightCount, EmptyLine):rows - numberRows rows@((leftCount, _, rightCount, _):_) (Row EmptyLine right@(Line _ _)) = (leftCount, EmptyLine, rightCount + 1, right):rows + numberRows rows@((leftCount, _, rightCount, _):_) (Row left@(Line _) EmptyLine) = (leftCount + 1, left, rightCount, EmptyLine):rows + numberRows rows@((leftCount, _, rightCount, _):_) (Row EmptyLine right@(Line _)) = (leftCount, EmptyLine, rightCount + 1, right):rows numberRows rows@((leftCount, _, rightCount, _):_) (Row left right) = (leftCount + 1, left, rightCount + 1, right):rows @@ -95,40 +95,40 @@ instance ToMarkup a => ToMarkup (Int, Line a, Int, Line a) where instance ToMarkup a => ToMarkup (Int, Line a) where toMarkup (_, line@EmptyLine) = numberTd "" <> toMarkup line <> string "\n" - toMarkup (num, line@(Line True _)) = td (string $ show num) ! A.class_ (stringValue "blob-num blob-num-replacement") <> toMarkup line <> string "\n" - toMarkup (num, line@(Line _ _)) = numberTd (show num) <> toMarkup line <> string "\n" + -- toMarkup (num, line@(Line _)) = td (string $ show num) ! A.class_ (stringValue "blob-num blob-num-replacement") <> toMarkup line <> string "\n" + toMarkup (num, line@(Line _)) = numberTd (show num) <> toMarkup line <> string "\n" numberTd :: String -> Html numberTd "" = td mempty ! A.class_ (stringValue "blob-num blob-num-empty empty-cell") numberTd s = td (string s) ! A.class_ (stringValue "blob-num") -codeTd :: Bool -> Maybe Html -> Html -codeTd _ Nothing = td mempty ! A.class_ (stringValue "blob-code blob-code-empty empty-cell") -codeTd True (Just el) = td el ! A.class_ (stringValue "blob-code blob-code-replacement") -codeTd _ (Just el) = td el ! A.class_ (stringValue "blob-code") +codeTd :: Maybe Html -> Html +codeTd Nothing = td mempty ! A.class_ (stringValue "blob-code blob-code-empty empty-cell") +-- codeTd True (Just el) = td el ! A.class_ (stringValue "blob-code blob-code-replacement") +codeTd (Just el) = td el ! A.class_ (stringValue "blob-code") instance ToMarkup a => ToMarkup (Line a) where - toMarkup EmptyLine = codeTd False Nothing - toMarkup (Line changed html) = codeTd changed . Just . mconcat $ toMarkup <$> html + toMarkup EmptyLine = codeTd Nothing + toMarkup (Line html) = codeTd . Just . mconcat $ toMarkup <$> html data Line a = - Line Bool [a] + Line [a] | EmptyLine deriving (Eq, Functor) unLine :: Line a -> [a] unLine EmptyLine = [] -unLine (Line _ elements) = elements +unLine (Line elements) = elements instance Show a => Show (Line a) where - show (Line change elements) = show change ++ " [" ++ intercalate ", " (show <$> elements) ++ "]" + show (Line elements) = "[" ++ intercalate ", " (show <$> elements) ++ "]" show EmptyLine = "EmptyLine" instance Monoid (Line a) where mempty = EmptyLine mappend EmptyLine line = line mappend line EmptyLine = line - mappend (Line c1 xs) (Line c2 ys) = Line (c1 || c2) (xs <> ys) + mappend (Line xs) (Line ys) = Line (xs <> ys) -- | A diff with only one side’s annotations. type SplitDiff leaf annotation = Free (Annotated leaf annotation) (Term leaf annotation) @@ -173,12 +173,12 @@ diffToRows (Free annotated@(Annotated (Info left _, Info right _) _)) _ before a diffToRows (Pure (Insert term)) (previousIndex, _) _ after = (rowWithInsertedLine <$> afterLines, (Range previousIndex previousIndex, range)) where (afterLines, range) = termToLines term after - rowWithInsertedLine (Line _ elements) = Row EmptyLine $ Line True [ Div (Just "insert") elements ] + rowWithInsertedLine (Line elements) = Row EmptyLine $ Line [ Div (Just "insert") elements ] rowWithInsertedLine line = Row line line diffToRows (Pure (Delete term)) (_, previousIndex) before _ = (rowWithDeletedLine <$> lines, (range, Range previousIndex previousIndex)) where (lines, range) = termToLines term before - rowWithDeletedLine (Line _ elements) = Row (Line True [ Div (Just "delete") elements ]) EmptyLine + rowWithDeletedLine (Line elements) = Row (Line [ Div (Just "delete") elements ]) EmptyLine rowWithDeletedLine line = Row line line diffToRows (Pure (Replace a b)) _ before after = (replacedRows, (leftRange, rightRange)) where @@ -205,15 +205,15 @@ splitTermByLines (Info range categories :< syntax) source = flip (,) range $ cas termToLines :: Term a Info -> String -> ([Line HTML], Range) termToLines (Info range categories :< syntax) source = (rows syntax, range) where - rows (Leaf _) = adjoin $ Line True . (:[]) <$> elements + rows (Leaf _) = adjoin $ Line . (:[]) <$> elements rows (Indexed i) = rewrapLineContentsIn (Ul $ classify categories) <$> childLines i rows (Fixed f) = rewrapLineContentsIn (Ul $ classify categories) <$> childLines f rows (Keyed k) = rewrapLineContentsIn (Dl $ classify categories) <$> childLines k adjoin = reverse . foldl (adjoinLinesBy openElement) [] - rewrapLineContentsIn f (Line _ elements) = Line True [ f elements ] + rewrapLineContentsIn f (Line elements) = Line [ f elements ] rewrapLineContentsIn _ EmptyLine = EmptyLine - contextLines r s = Line True . (:[]) <$> textElements r s + contextLines r s = Line . (:[]) <$> textElements r s childLines i = let (lines, previous) = foldl sumLines ([], start range) i in adjoin $ lines ++ contextLines (Range previous (end range)) source sumLines (lines, previous) child = let (childLines, childRange) = termToLines child source in @@ -252,7 +252,7 @@ annotatedToRows (Annotated (Info left leftCategories, Info right rightCategories rightElements = elementAndBreak (Span $ classify rightCategories) =<< actualLines (substring right after) wrap _ EmptyLine = EmptyLine - wrap f (Line c elements) = Line c [ f elements ] + wrap f (Line elements) = Line [ f elements ] rewrapRowContentsIn f (Row left right) = Row (wrap (f $ classify leftCategories) left) (wrap (f $ classify rightCategories) right) ranges = (left, right) sources = (before, after) @@ -264,7 +264,7 @@ annotatedToRows (Annotated (Info left leftCategories, Info right rightCategories (rows ++ contextRows (starts childRanges) previousIndices sources ++ childRows, ends childRanges) contextLines :: (Info -> a) -> Range -> Set.Set Category -> String -> [Line a] -contextLines constructor range categories source = Line True . (:[]) . constructor . (`Info` categories) <$> actualLineRanges range source +contextLines constructor range categories source = Line . (:[]) . constructor . (`Info` categories) <$> actualLineRanges range source contextRows :: (Int, Int) -> (Int, Int) -> (String, String) -> [Row HTML] contextRows childIndices previousIndices sources = zipWithMaybe rowFromMaybeRows leftElements rightElements @@ -283,7 +283,7 @@ textElements range source = elementAndBreak Text =<< actualLines s where s = substring range source rowFromMaybeRows :: Maybe a -> Maybe a -> Row a -rowFromMaybeRows a b = Row (maybe EmptyLine (Line False . (:[])) a) (maybe EmptyLine (Line False . (:[])) b) +rowFromMaybeRows a b = Row (maybe EmptyLine (Line . (:[])) a) (maybe EmptyLine (Line . (:[])) b) maybeLast :: Foldable f => f a -> Maybe a maybeLast = foldl (flip $ const . Just) Nothing diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index 9cf2e2afa..7ee809fe6 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -25,7 +25,7 @@ instance Arbitrary HTML where instance Arbitrary a => Arbitrary (Line a) where arbitrary = oneof [ - Line <$> arbitrary <*> arbitrary, + Line <$> arbitrary, const EmptyLine <$> (arbitrary :: Gen ()) ] spec :: Spec @@ -35,26 +35,26 @@ spec = do let sources = ("a", "a") ranges = (Range 0 1, Range 0 1) categories = (mempty, mempty) in - splitAnnotatedByLines sources ranges categories (Leaf "b") `shouldBe` [ Row (Line False [ Free $ Annotated (Info (fst ranges) (fst categories)) $ Leaf "b" ]) (Line False [ Free $ Annotated (Info (snd ranges) (snd categories)) $ Leaf "b" ]) ] + splitAnnotatedByLines sources ranges categories (Leaf "b") `shouldBe` [ Row (Line [ Free $ Annotated (Info (fst ranges) (fst categories)) $ Leaf "b" ]) (Line [ Free $ Annotated (Info (snd ranges) (snd categories)) $ Leaf "b" ]) ] describe "annotatedToRows" $ do it "outputs one row for single-line unchanged leaves" $ - annotatedToRows (unchanged "a" "leaf" (Leaf "")) "a" "a" `shouldBe` [ Row (Line False [ span "a" ]) (Line False [ span "a" ]) ] + annotatedToRows (unchanged "a" "leaf" (Leaf "")) "a" "a" `shouldBe` [ Row (Line [ span "a" ]) (Line [ span "a" ]) ] it "outputs one row for single-line empty unchanged indexed nodes" $ - annotatedToRows (unchanged "[]" "branch" (Indexed [])) "[]" "[]" `shouldBe` [ Row (Line False [ Ul (Just "category-branch") [ Text "[]" ] ]) (Line False [ Ul (Just "category-branch") [ Text "[]" ] ]) ] + annotatedToRows (unchanged "[]" "branch" (Indexed [])) "[]" "[]" `shouldBe` [ Row (Line [ Ul (Just "category-branch") [ Text "[]" ] ]) (Line [ Ul (Just "category-branch") [ Text "[]" ] ]) ] it "outputs one row for single-line non-empty unchanged indexed nodes" $ annotatedToRows (unchanged "[ a, b ]" "branch" (Indexed [ Free . offsetAnnotated 2 2 $ unchanged "a" "leaf" (Leaf ""), Free . offsetAnnotated 5 5 $ unchanged "b" "leaf" (Leaf "") - ])) "[ a, b ]" "[ a, b ]" `shouldBe` [ Row (Line False [ Ul (Just "category-branch") [ Text "[ ", span "a", Text ", ", span "b", Text " ]" ] ]) (Line False [ Ul (Just "category-branch") [ Text "[ ", span "a", Text ", ", span "b", Text " ]" ] ]) ] + ])) "[ a, b ]" "[ a, b ]" `shouldBe` [ Row (Line [ Ul (Just "category-branch") [ Text "[ ", span "a", Text ", ", span "b", Text " ]" ] ]) (Line [ Ul (Just "category-branch") [ Text "[ ", span "a", Text ", ", span "b", Text " ]" ] ]) ] it "outputs one row for single-line non-empty formatted indexed nodes" $ annotatedToRows (formatted "[ a, b ]" "[ a, b ]" "branch" (Indexed [ Free . offsetAnnotated 2 2 $ unchanged "a" "leaf" (Leaf ""), Free . offsetAnnotated 5 6 $ unchanged "b" "leaf" (Leaf "") - ])) "[ a, b ]" "[ a, b ]" `shouldBe` [ Row (Line False [ Ul (Just "category-branch") [ Text "[ ", span "a", Text ", ", span "b", Text " ]" ] ]) (Line False [ Ul (Just "category-branch") [ Text "[ ", span "a", Text ", ", span "b", Text " ]" ] ]) ] + ])) "[ a, b ]" "[ a, b ]" `shouldBe` [ Row (Line [ Ul (Just "category-branch") [ Text "[ ", span "a", Text ", ", span "b", Text " ]" ] ]) (Line [ Ul (Just "category-branch") [ Text "[ ", span "a", Text ", ", span "b", Text " ]" ] ]) ] it "outputs two rows for two-line non-empty unchanged indexed nodes" $ annotatedToRows (unchanged "[ a,\nb ]" "branch" (Indexed [ @@ -62,10 +62,10 @@ spec = do Free . offsetAnnotated 5 5 $ unchanged "b" "leaf" (Leaf "") ])) "[ a,\nb ]" "[ a,\nb ]" `shouldBe` [ - Row (Line False [ Ul (Just "category-branch") [ Text "[ ", span "a", Text ",", Break ] ]) - (Line False [ Ul (Just "category-branch") [ Text "[ ", span "a", Text ",", Break] ]), - Row (Line False [ Ul (Just "category-branch") [ span "b", Text " ]" ] ]) - (Line False [ Ul (Just "category-branch") [ span "b", Text " ]" ] ]) + Row (Line [ Ul (Just "category-branch") [ Text "[ ", span "a", Text ",", Break ] ]) + (Line [ Ul (Just "category-branch") [ Text "[ ", span "a", Text ",", Break] ]), + Row (Line [ Ul (Just "category-branch") [ span "b", Text " ]" ] ]) + (Line [ Ul (Just "category-branch") [ span "b", Text " ]" ] ]) ] it "outputs two rows for two-line non-empty formatted indexed nodes" $ @@ -74,12 +74,12 @@ spec = do Free . offsetAnnotated 5 5 $ unchanged "b" "leaf" (Leaf "") ])) "[ a,\nb ]" "[\na,\nb ]" `shouldBe` [ - Row (Line False [ Ul (Just "category-branch") [ Text "[ ", span "a", Text ",", Break ] ]) - (Line False [ Ul (Just "category-branch") [ Text "[", Break ] ]), + Row (Line [ Ul (Just "category-branch") [ Text "[ ", span "a", Text ",", Break ] ]) + (Line [ Ul (Just "category-branch") [ Text "[", Break ] ]), Row EmptyLine - (Line False [ Ul (Just "category-branch") [ span "a", Text ",", Break ] ]), - Row (Line False [ Ul (Just "category-branch") [ span "b", Text " ]" ] ]) - (Line False [ Ul (Just "category-branch") [ span "b", Text " ]" ] ]) + (Line [ Ul (Just "category-branch") [ span "a", Text ",", Break ] ]), + Row (Line [ Ul (Just "category-branch") [ span "b", Text " ]" ] ]) + (Line [ Ul (Just "category-branch") [ span "b", Text " ]" ] ]) ] it "" $ @@ -89,13 +89,13 @@ spec = do Free . offsetAnnotated 6 3 $ unchanged "b" "leaf" (Leaf "") ])) sourceA sourceB `shouldBe` [ - Row (Line False [ Ul (Just "category-branch") [ Text "[", Break ] ]) - (Line False [ Ul (Just "category-branch") [ Text "[", span "a", Text ",", span "b", Text "]" ] ]), - Row (Line False [ Ul (Just "category-branch") [ span "a", Break ] ]) + Row (Line [ Ul (Just "category-branch") [ Text "[", Break ] ]) + (Line [ Ul (Just "category-branch") [ Text "[", span "a", Text ",", span "b", Text "]" ] ]), + Row (Line [ Ul (Just "category-branch") [ span "a", Break ] ]) EmptyLine, - Row (Line False [ Ul (Just "category-branch") [ Text ",", Break ] ]) + Row (Line [ Ul (Just "category-branch") [ Text ",", Break ] ]) EmptyLine, - Row (Line False [ Ul (Just "category-branch") [ span "b", Text "]" ] ]) + Row (Line [ Ul (Just "category-branch") [ span "b", Text "]" ] ]) EmptyLine ] @@ -106,9 +106,9 @@ spec = do Free . offsetAnnotated 6 0 $ unchanged "a" "leaf" (Leaf "") ])) sourceA sourceB `shouldBe` [ - Row (Line True [ Ul (Just "category-branch") [ Div (Just "delete") [ span "/*", Break ] ] ]) EmptyLine, - Row (Line True [ Ul (Just "category-branch") [ Div (Just "delete") [ span "*/" ], Break ] ]) EmptyLine, - Row (Line False [ Ul (Just "category-branch") [ span "a" ] ]) (Line False [ Ul (Just "category-branch") [ span "a" ] ]) + Row (Line [ Ul (Just "category-branch") [ Div (Just "delete") [ span "/*", Break ] ] ]) EmptyLine, + Row (Line [ Ul (Just "category-branch") [ Div (Just "delete") [ span "*/" ], Break ] ]) EmptyLine, + Row (Line [ Ul (Just "category-branch") [ span "a" ] ]) (Line [ Ul (Just "category-branch") [ span "a" ] ]) ] describe "unicode" $ @@ -117,7 +117,7 @@ spec = do syntax = Leaf . Pure $ Replace (info sourceA "leaf" :< Leaf "") (info sourceB "leaf" :< Leaf "") in annotatedToRows (formatted sourceA sourceB "leaf" syntax) sourceA sourceB `shouldBe` - [ Row (Line False [ span "t\776" ]) (Line False [ span "\7831"]) ] + [ Row (Line [ span "t\776" ]) (Line [ span "\7831"]) ] describe "adjoinRowsBy" $ do @@ -126,8 +126,8 @@ spec = do prop "appends onto open rows" $ forAll ((arbitrary `suchThat` isOpen) >>= \ a -> (,) a <$> (arbitrary `suchThat` isOpen)) $ - \ (a@(Row (Line ac1 as1) (Line bc1 bs1)), b@(Row (Line ac2 as2) (Line bc2 bs2))) -> - adjoinRowsBy openElement openElement [ a ] b `shouldBe` [ Row (Line (ac1 || ac2) $ as1 ++ as2) (Line (bc1 || bc2) $ bs1 ++ bs2) ] + \ (a@(Row (Line a1) (Line b1)), b@(Row (Line a2) (Line b2))) -> + adjoinRowsBy openElement openElement [ a ] b `shouldBe` [ Row (Line $ a1 ++ a2) (Line $ b1 ++ b2) ] prop "does not append onto closed rows" $ forAll ((arbitrary `suchThat` isClosed) >>= \ a -> (,) a <$> (arbitrary `suchThat` isClosed)) $ @@ -146,8 +146,8 @@ spec = do termToLines (Info (Range 0 5) (Set.singleton "leaf") :< Leaf "") "/*\n*/" `shouldBe` ([ - Line True [ span "/*", Break ], - Line True [ span "*/" ] + Line [ span "/*", Break ], + Line [ span "*/" ] ], Range 0 5) describe "splitTermByLines" $ do @@ -155,32 +155,32 @@ spec = do splitTermByLines (Info (Range 0 5) mempty :< Leaf "") "/*\n*/" `shouldBe` ([ - Line True [ Info (Range 0 3) mempty :< Leaf "" ], - Line True [ Info (Range 3 5) mempty :< Leaf "" ] + Line [ Info (Range 0 3) mempty :< Leaf "" ], + Line [ Info (Range 3 5) mempty :< Leaf "" ] ], Range 0 5) describe "openLineBy" $ do it "produces the earliest non-empty line in a list, if open" $ openLineBy openElement [ - Line True [ Div (Just "delete") [ span "*/" ] ], - Line True [ Div (Just "delete") [ span " * Debugging", Break ] ], - Line True [ Div (Just "delete") [ span "/*", Break ] ] - ] `shouldBe` (Just $ Line True [ Div (Just "delete") [ span "*/" ] ]) + Line [ Div (Just "delete") [ span "*/" ] ], + Line [ Div (Just "delete") [ span " * Debugging", Break ] ], + Line [ Div (Just "delete") [ span "/*", Break ] ] + ] `shouldBe` (Just $ Line [ Div (Just "delete") [ span "*/" ] ]) it "produces the earliest non-empty line in a list, if open" $ openLineBy (openTerm "\n ") [ - Line True [ Info (Range 1 2) mempty :< Leaf "" ], - Line True [ Info (Range 0 1) mempty :< Leaf "" ] - ] `shouldBe` (Just $ Line True [ Info (Range 1 2) mempty :< Leaf "" ]) + Line [ Info (Range 1 2) mempty :< Leaf "" ], + Line [ Info (Range 0 1) mempty :< Leaf "" ] + ] `shouldBe` (Just $ Line [ Info (Range 1 2) mempty :< Leaf "" ]) it "returns Nothing if the earliest non-empty line is closed" $ openLineBy openElement [ - Line True [ Div (Just "delete") [ span " * Debugging", Break ] ] + Line [ Div (Just "delete") [ span " * Debugging", Break ] ] ] `shouldBe` Nothing it "returns Nothing if the earliest non-empty line is closed" $ openLineBy (openTerm "\n") [ - Line True [ Info (Range 0 1) mempty :< Leaf "" ] + Line [ Info (Range 0 1) mempty :< Leaf "" ] ] `shouldBe` Nothing describe "openTerm" $ do @@ -192,10 +192,10 @@ spec = do where rightRowText text = rightRow [ Text text ] - rightRow xs = Row EmptyLine (Line False xs) + rightRow xs = Row EmptyLine (Line xs) leftRowText text = leftRow [ Text text ] - leftRow xs = Row (Line False xs) EmptyLine - rowText a b = Row (Line False [ Text a ]) (Line False [ Text b ]) + leftRow xs = Row (Line xs) EmptyLine + rowText a b = Row (Line [ Text a ]) (Line [ Text b ]) info source category = Info (totalRange source) (Set.fromList [ category ]) unchanged source = formatted source source formatted source1 source2 category = Annotated (info source1 category, info source2 category) @@ -203,5 +203,5 @@ spec = do offsetAnnotated by1 by2 (Annotated (left, right) syntax) = Annotated (offsetInfo by1 left, offsetInfo by2 right) syntax span = Span (Just "category-leaf") isOpen (Row a b) = Maybe.isJust (openLineBy openElement [ a ]) && Maybe.isJust (openLineBy openElement [ b ]) - isClosed (Row a@(Line _ _) b@(Line _ _)) = Maybe.isNothing (openLineBy openElement [ a ]) && Maybe.isNothing (openLineBy openElement [ b ]) + isClosed (Row a@(Line _) b@(Line _)) = Maybe.isNothing (openLineBy openElement [ a ]) && Maybe.isNothing (openLineBy openElement [ b ]) isClosed (Row _ _) = False From 38a317156b6dfcbd0400eb4ca422a68dfec78c8a Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 12:53:31 -0500 Subject: [PATCH 153/259] Move arbitrary term generation into its own module. --- semantic-diff.cabal | 1 + test/ArbitraryTerm.hs | 47 +++++++++++++++++++++++++++++++++++++++++++ test/TermSpec.hs | 42 +------------------------------------- 3 files changed, 49 insertions(+), 41 deletions(-) create mode 100644 test/ArbitraryTerm.hs diff --git a/semantic-diff.cabal b/semantic-diff.cabal index e123f0616..1bd11f497 100644 --- a/semantic-diff.cabal +++ b/semantic-diff.cabal @@ -77,6 +77,7 @@ test-suite semantic-diff-test type: exitcode-stdio-1.0 hs-source-dirs: test main-is: Spec.hs + other-modules: ArbitraryTerm build-depends: base , containers , free diff --git a/test/ArbitraryTerm.hs b/test/ArbitraryTerm.hs new file mode 100644 index 000000000..a91221bcc --- /dev/null +++ b/test/ArbitraryTerm.hs @@ -0,0 +1,47 @@ +module ArbitraryTerm where + +import Categorizable +import Syntax +import Term +import Control.Comonad.Cofree +import Control.Monad +import qualified OrderedMap as Map +import qualified Data.List as List +import qualified Data.Set as Set +import GHC.Generics +import Test.QuickCheck hiding (Fixed) + +newtype ArbitraryTerm a annotation = ArbitraryTerm (annotation, (Syntax a (ArbitraryTerm a annotation))) + deriving (Show, Eq, Generic) + +unTerm :: ArbitraryTerm a annotation -> Term a annotation +unTerm = unfold unpack + where unpack (ArbitraryTerm (annotation, syntax)) = (annotation, syntax) + +instance (Eq a, Eq annotation, Arbitrary a, Arbitrary annotation) => Arbitrary (ArbitraryTerm a annotation) where + arbitrary = sized (\ x -> boundedTerm x x) -- first indicates the cube of the max length of lists, second indicates the cube of the max depth of the tree + where boundedTerm maxLength maxDepth = ArbitraryTerm <$> ((,) <$> arbitrary <*> boundedSyntax maxLength maxDepth) + boundedSyntax _ maxDepth | maxDepth <= 0 = liftM Leaf arbitrary + boundedSyntax maxLength maxDepth = frequency + [ (12, liftM Leaf arbitrary), + (1, liftM Indexed $ take maxLength <$> listOf (smallerTerm maxLength maxDepth)), + (1, liftM Fixed $ take maxLength <$> listOf (smallerTerm maxLength maxDepth)), + (1, liftM (Keyed . Map.fromList) $ take maxLength <$> listOf (arbitrary >>= (\x -> ((,) x) <$> smallerTerm maxLength maxDepth))) ] + smallerTerm maxLength maxDepth = boundedTerm (div maxLength 3) (div maxDepth 3) + shrink term@(ArbitraryTerm (annotation, syntax)) = (++) (subterms term) $ filter (/= term) $ + ArbitraryTerm <$> ((,) <$> shrink annotation <*> case syntax of + Leaf a -> Leaf <$> shrink a + Indexed i -> Indexed <$> (List.subsequences i >>= recursivelyShrink) + Fixed f -> Fixed <$> (List.subsequences f >>= recursivelyShrink) + Keyed k -> Keyed . Map.fromList <$> (List.subsequences (Map.toList k) >>= recursivelyShrink)) + +data CategorySet = A | B | C | D deriving (Eq, Show) + +instance Categorizable CategorySet where + categories A = Set.fromList [ "a" ] + categories B = Set.fromList [ "b" ] + categories C = Set.fromList [ "c" ] + categories D = Set.fromList [ "d" ] + +instance Arbitrary CategorySet where + arbitrary = elements [ A, B, C, D ] diff --git a/test/TermSpec.hs b/test/TermSpec.hs index 26e7dc582..c806198a1 100644 --- a/test/TermSpec.hs +++ b/test/TermSpec.hs @@ -5,51 +5,11 @@ import Test.Hspec.QuickCheck import Test.QuickCheck hiding (Fixed) import Categorizable -import qualified OrderedMap as Map -import qualified Data.List as List -import qualified Data.Set as Set import Interpreter import Diff -import Control.Comonad.Cofree -import Control.Monad -import GHC.Generics import Syntax import Term - -newtype ArbitraryTerm a annotation = ArbitraryTerm (annotation, (Syntax a (ArbitraryTerm a annotation))) - deriving (Show, Eq, Generic) - -unTerm :: ArbitraryTerm a annotation -> Term a annotation -unTerm = unfold unpack - where unpack (ArbitraryTerm (annotation, syntax)) = (annotation, syntax) - -instance (Eq a, Eq annotation, Arbitrary a, Arbitrary annotation) => Arbitrary (ArbitraryTerm a annotation) where - arbitrary = sized (\ x -> boundedTerm x x) -- first indicates the cube of the max length of lists, second indicates the cube of the max depth of the tree - where boundedTerm maxLength maxDepth = ArbitraryTerm <$> ((,) <$> arbitrary <*> boundedSyntax maxLength maxDepth) - boundedSyntax _ maxDepth | maxDepth <= 0 = liftM Leaf arbitrary - boundedSyntax maxLength maxDepth = frequency - [ (12, liftM Leaf arbitrary), - (1, liftM Indexed $ take maxLength <$> listOf (smallerTerm maxLength maxDepth)), - (1, liftM Fixed $ take maxLength <$> listOf (smallerTerm maxLength maxDepth)), - (1, liftM (Keyed . Map.fromList) $ take maxLength <$> listOf (arbitrary >>= (\x -> ((,) x) <$> smallerTerm maxLength maxDepth))) ] - smallerTerm maxLength maxDepth = boundedTerm (div maxLength 3) (div maxDepth 3) - shrink term@(ArbitraryTerm (annotation, syntax)) = (++) (subterms term) $ filter (/= term) $ - ArbitraryTerm <$> ((,) <$> shrink annotation <*> case syntax of - Leaf a -> Leaf <$> shrink a - Indexed i -> Indexed <$> (List.subsequences i >>= recursivelyShrink) - Fixed f -> Fixed <$> (List.subsequences f >>= recursivelyShrink) - Keyed k -> Keyed . Map.fromList <$> (List.subsequences (Map.toList k) >>= recursivelyShrink)) - -data CategorySet = A | B | C | D deriving (Eq, Show) - -instance Categorizable CategorySet where - categories A = Set.fromList [ "a" ] - categories B = Set.fromList [ "b" ] - categories C = Set.fromList [ "c" ] - categories D = Set.fromList [ "d" ] - -instance Arbitrary CategorySet where - arbitrary = elements [ A, B, C, D ] +import ArbitraryTerm main :: IO () main = hspec spec From 690966086e51d84fd9a168c6f6870f814d7c6f32 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 12:54:01 -0500 Subject: [PATCH 154/259] Remove some redundant parentheses. --- test/ArbitraryTerm.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/ArbitraryTerm.hs b/test/ArbitraryTerm.hs index a91221bcc..6a64cf0ed 100644 --- a/test/ArbitraryTerm.hs +++ b/test/ArbitraryTerm.hs @@ -11,7 +11,7 @@ import qualified Data.Set as Set import GHC.Generics import Test.QuickCheck hiding (Fixed) -newtype ArbitraryTerm a annotation = ArbitraryTerm (annotation, (Syntax a (ArbitraryTerm a annotation))) +newtype ArbitraryTerm a annotation = ArbitraryTerm (annotation, Syntax a (ArbitraryTerm a annotation)) deriving (Show, Eq, Generic) unTerm :: ArbitraryTerm a annotation -> Term a annotation @@ -26,7 +26,7 @@ instance (Eq a, Eq annotation, Arbitrary a, Arbitrary annotation) => Arbitrary ( [ (12, liftM Leaf arbitrary), (1, liftM Indexed $ take maxLength <$> listOf (smallerTerm maxLength maxDepth)), (1, liftM Fixed $ take maxLength <$> listOf (smallerTerm maxLength maxDepth)), - (1, liftM (Keyed . Map.fromList) $ take maxLength <$> listOf (arbitrary >>= (\x -> ((,) x) <$> smallerTerm maxLength maxDepth))) ] + (1, liftM (Keyed . Map.fromList) $ take maxLength <$> listOf (arbitrary >>= (\x -> (,) x <$> smallerTerm maxLength maxDepth))) ] smallerTerm maxLength maxDepth = boundedTerm (div maxLength 3) (div maxDepth 3) shrink term@(ArbitraryTerm (annotation, syntax)) = (++) (subterms term) $ filter (/= term) $ ArbitraryTerm <$> ((,) <$> shrink annotation <*> case syntax of From c4da8fb229d4df7483e36940b845f5cf1daad5c1 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 13:04:07 -0500 Subject: [PATCH 155/259] Generalize the single-line leaf test to arbitrary sources. --- test/SplitSpec.hs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index 7ee809fe6..560d9d3d7 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -12,6 +12,7 @@ import Control.Monad.Free hiding (unfold) import qualified Data.Maybe as Maybe import Patch import Syntax +import ArbitraryTerm instance Arbitrary a => Arbitrary (Row a) where arbitrary = oneof [ @@ -31,6 +32,12 @@ instance Arbitrary a => Arbitrary (Line a) where spec :: Spec spec = do describe "splitAnnotatedByLines" $ do + prop "outputs one row for single-line unchanged leaves" $ + \ a -> let source = filter (/= '\n') a + range = totalRange source in + splitAnnotatedByLines (source, source) (range, range) (mempty, mempty) (Leaf a) `shouldBe` [ + Row (Line [ Free $ Annotated (Info range mempty) $ Leaf a ]) (Line [ Free $ Annotated (Info range mempty) $ Leaf a ]) ] + it "outputs one row for single-line unchanged leaves" $ let sources = ("a", "a") ranges = (Range 0 1, Range 0 1) From 2a8a87959016051c91307c5c5c1e7697b736e6a0 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 13:04:33 -0500 Subject: [PATCH 156/259] Remove the hard-coded test. --- test/SplitSpec.hs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index 560d9d3d7..e9d1206c9 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -38,12 +38,6 @@ spec = do splitAnnotatedByLines (source, source) (range, range) (mempty, mempty) (Leaf a) `shouldBe` [ Row (Line [ Free $ Annotated (Info range mempty) $ Leaf a ]) (Line [ Free $ Annotated (Info range mempty) $ Leaf a ]) ] - it "outputs one row for single-line unchanged leaves" $ - let sources = ("a", "a") - ranges = (Range 0 1, Range 0 1) - categories = (mempty, mempty) in - splitAnnotatedByLines sources ranges categories (Leaf "b") `shouldBe` [ Row (Line [ Free $ Annotated (Info (fst ranges) (fst categories)) $ Leaf "b" ]) (Line [ Free $ Annotated (Info (snd ranges) (snd categories)) $ Leaf "b" ]) ] - describe "annotatedToRows" $ do it "outputs one row for single-line unchanged leaves" $ annotatedToRows (unchanged "a" "leaf" (Leaf "")) "a" "a" `shouldBe` [ Row (Line [ span "a" ]) (Line [ span "a" ]) ] From 867772d749532a113a08eb1dd8b93ee1cc719b53 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 13:04:39 -0500 Subject: [PATCH 157/259] Remove the corresponding annotatedToRows test. --- test/SplitSpec.hs | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index e9d1206c9..ea18bc63c 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -39,9 +39,6 @@ spec = do Row (Line [ Free $ Annotated (Info range mempty) $ Leaf a ]) (Line [ Free $ Annotated (Info range mempty) $ Leaf a ]) ] describe "annotatedToRows" $ do - it "outputs one row for single-line unchanged leaves" $ - annotatedToRows (unchanged "a" "leaf" (Leaf "")) "a" "a" `shouldBe` [ Row (Line [ span "a" ]) (Line [ span "a" ]) ] - it "outputs one row for single-line empty unchanged indexed nodes" $ annotatedToRows (unchanged "[]" "branch" (Indexed [])) "[]" "[]" `shouldBe` [ Row (Line [ Ul (Just "category-branch") [ Text "[]" ] ]) (Line [ Ul (Just "category-branch") [ Text "[]" ] ]) ] From 0775f90ce46eada7f58c534a7876f0cbfc15f72e Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 13:06:37 -0500 Subject: [PATCH 158/259] Syntax highlight categories. --- src/Split.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Split.hs b/src/Split.hs index 5e5bf888a..dc15dff0a 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -136,7 +136,7 @@ type SplitDiff leaf annotation = Free (Annotated leaf annotation) (Term leaf ann newtype Renderable a = Renderable (String, a) instance ToMarkup f => ToMarkup (Renderable (Info, Syntax a (f, Range))) where - toMarkup (Renderable (source, (Info range categories, syntax))) = classifyMarkup (maybeLast categories) $ case syntax of + toMarkup (Renderable (source, (Info range categories, syntax))) = classifyMarkup (classify categories) $ case syntax of Leaf _ -> span . string $ substring range source Indexed children -> ul . mconcat $ contentElements children Fixed children -> ul . mconcat $ contentElements children From 17a9de76ae38be4f303f6882ad08ddd313059335 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 13:09:02 -0500 Subject: [PATCH 159/259] Highlight patches within any code cell. --- UI/style.css | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/UI/style.css b/UI/style.css index 1ede9c083..d4a481ea7 100644 --- a/UI/style.css +++ b/UI/style.css @@ -81,12 +81,12 @@ body { padding: 0; font-family: monospace; } -.blob-code-replacement:last-child .insert, -.blob-code-replacement:last-child .replace { +.blob-code:last-child .insert, +.blob-code:last-child .replace { background-color: #a6f3a6; } -.blob-code-replacement .delete, -.blob-code-replacement .replace { +.blob-code .delete, +.blob-code .replace { background-color: #f8cbcb; } From 3d98361301ac4f36cca5a7031ef0b7049545eff9 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 13:09:10 -0500 Subject: [PATCH 160/259] Highlight the .patch class. --- UI/style.css | 2 ++ 1 file changed, 2 insertions(+) diff --git a/UI/style.css b/UI/style.css index d4a481ea7..85681b3f3 100644 --- a/UI/style.css +++ b/UI/style.css @@ -81,10 +81,12 @@ body { padding: 0; font-family: monospace; } +.blob-code:last-child .patch, .blob-code:last-child .insert, .blob-code:last-child .replace { background-color: #a6f3a6; } +.blob-code .patch, .blob-code .delete, .blob-code .replace { background-color: #f8cbcb; From aaaf8f27a438f5f2237dbd835929d71d09a43a76 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 13:16:03 -0500 Subject: [PATCH 161/259] Stub in a function to make arbitrary leaves & sources in some type. --- test/SplitSpec.hs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index ea18bc63c..c1b2177fd 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -29,6 +29,10 @@ instance Arbitrary a => Arbitrary (Line a) where Line <$> arbitrary, const EmptyLine <$> (arbitrary :: Gen ()) ] +arbitraryLeaf :: Int -> (Info -> Syntax String f -> f) -> Gen (String, f) +arbitraryLeaf start f = pairWithLeaf <$> arbitrary + where pairWithLeaf string = (string, f (Info (Range start $ start + length string) mempty) (Leaf string)) + spec :: Spec spec = do describe "splitAnnotatedByLines" $ do From 0422098f9b4ab2f87b4ff844fcf6311008e838d8 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 13:29:12 -0500 Subject: [PATCH 162/259] =?UTF-8?q?`arbitraryLeaf`=20doesn=E2=80=99t=20con?= =?UTF-8?q?struct=20terms.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/SplitSpec.hs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index c1b2177fd..2716008ac 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -29,9 +29,9 @@ instance Arbitrary a => Arbitrary (Line a) where Line <$> arbitrary, const EmptyLine <$> (arbitrary :: Gen ()) ] -arbitraryLeaf :: Int -> (Info -> Syntax String f -> f) -> Gen (String, f) -arbitraryLeaf start f = pairWithLeaf <$> arbitrary - where pairWithLeaf string = (string, f (Info (Range start $ start + length string) mempty) (Leaf string)) +arbitraryLeaf :: Int -> Gen (String, Info, Syntax String f) +arbitraryLeaf start = pairWithLeaf <$> arbitrary + where pairWithLeaf string = (string, Info (Range start $ start + length string) mempty, Leaf string) spec :: Spec spec = do From 5a552dc97c822450eb99adeb242e216d86c89054 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 13:29:36 -0500 Subject: [PATCH 163/259] Simplify the single-line unchanged leaf property. --- test/SplitSpec.hs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index 2716008ac..ce2d2338a 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -37,10 +37,9 @@ spec :: Spec spec = do describe "splitAnnotatedByLines" $ do prop "outputs one row for single-line unchanged leaves" $ - \ a -> let source = filter (/= '\n') a - range = totalRange source in - splitAnnotatedByLines (source, source) (range, range) (mempty, mempty) (Leaf a) `shouldBe` [ - Row (Line [ Free $ Annotated (Info range mempty) $ Leaf a ]) (Line [ Free $ Annotated (Info range mempty) $ Leaf a ]) ] + forAll (arbitraryLeaf 0 `suchThat` \ (a, _, _) -> filter (/= '\n') a == a) $ + \ (source, info@(Info range categories), syntax) -> splitAnnotatedByLines (source, source) (range, range) (categories, categories) syntax `shouldBe` [ + Row (Line [ Free $ Annotated info $ Leaf source ]) (Line [ Free $ Annotated info $ Leaf source ]) ] describe "annotatedToRows" $ do it "outputs one row for single-line empty unchanged indexed nodes" $ From bf05d63401ef114d3a7c39d6d23c9a976e27255b Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 13:31:31 -0500 Subject: [PATCH 164/259] Rename the tripling function. --- test/SplitSpec.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index ce2d2338a..fc08fad68 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -30,8 +30,8 @@ instance Arbitrary a => Arbitrary (Line a) where const EmptyLine <$> (arbitrary :: Gen ()) ] arbitraryLeaf :: Int -> Gen (String, Info, Syntax String f) -arbitraryLeaf start = pairWithLeaf <$> arbitrary - where pairWithLeaf string = (string, Info (Range start $ start + length string) mempty, Leaf string) +arbitraryLeaf start = toTuple <$> arbitrary + where toTuple string = (string, Info (Range start $ start + length string) mempty, Leaf string) spec :: Spec spec = do From b970f02c1d837a8c760c882e7c1ee84d8c7cadc2 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 13:38:44 -0500 Subject: [PATCH 165/259] =?UTF-8?q?Don=E2=80=99t=20offset=20arbitrary=20le?= =?UTF-8?q?aves.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/SplitSpec.hs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index fc08fad68..4cf26c2b2 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -29,15 +29,15 @@ instance Arbitrary a => Arbitrary (Line a) where Line <$> arbitrary, const EmptyLine <$> (arbitrary :: Gen ()) ] -arbitraryLeaf :: Int -> Gen (String, Info, Syntax String f) -arbitraryLeaf start = toTuple <$> arbitrary - where toTuple string = (string, Info (Range start $ start + length string) mempty, Leaf string) +arbitraryLeaf :: Gen (String, Info, Syntax String f) +arbitraryLeaf = toTuple <$> arbitrary + where toTuple string = (string, Info (Range 0 $ length string) mempty, Leaf string) spec :: Spec spec = do describe "splitAnnotatedByLines" $ do prop "outputs one row for single-line unchanged leaves" $ - forAll (arbitraryLeaf 0 `suchThat` \ (a, _, _) -> filter (/= '\n') a == a) $ + forAll (arbitraryLeaf `suchThat` \ (a, _, _) -> filter (/= '\n') a == a) $ \ (source, info@(Info range categories), syntax) -> splitAnnotatedByLines (source, source) (range, range) (categories, categories) syntax `shouldBe` [ Row (Line [ Free $ Annotated info $ Leaf source ]) (Line [ Free $ Annotated info $ Leaf source ]) ] From 780c8247a39d119029bc9c7c98420d4ce0bc574f Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 14:44:49 -0500 Subject: [PATCH 166/259] Abstract out a predicate for terms on a single line. --- test/SplitSpec.hs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index 4cf26c2b2..147decff4 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -206,3 +206,5 @@ spec = do isOpen (Row a b) = Maybe.isJust (openLineBy openElement [ a ]) && Maybe.isJust (openLineBy openElement [ b ]) isClosed (Row a@(Line _) b@(Line _)) = Maybe.isNothing (openLineBy openElement [ a ]) && Maybe.isNothing (openLineBy openElement [ b ]) isClosed (Row _ _) = False + + isOnSingleLine (a, _, _) = filter (/= '\n') a == a From b3c0802e552cf733b4c006103ef8a42ad2d348a8 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 14:44:57 -0500 Subject: [PATCH 167/259] Use the abstracted predicate. --- test/SplitSpec.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index 147decff4..2257394ac 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -37,7 +37,7 @@ spec :: Spec spec = do describe "splitAnnotatedByLines" $ do prop "outputs one row for single-line unchanged leaves" $ - forAll (arbitraryLeaf `suchThat` \ (a, _, _) -> filter (/= '\n') a == a) $ + forAll (arbitraryLeaf `suchThat` isOnSingleLine) $ \ (source, info@(Info range categories), syntax) -> splitAnnotatedByLines (source, source) (range, range) (categories, categories) syntax `shouldBe` [ Row (Line [ Free $ Annotated info $ Leaf source ]) (Line [ Free $ Annotated info $ Leaf source ]) ] From c41a2cfccce3203994917443316d9daa4d4a81e7 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 14:53:29 -0500 Subject: [PATCH 168/259] Enable RankNTypes. --- semantic-diff.cabal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/semantic-diff.cabal b/semantic-diff.cabal index 1bd11f497..6e063ebee 100644 --- a/semantic-diff.cabal +++ b/semantic-diff.cabal @@ -37,7 +37,7 @@ library , blaze-html , tree-sitter-parsers default-language: Haskell2010 - default-extensions: DeriveFunctor, FlexibleInstances, DeriveFoldable, DeriveTraversable + default-extensions: DeriveFunctor, FlexibleInstances, DeriveFoldable, DeriveTraversable, RankNTypes ghc-options: -Wall -fno-warn-name-shadowing executable semantic-diff-exe From b518c4702c631b57757d08a9b61cc4ad02768392 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 14:54:32 -0500 Subject: [PATCH 169/259] Add a function to find an open diff given a source string & left/right selector. --- src/Split.hs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Split.hs b/src/Split.hs index dc15dff0a..5b988a99c 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -330,6 +330,10 @@ openDiff :: String -> 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 +openDiff2 :: String -> (forall b. (b, b) -> b) -> Diff a Info -> Maybe (Diff a Info) +openDiff2 source which diff@(Free (Annotated (Info range1 _, Info range2 _) _)) = const diff <$> openRange source (which (range1, range2)) +openDiff2 source which diff@(Pure patch) = const diff . openTerm source <$> which (before patch, after patch) + openLineBy :: (a -> Maybe a) -> [Line a] -> Maybe (Line a) openLineBy _ [] = Nothing openLineBy f (EmptyLine : rest) = openLineBy f rest From eaab1d73b282cd03a469f4ff1a95af2fa159da59 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 14:55:39 -0500 Subject: [PATCH 170/259] Rephrase openDiff2 to accept a pair of sources & apply the selector to the pair. --- src/Split.hs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 5b988a99c..5b0266d2a 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -330,9 +330,9 @@ openDiff :: String -> 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 -openDiff2 :: String -> (forall b. (b, b) -> b) -> Diff a Info -> Maybe (Diff a Info) -openDiff2 source which diff@(Free (Annotated (Info range1 _, Info range2 _) _)) = const diff <$> openRange source (which (range1, range2)) -openDiff2 source which diff@(Pure patch) = const diff . openTerm source <$> which (before patch, after patch) +openDiff2 :: (forall b. (b, b) -> b) -> (String, String) -> Diff a Info -> Maybe (Diff a Info) +openDiff2 which sources diff@(Free (Annotated (Info range1 _, Info range2 _) _)) = const diff <$> openRange (which sources) (which (range1, range2)) +openDiff2 which sources diff@(Pure patch) = const diff . openTerm (which sources) <$> which (before patch, after patch) openLineBy :: (a -> Maybe a) -> [Line a] -> Maybe (Line a) openLineBy _ [] = Nothing From 2768459246494c89ce712da0fc88bffd3457f6e5 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 15:13:04 -0500 Subject: [PATCH 171/259] Rename the string parameters in `split`. --- src/Split.hs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 5b0266d2a..508139a6d 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -52,7 +52,7 @@ instance ToMarkup HTML where toMarkup (Dt key) = dt $ string key split :: Diff a Info -> String -> String -> IO ByteString -split diff before after = return . renderHtml +split diff left right = return . renderHtml . docTypeHtml . ((head $ link ! A.rel (stringValue "stylesheet") ! A.href (stringValue "style.css")) <>) . body @@ -60,8 +60,8 @@ split diff before after = return . renderHtml ((colgroup $ (col ! A.width (stringValue . show $ columnWidth)) <> col <> (col ! A.width (stringValue . show $ columnWidth)) <> col) <>) . mconcat $ toMarkup <$> reverse numbered where - rows = toRenderable <$> fst (splitDiffByLines diff (0, 0) (before, after)) - toRenderable (Row a b) = Row (Renderable . (,) before <$> a) (Renderable . (,) after <$> b) + rows = toRenderable <$> fst (splitDiffByLines diff (0, 0) (left, right)) + toRenderable (Row a b) = Row (Renderable . (,) left . split fst <$> a) (Renderable . (,) right . split snd <$> b) numbered = foldl numberRows [] rows maxNumber = case numbered of [] -> 0 From ecc1820a075bec6bc339a21685f390fe79bd6398 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 15:15:50 -0500 Subject: [PATCH 172/259] Add a recursive function to split a Diff into a SplitDiff. --- src/Split.hs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Split.hs b/src/Split.hs index 508139a6d..97341caeb 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -71,6 +71,12 @@ split diff left right = return . renderHtml digits n = let base = 10 :: Int in ceiling (logBase (fromIntegral base) (fromIntegral n) :: Double) + split :: (forall b. (b, b) -> b) -> Free (Annotated leaf (annotation, annotation)) (Patch (Term leaf annotation)) -> SplitDiff leaf annotation + split which (Pure patch) = Pure $ case which (before patch, after patch) of + Just term -> term + _ -> error "`split` expects to be called with a total selector for patches" + split which (Free (Annotated infos syntax)) = Free . Annotated (which infos) $ split which <$> syntax + columnWidth = max (20 + digits maxNumber * 8) 40 numberRows :: [(Int, Line a, Int, Line a)] -> Row a -> [(Int, Line a, Int, Line a)] From 5c27b16705f511b95e54a2d5dcaab855fae0e070 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 15:16:31 -0500 Subject: [PATCH 173/259] Fanout values into pairs. --- src/Split.hs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Split.hs b/src/Split.hs index 97341caeb..8387db74a 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -244,6 +244,7 @@ splitAnnotatedByLines sources ranges categories syntax = case syntax of starts (left, right) = (start left, start right) ends (left, right) = (end left, end right) makeRanges (leftStart, rightStart) (leftEnd, rightEnd) = (Range leftStart leftEnd, Range rightStart rightEnd) + duplicate x = (x, x) -- | Given an Annotated and before/after strings, returns a list of `Row`s representing the newline-separated diff. annotatedToRows :: Annotated a (Info, Info) (Diff a Info) -> String -> String -> [Row HTML] From cff90ee11bdf07e83aec9a5ef93f4e02054aac32 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 15:17:17 -0500 Subject: [PATCH 174/259] Split diffs into left/right Diffs instead of SplitDiffs. --- src/Split.hs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 8387db74a..0550bcc88 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -161,16 +161,16 @@ 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) -> (String, String) -> ([Row (SplitDiff a Info)], (Range, Range)) +splitDiffByLines :: Diff a Info -> (Int, Int) -> (String, String) -> ([Row (Diff 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 - (Row EmptyLine . fmap Pure <$> lines, (Range prevLeft prevLeft, range)) + (Row EmptyLine . fmap (Pure . Insert) <$> lines, (Range prevLeft prevLeft, range)) Pure (Delete term) -> let (lines, range) = splitTermByLines term (fst sources) in - (flip Row EmptyLine . fmap Pure <$> lines, (range, Range prevRight prevRight)) + (flip Row EmptyLine . fmap (Pure . Delete) <$> lines, (range, Range prevRight prevRight)) Pure (Replace leftTerm rightTerm) -> let (leftLines, leftRange) = splitTermByLines leftTerm (fst sources) (rightLines, rightRange) = splitTermByLines rightTerm (snd sources) in - (zipWithDefaults Row EmptyLine EmptyLine (fmap Pure <$> leftLines) (fmap Pure <$> rightLines), (leftRange, rightRange)) + (zipWithDefaults Row EmptyLine EmptyLine (fmap (Pure . Delete) <$> leftLines) (fmap (Pure . Insert) <$> rightLines), (leftRange, rightRange)) where categories (Info _ left, Info _ right) = (left, right) ranges (Info left _, Info right _) = (left, right) @@ -226,15 +226,15 @@ termToLines (Info range categories :< syntax) source = (rows syntax, range) (adjoin $ lines ++ contextLines (Range previous $ start childRange) source ++ childLines, end childRange) elements = elementAndBreak (Span $ classify categories) =<< actualLines (substring range source) -splitAnnotatedByLines :: (String, String) -> (Range, Range) -> (Set.Set Category, Set.Set Category) -> Syntax a (Diff a Info) -> [Row (SplitDiff a Info)] +splitAnnotatedByLines :: (String, String) -> (Range, Range) -> (Set.Set Category, Set.Set Category) -> Syntax a (Diff a Info) -> [Row (Diff a Info)] splitAnnotatedByLines sources ranges categories syntax = case syntax of Leaf a -> contextRows (Leaf a) ranges categories sources Indexed children -> adjoinChildRows Indexed children Fixed children -> adjoinChildRows Fixed children Keyed children -> adjoinChildRows Keyed children - where contextRows constructor ranges categories sources = zipWithDefaults Row EmptyLine EmptyLine (contextLines (Free . (`Annotated` constructor)) (fst ranges) (fst categories) (fst sources)) (contextLines (Free . (`Annotated` constructor)) (snd ranges) (snd categories) (snd sources)) + where contextRows constructor ranges categories sources = zipWithDefaults Row EmptyLine EmptyLine (contextLines (Free . (`Annotated` constructor) . duplicate) (fst ranges) (fst categories) (fst sources)) (contextLines (Free . (`Annotated` constructor) . duplicate) (snd ranges) (snd categories) (snd sources)) - adjoin = reverse . foldl (adjoinRowsBy (openDiff $ fst sources) (openDiff $ snd sources)) [] + adjoin = reverse . foldl (adjoinRowsBy (openDiff2 fst sources) (openDiff2 snd sources)) [] adjoinChildRows constructor children = let (rows, previous) = foldl (childRows $ constructor mempty) ([], starts ranges) children in adjoin $ rows ++ contextRows (constructor mempty) (makeRanges previous (ends ranges)) categories sources From 9cd5268642fc5c45fe6b79a12e34b65fc7e1faa3 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 15:17:21 -0500 Subject: [PATCH 175/259] Revert "Split diffs into left/right Diffs instead of SplitDiffs." This reverts commit 1f71599a59b15f90fcd1a2c2f33b97b35c21ce65. --- src/Split.hs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 0550bcc88..8387db74a 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -161,16 +161,16 @@ 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) -> (String, String) -> ([Row (Diff a Info)], (Range, Range)) +splitDiffByLines :: Diff a Info -> (Int, Int) -> (String, String) -> ([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 - (Row EmptyLine . fmap (Pure . Insert) <$> lines, (Range prevLeft prevLeft, range)) + (Row EmptyLine . fmap Pure <$> lines, (Range prevLeft prevLeft, range)) Pure (Delete term) -> let (lines, range) = splitTermByLines term (fst sources) in - (flip Row EmptyLine . fmap (Pure . Delete) <$> lines, (range, Range prevRight prevRight)) + (flip Row EmptyLine . fmap Pure <$> lines, (range, Range prevRight prevRight)) Pure (Replace leftTerm rightTerm) -> let (leftLines, leftRange) = splitTermByLines leftTerm (fst sources) (rightLines, rightRange) = splitTermByLines rightTerm (snd sources) in - (zipWithDefaults Row EmptyLine EmptyLine (fmap (Pure . Delete) <$> leftLines) (fmap (Pure . Insert) <$> rightLines), (leftRange, rightRange)) + (zipWithDefaults Row EmptyLine EmptyLine (fmap Pure <$> leftLines) (fmap Pure <$> rightLines), (leftRange, rightRange)) where categories (Info _ left, Info _ right) = (left, right) ranges (Info left _, Info right _) = (left, right) @@ -226,15 +226,15 @@ termToLines (Info range categories :< syntax) source = (rows syntax, range) (adjoin $ lines ++ contextLines (Range previous $ start childRange) source ++ childLines, end childRange) elements = elementAndBreak (Span $ classify categories) =<< actualLines (substring range source) -splitAnnotatedByLines :: (String, String) -> (Range, Range) -> (Set.Set Category, Set.Set Category) -> Syntax a (Diff a Info) -> [Row (Diff a Info)] +splitAnnotatedByLines :: (String, String) -> (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 Fixed children -> adjoinChildRows Fixed children Keyed children -> adjoinChildRows Keyed children - where contextRows constructor ranges categories sources = zipWithDefaults Row EmptyLine EmptyLine (contextLines (Free . (`Annotated` constructor) . duplicate) (fst ranges) (fst categories) (fst sources)) (contextLines (Free . (`Annotated` constructor) . duplicate) (snd ranges) (snd categories) (snd sources)) + where contextRows constructor ranges categories sources = zipWithDefaults Row EmptyLine EmptyLine (contextLines (Free . (`Annotated` constructor)) (fst ranges) (fst categories) (fst sources)) (contextLines (Free . (`Annotated` constructor)) (snd ranges) (snd categories) (snd sources)) - adjoin = reverse . foldl (adjoinRowsBy (openDiff2 fst sources) (openDiff2 snd sources)) [] + adjoin = reverse . foldl (adjoinRowsBy (openDiff $ fst sources) (openDiff $ snd sources)) [] adjoinChildRows constructor children = let (rows, previous) = foldl (childRows $ constructor mempty) ([], starts ranges) children in adjoin $ rows ++ contextRows (constructor mempty) (makeRanges previous (ends ranges)) categories sources From 610133fdb3108030f72a09169ecc41581df9abcc Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 15:17:26 -0500 Subject: [PATCH 176/259] Revert "Fanout values into pairs." This reverts commit 21bb26bb43b87d265ced27f30570283009822769. --- src/Split.hs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Split.hs b/src/Split.hs index 8387db74a..97341caeb 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -244,7 +244,6 @@ splitAnnotatedByLines sources ranges categories syntax = case syntax of starts (left, right) = (start left, start right) ends (left, right) = (end left, end right) makeRanges (leftStart, rightStart) (leftEnd, rightEnd) = (Range leftStart leftEnd, Range rightStart rightEnd) - duplicate x = (x, x) -- | Given an Annotated and before/after strings, returns a list of `Row`s representing the newline-separated diff. annotatedToRows :: Annotated a (Info, Info) (Diff a Info) -> String -> String -> [Row HTML] From 37afcfbc04d814a03c8c6a6e61db227f377a53f6 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 15:17:29 -0500 Subject: [PATCH 177/259] Revert "Add a recursive function to split a Diff into a SplitDiff." This reverts commit e5ecdf3a0bbf3bd8a97dd210b8dedc6304e55e5d. --- src/Split.hs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 97341caeb..508139a6d 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -71,12 +71,6 @@ split diff left right = return . renderHtml digits n = let base = 10 :: Int in ceiling (logBase (fromIntegral base) (fromIntegral n) :: Double) - split :: (forall b. (b, b) -> b) -> Free (Annotated leaf (annotation, annotation)) (Patch (Term leaf annotation)) -> SplitDiff leaf annotation - split which (Pure patch) = Pure $ case which (before patch, after patch) of - Just term -> term - _ -> error "`split` expects to be called with a total selector for patches" - split which (Free (Annotated infos syntax)) = Free . Annotated (which infos) $ split which <$> syntax - columnWidth = max (20 + digits maxNumber * 8) 40 numberRows :: [(Int, Line a, Int, Line a)] -> Row a -> [(Int, Line a, Int, Line a)] From 73fd8b3d91e7fd85d94ca9a4582b7f83bd4de952 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 15:17:34 -0500 Subject: [PATCH 178/259] Revert "Rename the string parameters in `split`." This reverts commit 46733254edb4a0ce79c49491753385622890758f. --- src/Split.hs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 508139a6d..5b0266d2a 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -52,7 +52,7 @@ instance ToMarkup HTML where toMarkup (Dt key) = dt $ string key split :: Diff a Info -> String -> String -> IO ByteString -split diff left right = return . renderHtml +split diff before after = return . renderHtml . docTypeHtml . ((head $ link ! A.rel (stringValue "stylesheet") ! A.href (stringValue "style.css")) <>) . body @@ -60,8 +60,8 @@ split diff left right = return . renderHtml ((colgroup $ (col ! A.width (stringValue . show $ columnWidth)) <> col <> (col ! A.width (stringValue . show $ columnWidth)) <> col) <>) . mconcat $ toMarkup <$> reverse numbered where - rows = toRenderable <$> fst (splitDiffByLines diff (0, 0) (left, right)) - toRenderable (Row a b) = Row (Renderable . (,) left . split fst <$> a) (Renderable . (,) right . split snd <$> b) + rows = toRenderable <$> fst (splitDiffByLines diff (0, 0) (before, after)) + toRenderable (Row a b) = Row (Renderable . (,) before <$> a) (Renderable . (,) after <$> b) numbered = foldl numberRows [] rows maxNumber = case numbered of [] -> 0 From b6c4969bdd563f5eb136144f2ebfbe0cfa2c1a59 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 15:17:38 -0500 Subject: [PATCH 179/259] Revert "Rephrase openDiff2 to accept a pair of sources & apply the selector to the pair." This reverts commit c22e9a3937f9bfdd91382fd20c29b681ccb18927. --- src/Split.hs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 5b0266d2a..5b988a99c 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -330,9 +330,9 @@ openDiff :: String -> 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 -openDiff2 :: (forall b. (b, b) -> b) -> (String, String) -> Diff a Info -> Maybe (Diff a Info) -openDiff2 which sources diff@(Free (Annotated (Info range1 _, Info range2 _) _)) = const diff <$> openRange (which sources) (which (range1, range2)) -openDiff2 which sources diff@(Pure patch) = const diff . openTerm (which sources) <$> which (before patch, after patch) +openDiff2 :: String -> (forall b. (b, b) -> b) -> Diff a Info -> Maybe (Diff a Info) +openDiff2 source which diff@(Free (Annotated (Info range1 _, Info range2 _) _)) = const diff <$> openRange source (which (range1, range2)) +openDiff2 source which diff@(Pure patch) = const diff . openTerm source <$> which (before patch, after patch) openLineBy :: (a -> Maybe a) -> [Line a] -> Maybe (Line a) openLineBy _ [] = Nothing From 7462ace01b6f32f8fc84e7b91782e2e41cf17ad7 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 15:17:44 -0500 Subject: [PATCH 180/259] Revert "Add a function to find an open diff given a source string & left/right selector." This reverts commit 311f426726c3bbd409450444e3cc67d36510bbbe. --- src/Split.hs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 5b988a99c..dc15dff0a 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -330,10 +330,6 @@ openDiff :: String -> 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 -openDiff2 :: String -> (forall b. (b, b) -> b) -> Diff a Info -> Maybe (Diff a Info) -openDiff2 source which diff@(Free (Annotated (Info range1 _, Info range2 _) _)) = const diff <$> openRange source (which (range1, range2)) -openDiff2 source which diff@(Pure patch) = const diff . openTerm source <$> which (before patch, after patch) - openLineBy :: (a -> Maybe a) -> [Line a] -> Maybe (Line a) openLineBy _ [] = Nothing openLineBy f (EmptyLine : rest) = openLineBy f rest From 6e20ad6a9c5df51a41b730bdcefc68a03b8b0e61 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 15:17:55 -0500 Subject: [PATCH 181/259] Revert "Enable RankNTypes." This reverts commit 8fce071dc9a45ff1ecb9d683980fc584a358eece. --- semantic-diff.cabal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/semantic-diff.cabal b/semantic-diff.cabal index 6e063ebee..1bd11f497 100644 --- a/semantic-diff.cabal +++ b/semantic-diff.cabal @@ -37,7 +37,7 @@ library , blaze-html , tree-sitter-parsers default-language: Haskell2010 - default-extensions: DeriveFunctor, FlexibleInstances, DeriveFoldable, DeriveTraversable, RankNTypes + default-extensions: DeriveFunctor, FlexibleInstances, DeriveFoldable, DeriveTraversable ghc-options: -Wall -fno-warn-name-shadowing executable semantic-diff-exe From 20817152c24d6dc5f81ac30872f16a29d640220e Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 15:20:46 -0500 Subject: [PATCH 182/259] Rename the line contents binding. --- src/Split.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Split.hs b/src/Split.hs index dc15dff0a..1191af80c 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -109,7 +109,7 @@ codeTd (Just el) = td el ! A.class_ (stringValue "blob-code") instance ToMarkup a => ToMarkup (Line a) where toMarkup EmptyLine = codeTd Nothing - toMarkup (Line html) = codeTd . Just . mconcat $ toMarkup <$> html + toMarkup (Line contents) = codeTd . Just . mconcat $ toMarkup <$> contents data Line a = Line [a] From cf82488820224a1d43487984762c990260f669cf Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 15:29:16 -0500 Subject: [PATCH 183/259] =?UTF-8?q?codeTd=20takes=20a=20=E2=80=9Chas=20cha?= =?UTF-8?q?nges=E2=80=9D=20flag=20again.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We always pass `False` currently. --- src/Split.hs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 1191af80c..2997bcdea 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -102,14 +102,14 @@ numberTd :: String -> Html numberTd "" = td mempty ! A.class_ (stringValue "blob-num blob-num-empty empty-cell") numberTd s = td (string s) ! A.class_ (stringValue "blob-num") -codeTd :: Maybe Html -> Html -codeTd Nothing = td mempty ! A.class_ (stringValue "blob-code blob-code-empty empty-cell") --- codeTd True (Just el) = td el ! A.class_ (stringValue "blob-code blob-code-replacement") -codeTd (Just el) = td el ! A.class_ (stringValue "blob-code") +codeTd :: Bool -> Maybe Html -> Html +codeTd _ Nothing = td mempty ! A.class_ (stringValue "blob-code blob-code-empty empty-cell") +codeTd True (Just el) = td el ! A.class_ (stringValue "blob-code blob-code-replacement") +codeTd False (Just el) = td el ! A.class_ (stringValue "blob-code") instance ToMarkup a => ToMarkup (Line a) where - toMarkup EmptyLine = codeTd Nothing - toMarkup (Line contents) = codeTd . Just . mconcat $ toMarkup <$> contents + toMarkup EmptyLine = codeTd False Nothing + toMarkup (Line contents) = codeTd False . Just . mconcat $ toMarkup <$> contents data Line a = Line [a] From 9e6f415dc62d8b6d94c50eabcf3f2e62a33f1790 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 15:38:18 -0500 Subject: [PATCH 184/259] Port the single-line empty unchanged indexed diff test to splitAnnotatedByLines. --- test/SplitSpec.hs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index 2257394ac..8482cb5f8 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -41,6 +41,11 @@ spec = do \ (source, info@(Info range categories), syntax) -> splitAnnotatedByLines (source, source) (range, range) (categories, categories) syntax `shouldBe` [ Row (Line [ Free $ Annotated info $ Leaf source ]) (Line [ Free $ Annotated info $ Leaf source ]) ] + prop "outputs one row for single-line empty unchanged indexed nodes" $ + forAll (arbitrary `suchThat` \ s -> filter (/= '\n') s == s) $ + \ source -> splitAnnotatedByLines (source, source) (totalRange source, totalRange source) (mempty, mempty) (Indexed [] :: Syntax String (Diff String Info)) `shouldBe` [ + Row (Line [ Free $ Annotated (Info (totalRange source) mempty) $ Indexed [] ]) (Line [ Free $ Annotated (Info (totalRange source) mempty) $ Indexed [] ]) ] + describe "annotatedToRows" $ do it "outputs one row for single-line empty unchanged indexed nodes" $ annotatedToRows (unchanged "[]" "branch" (Indexed [])) "[]" "[]" `shouldBe` [ Row (Line [ Ul (Just "category-branch") [ Text "[]" ] ]) (Line [ Ul (Just "category-branch") [ Text "[]" ] ]) ] From ef027dba367c5a6a2aeb280149b3a81bc358b95f Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 15:48:37 -0500 Subject: [PATCH 185/259] Test that we preserve the line counts in equal diffs. --- test/SplitSpec.hs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index 8482cb5f8..5cba2a075 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -46,6 +46,10 @@ spec = do \ source -> splitAnnotatedByLines (source, source) (totalRange source, totalRange source) (mempty, mempty) (Indexed [] :: Syntax String (Diff String Info)) `shouldBe` [ Row (Line [ Free $ Annotated (Info (totalRange source) mempty) $ Indexed [] ]) (Line [ Free $ Annotated (Info (totalRange source) mempty) $ Indexed [] ]) ] + prop "preserves line counts in equal sources" $ + \ source -> let range = totalRange source in + length (splitAnnotatedByLines (source, source) (totalRange source, totalRange source) (mempty, mempty) (Indexed . fst $ foldl combineIntoLeaves ([], 0) source)) `shouldBe` length (filter (== '\n') source) + 1 + describe "annotatedToRows" $ do it "outputs one row for single-line empty unchanged indexed nodes" $ annotatedToRows (unchanged "[]" "branch" (Indexed [])) "[]" "[]" `shouldBe` [ Row (Line [ Ul (Just "category-branch") [ Text "[]" ] ]) (Line [ Ul (Just "category-branch") [ Text "[]" ] ]) ] @@ -213,3 +217,5 @@ spec = do isClosed (Row _ _) = False isOnSingleLine (a, _, _) = filter (/= '\n') a == a + + combineIntoLeaves (leaves, start) char = (leaves ++ [ Free $ Annotated (Info (Range start $ start + 1) mempty, Info (Range start $ start + 1) mempty) (Leaf [ char ]) ], start + 1) From 603e750d67c5caa970e303a381753fb37d962b5b Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 15:55:59 -0500 Subject: [PATCH 186/259] Remove an unused let binding. --- test/SplitSpec.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index 5cba2a075..e29ba6971 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -47,7 +47,7 @@ spec = do Row (Line [ Free $ Annotated (Info (totalRange source) mempty) $ Indexed [] ]) (Line [ Free $ Annotated (Info (totalRange source) mempty) $ Indexed [] ]) ] prop "preserves line counts in equal sources" $ - \ source -> let range = totalRange source in + \ source -> length (splitAnnotatedByLines (source, source) (totalRange source, totalRange source) (mempty, mempty) (Indexed . fst $ foldl combineIntoLeaves ([], 0) source)) `shouldBe` length (filter (== '\n') source) + 1 describe "annotatedToRows" $ do From 6510e9552659552d5d043bbf1e2f3634cb73f792 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 16:10:05 -0500 Subject: [PATCH 187/259] Test that we always produce the maximum of the lines in two sources. --- test/SplitSpec.hs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index e29ba6971..9e708a393 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -50,6 +50,10 @@ spec = do \ source -> length (splitAnnotatedByLines (source, source) (totalRange source, totalRange source) (mempty, mempty) (Indexed . fst $ foldl combineIntoLeaves ([], 0) source)) `shouldBe` length (filter (== '\n') source) + 1 + prop "produces the maximum line count in inequal sources" $ + \ sourceA sourceB -> + length (splitAnnotatedByLines (sourceA, sourceB) (totalRange sourceA, totalRange sourceB) (mempty, mempty) (Indexed [])) `shouldBe` max (length (filter (== '\n') sourceA) + 1) (length (filter (== '\n') sourceB) + 1) + describe "annotatedToRows" $ do it "outputs one row for single-line empty unchanged indexed nodes" $ annotatedToRows (unchanged "[]" "branch" (Indexed [])) "[]" "[]" `shouldBe` [ Row (Line [ Ul (Just "category-branch") [ Text "[]" ] ]) (Line [ Ul (Just "category-branch") [ Text "[]" ] ]) ] From 1b90bc02910e5101350599247cda353229756b60 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 16:26:07 -0500 Subject: [PATCH 188/259] Add a function to construct a leaf from a pair of line ranges. --- test/SplitSpec.hs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index 9e708a393..ba731fa69 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -223,3 +223,5 @@ spec = do isOnSingleLine (a, _, _) = filter (/= '\n') a == a combineIntoLeaves (leaves, start) char = (leaves ++ [ Free $ Annotated (Info (Range start $ start + 1) mempty, Info (Range start $ start + 1) mempty) (Leaf [ char ]) ], start + 1) + + leafWithRangesInSources sourceA sourceB rangeA rangeB = Free $ Annotated (Info rangeA mempty, Info rangeB mempty) (Leaf $ substring rangeA sourceA ++ substring rangeB sourceB) From 9a496a6be58cc90698fe649d98a9fe1c1215210a Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 16:26:24 -0500 Subject: [PATCH 189/259] Populate the indexed term with leaves. --- test/SplitSpec.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index ba731fa69..b5ab74ba8 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -52,7 +52,7 @@ spec = do prop "produces the maximum line count in inequal sources" $ \ sourceA sourceB -> - length (splitAnnotatedByLines (sourceA, sourceB) (totalRange sourceA, totalRange sourceB) (mempty, mempty) (Indexed [])) `shouldBe` max (length (filter (== '\n') sourceA) + 1) (length (filter (== '\n') sourceB) + 1) + length (splitAnnotatedByLines (sourceA, sourceB) (totalRange sourceA, totalRange sourceB) (mempty, mempty) (Indexed $ zipWith (leafWithRangesInSources sourceA sourceB) (actualLineRanges (totalRange sourceA) sourceA) (actualLineRanges (totalRange sourceB) sourceB))) `shouldBe` max (length (filter (== '\n') sourceA) + 1) (length (filter (== '\n') sourceB) + 1) describe "annotatedToRows" $ do it "outputs one row for single-line empty unchanged indexed nodes" $ From c41364a743cf58ea2674d38f178c719a30fcf1bf Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 16:28:49 -0500 Subject: [PATCH 190/259] Remove the remaining annotatedToRows tests. --- test/SplitSpec.hs | 80 ----------------------------------------------- 1 file changed, 80 deletions(-) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index b5ab74ba8..60528f73f 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -54,86 +54,6 @@ spec = do \ sourceA sourceB -> length (splitAnnotatedByLines (sourceA, sourceB) (totalRange sourceA, totalRange sourceB) (mempty, mempty) (Indexed $ zipWith (leafWithRangesInSources sourceA sourceB) (actualLineRanges (totalRange sourceA) sourceA) (actualLineRanges (totalRange sourceB) sourceB))) `shouldBe` max (length (filter (== '\n') sourceA) + 1) (length (filter (== '\n') sourceB) + 1) - describe "annotatedToRows" $ do - it "outputs one row for single-line empty unchanged indexed nodes" $ - annotatedToRows (unchanged "[]" "branch" (Indexed [])) "[]" "[]" `shouldBe` [ Row (Line [ Ul (Just "category-branch") [ Text "[]" ] ]) (Line [ Ul (Just "category-branch") [ Text "[]" ] ]) ] - - it "outputs one row for single-line non-empty unchanged indexed nodes" $ - annotatedToRows (unchanged "[ a, b ]" "branch" (Indexed [ - Free . offsetAnnotated 2 2 $ unchanged "a" "leaf" (Leaf ""), - Free . offsetAnnotated 5 5 $ unchanged "b" "leaf" (Leaf "") - ])) "[ a, b ]" "[ a, b ]" `shouldBe` [ Row (Line [ Ul (Just "category-branch") [ Text "[ ", span "a", Text ", ", span "b", Text " ]" ] ]) (Line [ Ul (Just "category-branch") [ Text "[ ", span "a", Text ", ", span "b", Text " ]" ] ]) ] - - it "outputs one row for single-line non-empty formatted indexed nodes" $ - annotatedToRows (formatted "[ a, b ]" "[ a, b ]" "branch" (Indexed [ - Free . offsetAnnotated 2 2 $ unchanged "a" "leaf" (Leaf ""), - Free . offsetAnnotated 5 6 $ unchanged "b" "leaf" (Leaf "") - ])) "[ a, b ]" "[ a, b ]" `shouldBe` [ Row (Line [ Ul (Just "category-branch") [ Text "[ ", span "a", Text ", ", span "b", Text " ]" ] ]) (Line [ Ul (Just "category-branch") [ Text "[ ", span "a", Text ", ", span "b", Text " ]" ] ]) ] - - it "outputs two rows for two-line non-empty unchanged indexed nodes" $ - annotatedToRows (unchanged "[ a,\nb ]" "branch" (Indexed [ - Free . offsetAnnotated 2 2 $ unchanged "a" "leaf" (Leaf ""), - Free . offsetAnnotated 5 5 $ unchanged "b" "leaf" (Leaf "") - ])) "[ a,\nb ]" "[ a,\nb ]" `shouldBe` - [ - Row (Line [ Ul (Just "category-branch") [ Text "[ ", span "a", Text ",", Break ] ]) - (Line [ Ul (Just "category-branch") [ Text "[ ", span "a", Text ",", Break] ]), - Row (Line [ Ul (Just "category-branch") [ span "b", Text " ]" ] ]) - (Line [ Ul (Just "category-branch") [ span "b", Text " ]" ] ]) - ] - - it "outputs two rows for two-line non-empty formatted indexed nodes" $ - annotatedToRows (formatted "[ a,\nb ]" "[\na,\nb ]" "branch" (Indexed [ - Free . offsetAnnotated 2 2 $ unchanged "a" "leaf" (Leaf ""), - Free . offsetAnnotated 5 5 $ unchanged "b" "leaf" (Leaf "") - ])) "[ a,\nb ]" "[\na,\nb ]" `shouldBe` - [ - Row (Line [ Ul (Just "category-branch") [ Text "[ ", span "a", Text ",", Break ] ]) - (Line [ Ul (Just "category-branch") [ Text "[", Break ] ]), - Row EmptyLine - (Line [ Ul (Just "category-branch") [ span "a", Text ",", Break ] ]), - Row (Line [ Ul (Just "category-branch") [ span "b", Text " ]" ] ]) - (Line [ Ul (Just "category-branch") [ span "b", Text " ]" ] ]) - ] - - it "" $ - let (sourceA, sourceB) = ("[\na\n,\nb]", "[a,b]") in - annotatedToRows (formatted sourceA sourceB "branch" (Indexed [ - Free . offsetAnnotated 2 1 $ unchanged "a" "leaf" (Leaf ""), - Free . offsetAnnotated 6 3 $ unchanged "b" "leaf" (Leaf "") - ])) sourceA sourceB `shouldBe` - [ - Row (Line [ Ul (Just "category-branch") [ Text "[", Break ] ]) - (Line [ Ul (Just "category-branch") [ Text "[", span "a", Text ",", span "b", Text "]" ] ]), - Row (Line [ Ul (Just "category-branch") [ span "a", Break ] ]) - EmptyLine, - Row (Line [ Ul (Just "category-branch") [ Text ",", Break ] ]) - EmptyLine, - Row (Line [ Ul (Just "category-branch") [ span "b", Text "]" ] ]) - EmptyLine - ] - - it "splits multi-line deletions across multiple rows" $ - let (sourceA, sourceB) = ("/*\n*/\na", "a") in - annotatedToRows (formatted sourceA sourceB "branch" (Indexed [ - Pure . Delete $ (Info (Range 0 5) (Set.fromList ["leaf"]) :< Leaf ""), - Free . offsetAnnotated 6 0 $ unchanged "a" "leaf" (Leaf "") - ])) sourceA sourceB `shouldBe` - [ - Row (Line [ Ul (Just "category-branch") [ Div (Just "delete") [ span "/*", Break ] ] ]) EmptyLine, - Row (Line [ Ul (Just "category-branch") [ Div (Just "delete") [ span "*/" ], Break ] ]) EmptyLine, - Row (Line [ Ul (Just "category-branch") [ span "a" ] ]) (Line [ Ul (Just "category-branch") [ span "a" ] ]) - ] - - describe "unicode" $ - it "equivalent precomposed and decomposed characters are not equal" $ - let (sourceA, sourceB) = ("t\776", "\7831") - syntax = Leaf . Pure $ Replace (info sourceA "leaf" :< Leaf "") (info sourceB "leaf" :< Leaf "") - in - annotatedToRows (formatted sourceA sourceB "leaf" syntax) sourceA sourceB `shouldBe` - [ Row (Line [ span "t\776" ]) (Line [ span "\7831"]) ] - - describe "adjoinRowsBy" $ do prop "is identity on top of no rows" $ \ a -> adjoinRowsBy openElement openElement [] a == [ a ] From ebb843ef4d413d927dda30527da5fc4bb6fefa6f Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 16:29:14 -0500 Subject: [PATCH 191/259] Remove the termToLines test. --- test/SplitSpec.hs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index 60528f73f..1bf993eb8 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -75,15 +75,6 @@ spec = do forAll ((arbitrary `suchThat` isOpen) >>= \ a -> (,) a <$> (arbitrary `suchThat` isOpen)) $ \ (a, b) -> adjoinRowsBy openElement openElement [ Row EmptyLine EmptyLine, a ] b `shouldBe` Row EmptyLine EmptyLine : adjoinRowsBy openElement openElement [ a ] b - describe "termToLines" $ do - it "splits multi-line terms into multiple lines" $ - termToLines (Info (Range 0 5) (Set.singleton "leaf") :< Leaf "") "/*\n*/" - `shouldBe` - ([ - Line [ span "/*", Break ], - Line [ span "*/" ] - ], Range 0 5) - describe "splitTermByLines" $ do it "splits multi-line terms into multiple lines" $ splitTermByLines (Info (Range 0 5) mempty :< Leaf "") "/*\n*/" From bd3bee668aa479ceec779a19c3bafb4c6d2fd420 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 16:34:32 -0500 Subject: [PATCH 192/259] Generalize the splitTermByLines test across arbitrary strings. --- test/SplitSpec.hs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index 1bf993eb8..38de4c30c 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -76,13 +76,9 @@ spec = do \ (a, b) -> adjoinRowsBy openElement openElement [ Row EmptyLine EmptyLine, a ] b `shouldBe` Row EmptyLine EmptyLine : adjoinRowsBy openElement openElement [ a ] b describe "splitTermByLines" $ do - it "splits multi-line terms into multiple lines" $ - splitTermByLines (Info (Range 0 5) mempty :< Leaf "") "/*\n*/" - `shouldBe` - ([ - Line [ Info (Range 0 3) mempty :< Leaf "" ], - Line [ Info (Range 3 5) mempty :< Leaf "" ] - ], Range 0 5) + prop "preserves line count" $ + \ source -> let range = totalRange source in + splitTermByLines (Info range mempty :< Leaf source) source `shouldBe` (Line . (:[]) . (:< Leaf source) . (`Info` mempty) <$> actualLineRanges range source, range) describe "openLineBy" $ do it "produces the earliest non-empty line in a list, if open" $ From bbbd874722b815378fea966e02599496009e5759 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 16:35:23 -0500 Subject: [PATCH 193/259] Remove the openLineBy tests using openElement. --- test/SplitSpec.hs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index 38de4c30c..bbd3b8adb 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -81,24 +81,12 @@ spec = do splitTermByLines (Info range mempty :< Leaf source) source `shouldBe` (Line . (:[]) . (:< Leaf source) . (`Info` mempty) <$> actualLineRanges range source, range) describe "openLineBy" $ do - it "produces the earliest non-empty line in a list, if open" $ - openLineBy openElement [ - Line [ Div (Just "delete") [ span "*/" ] ], - Line [ Div (Just "delete") [ span " * Debugging", Break ] ], - Line [ Div (Just "delete") [ span "/*", Break ] ] - ] `shouldBe` (Just $ Line [ Div (Just "delete") [ span "*/" ] ]) - it "produces the earliest non-empty line in a list, if open" $ openLineBy (openTerm "\n ") [ Line [ Info (Range 1 2) mempty :< Leaf "" ], Line [ Info (Range 0 1) mempty :< Leaf "" ] ] `shouldBe` (Just $ Line [ Info (Range 1 2) mempty :< Leaf "" ]) - it "returns Nothing if the earliest non-empty line is closed" $ - openLineBy openElement [ - Line [ Div (Just "delete") [ span " * Debugging", Break ] ] - ] `shouldBe` Nothing - it "returns Nothing if the earliest non-empty line is closed" $ openLineBy (openTerm "\n") [ Line [ Info (Range 0 1) mempty :< Leaf "" ] From 6607f0d605be76c4d5a18010b501639d4a8ac29f Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 16:39:43 -0500 Subject: [PATCH 194/259] Remove diffToRows & annotatedToRows. --- src/Split.hs | 44 -------------------------------------------- 1 file changed, 44 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 2997bcdea..27eaafb19 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -13,7 +13,6 @@ import Text.Blaze.Html import Text.Blaze.Html5 hiding (map) import qualified Text.Blaze.Html5.Attributes as A import Text.Blaze.Html.Renderer.Utf8 -import qualified OrderedMap as Map import Data.Monoid import qualified Data.Set as Set import Data.List (intercalate) @@ -168,25 +167,6 @@ splitDiffByLines diff (prevLeft, prevRight) sources = case diff of where categories (Info _ left, Info _ right) = (left, right) ranges (Info left _, Info right _) = (left, right) -diffToRows :: Diff a Info -> (Int, Int) -> String -> String -> ([Row HTML], (Range, Range)) -diffToRows (Free annotated@(Annotated (Info left _, Info right _) _)) _ before after = (annotatedToRows annotated before after, (left, right)) -diffToRows (Pure (Insert term)) (previousIndex, _) _ after = (rowWithInsertedLine <$> afterLines, (Range previousIndex previousIndex, range)) - where - (afterLines, range) = termToLines term after - rowWithInsertedLine (Line elements) = Row EmptyLine $ Line [ Div (Just "insert") elements ] - rowWithInsertedLine line = Row line line -diffToRows (Pure (Delete term)) (_, previousIndex) before _ = (rowWithDeletedLine <$> lines, (range, Range previousIndex previousIndex)) - where - (lines, range) = termToLines term before - rowWithDeletedLine (Line elements) = Row (Line [ Div (Just "delete") elements ]) EmptyLine - rowWithDeletedLine line = Row line line -diffToRows (Pure (Replace a b)) _ before after = (replacedRows, (leftRange, rightRange)) - where - replacedRows = zipWithMaybe rowFromMaybeRows (replace <$> leftElements) (replace <$> rightElements) - replace = Div (Just "replace") . unLine - (leftElements, leftRange) = termToLines a before - (rightElements, rightRange) = termToLines b after - -- | Takes a term and a source and returns a list of lines and their range within source. splitTermByLines :: Term a Info -> String -> ([Line (Term a Info)], Range) splitTermByLines (Info range categories :< syntax) source = flip (,) range $ case syntax of @@ -239,30 +219,6 @@ 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) --- | Given an Annotated and before/after strings, returns a list of `Row`s representing the newline-separated diff. -annotatedToRows :: Annotated a (Info, Info) (Diff a Info) -> String -> String -> [Row HTML] -annotatedToRows (Annotated (Info left leftCategories, Info right rightCategories) syntax) before after = rows syntax - where - rows (Leaf _) = zipWithMaybe rowFromMaybeRows leftElements rightElements - rows (Indexed i) = rewrapRowContentsIn Ul <$> childRows i - rows (Fixed f) = rewrapRowContentsIn Ul <$> childRows f - rows (Keyed k) = rewrapRowContentsIn Dl <$> childRows (snd <$> Map.toList k) - - leftElements = elementAndBreak (Span $ classify leftCategories) =<< actualLines (substring left before) - rightElements = elementAndBreak (Span $ classify rightCategories) =<< actualLines (substring right after) - - wrap _ EmptyLine = EmptyLine - wrap f (Line elements) = Line [ f elements ] - rewrapRowContentsIn f (Row left right) = Row (wrap (f $ classify leftCategories) left) (wrap (f $ classify rightCategories) right) - ranges = (left, right) - sources = (before, after) - childRows = appendRemainder . foldl sumRows ([], starts ranges) - appendRemainder (rows, previousIndices) = reverse . foldl (adjoinRowsBy openElement openElement) [] $ rows ++ contextRows (ends ranges) previousIndices sources - starts (left, right) = (start left, start right) - ends (left, right) = (end left, end right) - sumRows (rows, previousIndices) child = let (childRows, childRanges) = diffToRows child previousIndices before after in - (rows ++ contextRows (starts childRanges) previousIndices sources ++ childRows, ends childRanges) - contextLines :: (Info -> a) -> Range -> Set.Set Category -> String -> [Line a] contextLines constructor range categories source = Line . (:[]) . constructor . (`Info` categories) <$> actualLineRanges range source From 39e318317f698f80415b45d5b1d802755bda49ce Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 16:40:20 -0500 Subject: [PATCH 195/259] Remove termToLines. --- src/Split.hs | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 27eaafb19..1b7b1e2c8 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -181,25 +181,6 @@ 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) --- | Takes a term and a source and returns a list of lines and their range within source. -termToLines :: Term a Info -> String -> ([Line HTML], Range) -termToLines (Info range categories :< syntax) source = (rows syntax, range) - where - rows (Leaf _) = adjoin $ Line . (:[]) <$> elements - rows (Indexed i) = rewrapLineContentsIn (Ul $ classify categories) <$> childLines i - rows (Fixed f) = rewrapLineContentsIn (Ul $ classify categories) <$> childLines f - rows (Keyed k) = rewrapLineContentsIn (Dl $ classify categories) <$> childLines k - - adjoin = reverse . foldl (adjoinLinesBy openElement) [] - rewrapLineContentsIn f (Line elements) = Line [ f elements ] - rewrapLineContentsIn _ EmptyLine = EmptyLine - contextLines r s = Line . (:[]) <$> textElements r s - childLines i = let (lines, previous) = foldl sumLines ([], start range) i in - adjoin $ lines ++ contextLines (Range previous (end range)) source - sumLines (lines, previous) child = let (childLines, childRange) = termToLines child source in - (adjoin $ lines ++ contextLines (Range previous $ start childRange) source ++ childLines, end childRange) - elements = elementAndBreak (Span $ classify categories) =<< actualLines (substring range source) - splitAnnotatedByLines :: (String, String) -> (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 From 1f8b9b9ae9a6a20d7b8b8d0b0dd0d0e82e6fb8cc Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 16:41:17 -0500 Subject: [PATCH 196/259] Remove the global contextRows definition. --- src/Split.hs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 1b7b1e2c8..6c2c4b958 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -203,12 +203,6 @@ splitAnnotatedByLines sources ranges categories syntax = case syntax of contextLines :: (Info -> a) -> Range -> Set.Set Category -> String -> [Line a] contextLines constructor range categories source = Line . (:[]) . constructor . (`Info` categories) <$> actualLineRanges range source -contextRows :: (Int, Int) -> (Int, Int) -> (String, String) -> [Row HTML] -contextRows childIndices previousIndices sources = zipWithMaybe rowFromMaybeRows leftElements rightElements - where - leftElements = textElements (Range (fst previousIndices) (fst childIndices)) (fst sources) - rightElements = textElements (Range (snd previousIndices) (snd childIndices)) (snd sources) - elementAndBreak :: (String -> HTML) -> String -> [HTML] elementAndBreak _ "" = [] elementAndBreak _ "\n" = [ Break ] From 4070c8f271f6487e1e577a5de3c7396061a3784a Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 16:41:52 -0500 Subject: [PATCH 197/259] Remove the textElements definition. --- src/Split.hs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 6c2c4b958..dd4a2f9f2 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -209,10 +209,6 @@ elementAndBreak _ "\n" = [ Break ] elementAndBreak constructor x | '\n' <- last x = [ constructor $ init x, Break ] elementAndBreak constructor x = [ constructor x ] -textElements :: Range -> String -> [HTML] -textElements range source = elementAndBreak Text =<< actualLines s - where s = substring range source - rowFromMaybeRows :: Maybe a -> Maybe a -> Row a rowFromMaybeRows a b = Row (maybe EmptyLine (Line . (:[])) a) (maybe EmptyLine (Line . (:[])) b) From c3a9b4f5d1bcd251ec42f3242524443f890133b0 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 16:42:03 -0500 Subject: [PATCH 198/259] Remove the rowFromMaybeRows definition. --- src/Split.hs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index dd4a2f9f2..0ba1d92f4 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -209,9 +209,6 @@ elementAndBreak _ "\n" = [ Break ] elementAndBreak constructor x | '\n' <- last x = [ constructor $ init x, Break ] elementAndBreak constructor x = [ constructor x ] -rowFromMaybeRows :: Maybe a -> Maybe a -> Row a -rowFromMaybeRows a b = Row (maybe EmptyLine (Line . (:[])) a) (maybe EmptyLine (Line . (:[])) b) - maybeLast :: Foldable f => f a -> Maybe a maybeLast = foldl (flip $ const . Just) Nothing From 1d0aecda802a65b16df198b88f823b49811df0a9 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 16:42:27 -0500 Subject: [PATCH 199/259] Remove the zipWithMaybe definition. --- src/Split.hs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 0ba1d92f4..7330e0750 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -265,9 +265,6 @@ adjoinLinesBy f (EmptyLine : xs) line | Just _ <- openLineBy f xs = EmptyLine : adjoinLinesBy f (prev:rest) line | Just _ <- openLineBy f [ prev ] = (prev <> line) : rest adjoinLinesBy _ lines line = line : lines -zipWithMaybe :: (Maybe a -> Maybe b -> c) -> [a] -> [b] -> [c] -zipWithMaybe f a b = zipWithDefaults f Nothing Nothing (Just <$> a) (Just <$> b) - 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) From 97d868ad26d1cbe20993acc99eeabd9b426ad085 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 16:42:57 -0500 Subject: [PATCH 200/259] Remove elementAndBreak. --- src/Split.hs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 7330e0750..6be3765f6 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -203,12 +203,6 @@ splitAnnotatedByLines sources ranges categories syntax = case syntax of contextLines :: (Info -> a) -> Range -> Set.Set Category -> String -> [Line a] contextLines constructor range categories source = Line . (:[]) . constructor . (`Info` categories) <$> actualLineRanges range source -elementAndBreak :: (String -> HTML) -> String -> [HTML] -elementAndBreak _ "" = [] -elementAndBreak _ "\n" = [ Break ] -elementAndBreak constructor x | '\n' <- last x = [ constructor $ init x, Break ] -elementAndBreak constructor x = [ constructor x ] - maybeLast :: Foldable f => f a -> Maybe a maybeLast = foldl (flip $ const . Just) Nothing From 0d33052528a142d62a7e3b7f1883aab8121b3a10 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 16:44:06 -0500 Subject: [PATCH 201/259] Remove the ToMarkup instance for HTML. --- src/Split.hs | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 6be3765f6..9560a6312 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -33,23 +33,6 @@ classifyMarkup :: Maybe ClassName -> Markup -> Markup classifyMarkup (Just className) element = element ! A.class_ (stringValue className) classifyMarkup _ element = element -toLi :: HTML -> Markup -toLi (Text s) = string s -toLi e = li $ toMarkup e - -toDd :: HTML -> Markup -toDd (Text s) = string s -toDd e = dd $ toMarkup e - -instance ToMarkup HTML where - toMarkup Break = br - toMarkup (Text s) = string s - toMarkup (Span className s) = classifyMarkup className . span $ string s - toMarkup (Ul className children) = classifyMarkup className . ul $ mconcat (toLi <$> children) - toMarkup (Dl className children) = classifyMarkup className . dl $ mconcat (toDd <$> children) - toMarkup (Div className children) = classifyMarkup className . div $ mconcat (toMarkup <$> children) - toMarkup (Dt key) = dt $ string key - split :: Diff a Info -> String -> String -> IO ByteString split diff before after = return . renderHtml . docTypeHtml From 3adfd06d5a00ede0265c3181f85fd0422a30e76f Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 16:52:20 -0500 Subject: [PATCH 202/259] Add an open string selector. --- test/SplitSpec.hs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index bbd3b8adb..fba9c52e5 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -120,3 +120,5 @@ spec = do combineIntoLeaves (leaves, start) char = (leaves ++ [ Free $ Annotated (Info (Range start $ start + 1) mempty, Info (Range start $ start + 1) mempty) (Leaf [ char ]) ], start + 1) leafWithRangesInSources sourceA sourceB rangeA rangeB = Free $ Annotated (Info rangeA mempty, Info rangeB mempty) (Leaf $ substring rangeA sourceA ++ substring rangeB sourceB) + + openString string = const string <$> openRange string (totalRange string) From 8599fd46d9f7cbf64798ea15dc69de9156a59e78 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 16:52:36 -0500 Subject: [PATCH 203/259] Test adjoinRowsBy using openString. --- test/SplitSpec.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index fba9c52e5..550c69ce2 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -56,7 +56,7 @@ spec = do describe "adjoinRowsBy" $ do prop "is identity on top of no rows" $ - \ a -> adjoinRowsBy openElement openElement [] a == [ a ] + \ a -> adjoinRowsBy openString openString [] a == [ a ] prop "appends onto open rows" $ forAll ((arbitrary `suchThat` isOpen) >>= \ a -> (,) a <$> (arbitrary `suchThat` isOpen)) $ From 631e572ab3b8e90f9aa3a8ce86d511eabaab6e1d Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 16:55:13 -0500 Subject: [PATCH 204/259] Generalize the isClosed predicate. --- test/SplitSpec.hs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index 550c69ce2..b61a20a53 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -64,11 +64,11 @@ spec = do adjoinRowsBy openElement openElement [ a ] b `shouldBe` [ Row (Line $ a1 ++ a2) (Line $ b1 ++ b2) ] prop "does not append onto closed rows" $ - forAll ((arbitrary `suchThat` isClosed) >>= \ a -> (,) a <$> (arbitrary `suchThat` isClosed)) $ + forAll ((arbitrary `suchThat` isClosedBy openElement) >>= \ a -> (,) a <$> (arbitrary `suchThat` isClosedBy openElement)) $ \ (a, b) -> adjoinRowsBy openElement openElement [ a ] b `shouldBe` [ b, a ] prop "does not promote elements through empty lines onto closed lines" $ - forAll ((arbitrary `suchThat` isClosed) >>= \ a -> (,) a <$> (arbitrary `suchThat` isClosed)) $ + forAll ((arbitrary `suchThat` isClosedBy openElement) >>= \ a -> (,) a <$> (arbitrary `suchThat` isClosedBy openElement)) $ \ (a, b) -> adjoinRowsBy openElement openElement [ Row EmptyLine EmptyLine, a ] b `shouldBe` [ b, Row EmptyLine EmptyLine, a ] prop "promotes elements through empty lines onto open lines" $ @@ -112,8 +112,8 @@ spec = do offsetAnnotated by1 by2 (Annotated (left, right) syntax) = Annotated (offsetInfo by1 left, offsetInfo by2 right) syntax span = Span (Just "category-leaf") isOpen (Row a b) = Maybe.isJust (openLineBy openElement [ a ]) && Maybe.isJust (openLineBy openElement [ b ]) - isClosed (Row a@(Line _) b@(Line _)) = Maybe.isNothing (openLineBy openElement [ a ]) && Maybe.isNothing (openLineBy openElement [ b ]) - isClosed (Row _ _) = False + isClosedBy f (Row a@(Line _) b@(Line _)) = Maybe.isNothing (openLineBy f [ a ]) && Maybe.isNothing (openLineBy f [ b ]) + isClosedBy _ (Row _ _) = False isOnSingleLine (a, _, _) = filter (/= '\n') a == a From cfa82876c1ec008f8e732a9af2d7c68495fe0ffc Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 16:55:18 -0500 Subject: [PATCH 205/259] Generalize the isOpen predicate. --- test/SplitSpec.hs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index b61a20a53..7de74e5f2 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -59,7 +59,7 @@ spec = do \ a -> adjoinRowsBy openString openString [] a == [ a ] prop "appends onto open rows" $ - forAll ((arbitrary `suchThat` isOpen) >>= \ a -> (,) a <$> (arbitrary `suchThat` isOpen)) $ + forAll ((arbitrary `suchThat` isOpenBy openElement) >>= \ a -> (,) a <$> (arbitrary `suchThat` isOpenBy openElement)) $ \ (a@(Row (Line a1) (Line b1)), b@(Row (Line a2) (Line b2))) -> adjoinRowsBy openElement openElement [ a ] b `shouldBe` [ Row (Line $ a1 ++ a2) (Line $ b1 ++ b2) ] @@ -72,7 +72,7 @@ spec = do \ (a, b) -> adjoinRowsBy openElement openElement [ Row EmptyLine EmptyLine, a ] b `shouldBe` [ b, Row EmptyLine EmptyLine, a ] prop "promotes elements through empty lines onto open lines" $ - forAll ((arbitrary `suchThat` isOpen) >>= \ a -> (,) a <$> (arbitrary `suchThat` isOpen)) $ + forAll ((arbitrary `suchThat` isOpenBy openElement) >>= \ a -> (,) a <$> (arbitrary `suchThat` isOpenBy openElement)) $ \ (a, b) -> adjoinRowsBy openElement openElement [ Row EmptyLine EmptyLine, a ] b `shouldBe` Row EmptyLine EmptyLine : adjoinRowsBy openElement openElement [ a ] b describe "splitTermByLines" $ do @@ -111,7 +111,7 @@ spec = do offsetInfo by (Info (Range start end) categories) = Info (Range (start + by) (end + by)) categories offsetAnnotated by1 by2 (Annotated (left, right) syntax) = Annotated (offsetInfo by1 left, offsetInfo by2 right) syntax span = Span (Just "category-leaf") - isOpen (Row a b) = Maybe.isJust (openLineBy openElement [ a ]) && Maybe.isJust (openLineBy openElement [ b ]) + isOpenBy f (Row a b) = Maybe.isJust (openLineBy f [ a ]) && Maybe.isJust (openLineBy f [ b ]) isClosedBy f (Row a@(Line _) b@(Line _)) = Maybe.isNothing (openLineBy f [ a ]) && Maybe.isNothing (openLineBy f [ b ]) isClosedBy _ (Row _ _) = False From 8c71fff97a11f68cfdf2face714d83b57e98f928 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 16:55:53 -0500 Subject: [PATCH 206/259] Test appending onto open rows over strings. --- test/SplitSpec.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index 7de74e5f2..f7581a53d 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -59,9 +59,9 @@ spec = do \ a -> adjoinRowsBy openString openString [] a == [ a ] prop "appends onto open rows" $ - forAll ((arbitrary `suchThat` isOpenBy openElement) >>= \ a -> (,) a <$> (arbitrary `suchThat` isOpenBy openElement)) $ + forAll ((arbitrary `suchThat` isOpenBy openString) >>= \ a -> (,) a <$> (arbitrary `suchThat` isOpenBy openString)) $ \ (a@(Row (Line a1) (Line b1)), b@(Row (Line a2) (Line b2))) -> - adjoinRowsBy openElement openElement [ a ] b `shouldBe` [ Row (Line $ a1 ++ a2) (Line $ b1 ++ b2) ] + adjoinRowsBy openString openString [ a ] b `shouldBe` [ Row (Line $ a1 ++ a2) (Line $ b1 ++ b2) ] prop "does not append onto closed rows" $ forAll ((arbitrary `suchThat` isClosedBy openElement) >>= \ a -> (,) a <$> (arbitrary `suchThat` isClosedBy openElement)) $ From c643f2ed5804934b18bc0350e255258a2beb526a Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 16:56:22 -0500 Subject: [PATCH 207/259] Test not appending onto closed rows over strings. --- test/SplitSpec.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index f7581a53d..50c5a8756 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -64,8 +64,8 @@ spec = do adjoinRowsBy openString openString [ a ] b `shouldBe` [ Row (Line $ a1 ++ a2) (Line $ b1 ++ b2) ] prop "does not append onto closed rows" $ - forAll ((arbitrary `suchThat` isClosedBy openElement) >>= \ a -> (,) a <$> (arbitrary `suchThat` isClosedBy openElement)) $ - \ (a, b) -> adjoinRowsBy openElement openElement [ a ] b `shouldBe` [ b, a ] + forAll ((arbitrary `suchThat` isClosedBy openString) >>= \ a -> (,) a <$> (arbitrary `suchThat` isClosedBy openString)) $ + \ (a, b) -> adjoinRowsBy openString openString [ a ] b `shouldBe` [ b, a ] prop "does not promote elements through empty lines onto closed lines" $ forAll ((arbitrary `suchThat` isClosedBy openElement) >>= \ a -> (,) a <$> (arbitrary `suchThat` isClosedBy openElement)) $ From 208df10e1a16fef679b7e7688d8877e515ee5d08 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 17:02:34 -0500 Subject: [PATCH 208/259] Add an openMaybe function for quicker open/closed tests. --- test/SplitSpec.hs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index 50c5a8756..4abf2eb47 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -122,3 +122,6 @@ spec = do leafWithRangesInSources sourceA sourceB rangeA rangeB = Free $ Annotated (Info rangeA mempty, Info rangeB mempty) (Leaf $ substring rangeA sourceA ++ substring rangeB sourceB) openString string = const string <$> openRange string (totalRange string) + openMaybe :: Maybe String -> Maybe (Maybe String) + openMaybe (Just a) = Just (Just a) + openMaybe Nothing = Nothing From 7b2ac7642217701050ef4ce707323ea420c5c342 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 17:05:02 -0500 Subject: [PATCH 209/259] Test not appending onto closed rows by means of openMaybe. This is much faster. --- test/SplitSpec.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index 4abf2eb47..6f63901c4 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -64,8 +64,8 @@ spec = do adjoinRowsBy openString openString [ a ] b `shouldBe` [ Row (Line $ a1 ++ a2) (Line $ b1 ++ b2) ] prop "does not append onto closed rows" $ - forAll ((arbitrary `suchThat` isClosedBy openString) >>= \ a -> (,) a <$> (arbitrary `suchThat` isClosedBy openString)) $ - \ (a, b) -> adjoinRowsBy openString openString [ a ] b `shouldBe` [ b, a ] + forAll ((arbitrary `suchThat` isClosedBy openMaybe) >>= \ a -> (,) a <$> (arbitrary `suchThat` isClosedBy openMaybe)) $ + \ (a, b) -> adjoinRowsBy openMaybe openMaybe [ a ] b `shouldBe` [ b, a ] prop "does not promote elements through empty lines onto closed lines" $ forAll ((arbitrary `suchThat` isClosedBy openElement) >>= \ a -> (,) a <$> (arbitrary `suchThat` isClosedBy openElement)) $ From 8f34f04dae58f465b2f9fa270df7c86fa7de1902 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 17:05:35 -0500 Subject: [PATCH 210/259] Test not promoting onto closed lines via openMaybe. --- test/SplitSpec.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index 6f63901c4..f61ebf41d 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -68,8 +68,8 @@ spec = do \ (a, b) -> adjoinRowsBy openMaybe openMaybe [ a ] b `shouldBe` [ b, a ] prop "does not promote elements through empty lines onto closed lines" $ - forAll ((arbitrary `suchThat` isClosedBy openElement) >>= \ a -> (,) a <$> (arbitrary `suchThat` isClosedBy openElement)) $ - \ (a, b) -> adjoinRowsBy openElement openElement [ Row EmptyLine EmptyLine, a ] b `shouldBe` [ b, Row EmptyLine EmptyLine, a ] + forAll ((arbitrary `suchThat` isClosedBy openMaybe) >>= \ a -> (,) a <$> (arbitrary `suchThat` isClosedBy openMaybe)) $ + \ (a, b) -> adjoinRowsBy openMaybe openMaybe [ Row EmptyLine EmptyLine, a ] b `shouldBe` [ b, Row EmptyLine EmptyLine, a ] prop "promotes elements through empty lines onto open lines" $ forAll ((arbitrary `suchThat` isOpenBy openElement) >>= \ a -> (,) a <$> (arbitrary `suchThat` isOpenBy openElement)) $ From cfee3a90fcb0490c9a41a247abdbee24b662d149 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 17:06:09 -0500 Subject: [PATCH 211/259] Test promoting onto open lines via openMaybe. --- test/SplitSpec.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index f61ebf41d..e7ee94aad 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -72,8 +72,8 @@ spec = do \ (a, b) -> adjoinRowsBy openMaybe openMaybe [ Row EmptyLine EmptyLine, a ] b `shouldBe` [ b, Row EmptyLine EmptyLine, a ] prop "promotes elements through empty lines onto open lines" $ - forAll ((arbitrary `suchThat` isOpenBy openElement) >>= \ a -> (,) a <$> (arbitrary `suchThat` isOpenBy openElement)) $ - \ (a, b) -> adjoinRowsBy openElement openElement [ Row EmptyLine EmptyLine, a ] b `shouldBe` Row EmptyLine EmptyLine : adjoinRowsBy openElement openElement [ a ] b + forAll ((arbitrary `suchThat` isOpenBy openMaybe) >>= \ a -> (,) a <$> (arbitrary `suchThat` isOpenBy openMaybe)) $ + \ (a, b) -> adjoinRowsBy openMaybe openMaybe [ Row EmptyLine EmptyLine, a ] b `shouldBe` Row EmptyLine EmptyLine : adjoinRowsBy openMaybe openMaybe [ a ] b describe "splitTermByLines" $ do prop "preserves line count" $ From cf00dcd95e7db761706d7e3f9f3266c6b4b0fdf3 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 17:06:45 -0500 Subject: [PATCH 212/259] Test appending onto open rows via openMaybe. --- test/SplitSpec.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index e7ee94aad..b17677c82 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -59,9 +59,9 @@ spec = do \ a -> adjoinRowsBy openString openString [] a == [ a ] prop "appends onto open rows" $ - forAll ((arbitrary `suchThat` isOpenBy openString) >>= \ a -> (,) a <$> (arbitrary `suchThat` isOpenBy openString)) $ + forAll ((arbitrary `suchThat` isOpenBy openMaybe) >>= \ a -> (,) a <$> (arbitrary `suchThat` isOpenBy openMaybe)) $ \ (a@(Row (Line a1) (Line b1)), b@(Row (Line a2) (Line b2))) -> - adjoinRowsBy openString openString [ a ] b `shouldBe` [ Row (Line $ a1 ++ a2) (Line $ b1 ++ b2) ] + adjoinRowsBy openMaybe openMaybe [ a ] b `shouldBe` [ Row (Line $ a1 ++ a2) (Line $ b1 ++ b2) ] prop "does not append onto closed rows" $ forAll ((arbitrary `suchThat` isClosedBy openMaybe) >>= \ a -> (,) a <$> (arbitrary `suchThat` isClosedBy openMaybe)) $ From 821ee2e79287c813253c51bd4ddc1f64159d860c Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 17:06:51 -0500 Subject: [PATCH 213/259] Test the identity case via openMaybe. --- test/SplitSpec.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index b17677c82..818d0a0fa 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -56,7 +56,7 @@ spec = do describe "adjoinRowsBy" $ do prop "is identity on top of no rows" $ - \ a -> adjoinRowsBy openString openString [] a == [ a ] + \ a -> adjoinRowsBy openMaybe openMaybe [] a == [ a ] prop "appends onto open rows" $ forAll ((arbitrary `suchThat` isOpenBy openMaybe) >>= \ a -> (,) a <$> (arbitrary `suchThat` isOpenBy openMaybe)) $ From b121ee54e336958abb353b605ae1f327355456ea Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 17:06:55 -0500 Subject: [PATCH 214/259] Remove openString. --- test/SplitSpec.hs | 1 - 1 file changed, 1 deletion(-) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index 818d0a0fa..9e180a4ac 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -121,7 +121,6 @@ spec = do leafWithRangesInSources sourceA sourceB rangeA rangeB = Free $ Annotated (Info rangeA mempty, Info rangeB mempty) (Leaf $ substring rangeA sourceA ++ substring rangeB sourceB) - openString string = const string <$> openRange string (totalRange string) openMaybe :: Maybe String -> Maybe (Maybe String) openMaybe (Just a) = Just (Just a) openMaybe Nothing = Nothing From 6663dfe87b3583e5f384f1976bf3ea18d45535af Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 17:08:02 -0500 Subject: [PATCH 215/259] openMaybe is defined over Maybe Bool. --- test/SplitSpec.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index 9e180a4ac..843dedf29 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -121,6 +121,6 @@ spec = do leafWithRangesInSources sourceA sourceB rangeA rangeB = Free $ Annotated (Info rangeA mempty, Info rangeB mempty) (Leaf $ substring rangeA sourceA ++ substring rangeB sourceB) - openMaybe :: Maybe String -> Maybe (Maybe String) + openMaybe :: Maybe Bool -> Maybe (Maybe Bool) openMaybe (Just a) = Just (Just a) openMaybe Nothing = Nothing From 52a057b5773ad0d26bd1451adb19a3e98446d6ce Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 17:08:50 -0500 Subject: [PATCH 216/259] Remove the Arbitrary instance for HTML. --- test/SplitSpec.hs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index 843dedf29..eb0d345bd 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -18,12 +18,6 @@ instance Arbitrary a => Arbitrary (Row a) where arbitrary = oneof [ Row <$> arbitrary <*> arbitrary ] -instance Arbitrary HTML where - arbitrary = oneof [ - Text <$> arbitrary, - Span <$> arbitrary <*> arbitrary, - const Break <$> (arbitrary :: Gen ()) ] - instance Arbitrary a => Arbitrary (Line a) where arbitrary = oneof [ Line <$> arbitrary, From 6783d410bb5affd592336013078e01b3c97aa619 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 17:09:32 -0500 Subject: [PATCH 217/259] Remove `openElement`. --- src/Split.hs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 9560a6312..9f9825b18 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -212,13 +212,6 @@ adjoinRowsBy _ g rows (Row left' right') | Just _ <- openLineBy g $ unRight <$> adjoinRowsBy _ _ rows row = row : rows -openElement :: HTML -> Maybe HTML -openElement Break = Nothing -openElement (Ul _ elements) = openElement =<< maybeLast elements -openElement (Dl _ elements) = openElement =<< maybeLast elements -openElement (Div _ elements) = openElement =<< maybeLast elements -openElement h = Just h - openRange :: String -> Range -> Maybe Range openRange source range = case (source !!) <$> maybeLastIndex range of Just '\n' -> Nothing From 3d1fb64cbc717c19128f904b32923b01c5d9abb4 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 17:10:49 -0500 Subject: [PATCH 218/259] Remove `span`. --- test/SplitSpec.hs | 1 - 1 file changed, 1 deletion(-) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index eb0d345bd..019743f99 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -104,7 +104,6 @@ spec = do formatted source1 source2 category = Annotated (info source1 category, info source2 category) offsetInfo by (Info (Range start end) categories) = Info (Range (start + by) (end + by)) categories offsetAnnotated by1 by2 (Annotated (left, right) syntax) = Annotated (offsetInfo by1 left, offsetInfo by2 right) syntax - span = Span (Just "category-leaf") isOpenBy f (Row a b) = Maybe.isJust (openLineBy f [ a ]) && Maybe.isJust (openLineBy f [ b ]) isClosedBy f (Row a@(Line _) b@(Line _)) = Maybe.isNothing (openLineBy f [ a ]) && Maybe.isNothing (openLineBy f [ b ]) isClosedBy _ (Row _ _) = False From ddf4ccd141bd79e0577fccee450e6fd523b66e63 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 17:10:57 -0500 Subject: [PATCH 219/259] Remove the row text functions. --- test/SplitSpec.hs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index 019743f99..17fefc6b4 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -94,11 +94,6 @@ spec = do openTerm " \n" (Info (Range 0 2) mempty :< Leaf "") `shouldBe` Nothing where - rightRowText text = rightRow [ Text text ] - rightRow xs = Row EmptyLine (Line xs) - leftRowText text = leftRow [ Text text ] - leftRow xs = Row (Line xs) EmptyLine - rowText a b = Row (Line [ Text a ]) (Line [ Text b ]) info source category = Info (totalRange source) (Set.fromList [ category ]) unchanged source = formatted source source formatted source1 source2 category = Annotated (info source1 category, info source2 category) From 08d03e933cd5c9c7923be49a5ad4eadba443d69f Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 17:11:49 -0500 Subject: [PATCH 220/259] Remove the term construction helpers. --- test/SplitSpec.hs | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index 17fefc6b4..02ad4b73c 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -94,9 +94,6 @@ spec = do openTerm " \n" (Info (Range 0 2) mempty :< Leaf "") `shouldBe` Nothing where - info source category = Info (totalRange source) (Set.fromList [ category ]) - unchanged source = formatted source source - formatted source1 source2 category = Annotated (info source1 category, info source2 category) offsetInfo by (Info (Range start end) categories) = Info (Range (start + by) (end + by)) categories offsetAnnotated by1 by2 (Annotated (left, right) syntax) = Annotated (offsetInfo by1 left, offsetInfo by2 right) syntax isOpenBy f (Row a b) = Maybe.isJust (openLineBy f [ a ]) && Maybe.isJust (openLineBy f [ b ]) From 1621dca3bc70b85d5f48fa490ac7cad16cc444dd Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 17:12:08 -0500 Subject: [PATCH 221/259] Remove the offset functions. --- test/SplitSpec.hs | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index 02ad4b73c..cdfd8e424 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -94,8 +94,6 @@ spec = do openTerm " \n" (Info (Range 0 2) mempty :< Leaf "") `shouldBe` Nothing where - offsetInfo by (Info (Range start end) categories) = Info (Range (start + by) (end + by)) categories - offsetAnnotated by1 by2 (Annotated (left, right) syntax) = Annotated (offsetInfo by1 left, offsetInfo by2 right) syntax isOpenBy f (Row a b) = Maybe.isJust (openLineBy f [ a ]) && Maybe.isJust (openLineBy f [ b ]) isClosedBy f (Row a@(Line _) b@(Line _)) = Maybe.isNothing (openLineBy f [ a ]) && Maybe.isNothing (openLineBy f [ b ]) isClosedBy _ (Row _ _) = False From e7196262168248ab2fe1564bf07fda44346d5f8c Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 17:12:56 -0500 Subject: [PATCH 222/259] Remove HTML. --- src/Split.hs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 9f9825b18..fb9de7f65 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -19,16 +19,6 @@ import Data.List (intercalate) type ClassName = String -data HTML = - Break - | Text String - | Span (Maybe ClassName) String - | Ul (Maybe ClassName) [HTML] - | Dl (Maybe ClassName) [HTML] - | Div (Maybe ClassName) [HTML] - | Dt String - deriving (Show, Eq) - classifyMarkup :: Maybe ClassName -> Markup -> Markup classifyMarkup (Just className) element = element ! A.class_ (stringValue className) classifyMarkup _ element = element From 24d22042d10f1677b9ddb03bca2ad34a106d2ed0 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 17:18:17 -0500 Subject: [PATCH 223/259] `classifyMarkup` takes categories directly. --- src/Split.hs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index fb9de7f65..190040b45 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -19,9 +19,8 @@ import Data.List (intercalate) type ClassName = String -classifyMarkup :: Maybe ClassName -> Markup -> Markup -classifyMarkup (Just className) element = element ! A.class_ (stringValue className) -classifyMarkup _ element = element +classifyMarkup :: Foldable f => f String -> Markup -> Markup +classifyMarkup categories element = maybe element ((element !) . A.class_ . stringValue . ("category-" ++)) $ maybeLast categories split :: Diff a Info -> String -> String -> IO ByteString split diff before after = return . renderHtml @@ -108,7 +107,7 @@ type SplitDiff leaf annotation = Free (Annotated leaf annotation) (Term leaf ann newtype Renderable a = Renderable (String, a) instance ToMarkup f => ToMarkup (Renderable (Info, Syntax a (f, Range))) where - toMarkup (Renderable (source, (Info range categories, syntax))) = classifyMarkup (classify categories) $ case syntax of + toMarkup (Renderable (source, (Info range categories, syntax))) = classifyMarkup categories $ case syntax of Leaf _ -> span . string $ substring range source Indexed children -> ul . mconcat $ contentElements children Fixed children -> ul . mconcat $ contentElements children From ce2c759fea6e3786d96ea742408b5d62916b3d57 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 17:18:27 -0500 Subject: [PATCH 224/259] Remove `classify`. --- src/Split.hs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 190040b45..6ebf5f81e 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -227,9 +227,6 @@ adjoinLinesBy _ lines line = line : lines 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) -classify :: Set.Set Category -> Maybe ClassName -classify categories = ("category-" ++) <$> maybeLast categories - actualLines :: String -> [String] actualLines "" = [""] actualLines lines = case break (== '\n') lines of From 8f469a07c4c089bbb4fd1dab0bd5ba4816ce1db9 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 17:20:08 -0500 Subject: [PATCH 225/259] Stub in a Line module. --- semantic-diff.cabal | 1 + src/Line.hs | 1 + 2 files changed, 2 insertions(+) create mode 100644 src/Line.hs diff --git a/semantic-diff.cabal b/semantic-diff.cabal index 1bd11f497..3d5f56637 100644 --- a/semantic-diff.cabal +++ b/semantic-diff.cabal @@ -18,6 +18,7 @@ library , Operation , Algorithm , Interpreter + , Line , OrderedMap , Patch , SES diff --git a/src/Line.hs b/src/Line.hs new file mode 100644 index 000000000..3b9f94392 --- /dev/null +++ b/src/Line.hs @@ -0,0 +1 @@ +module Line where From 4a39f65fdf2f10489263d9f348a7b7c3313470eb Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 17:21:17 -0500 Subject: [PATCH 226/259] Move Line to its own file. --- src/Line.hs | 22 ++++++++++++++++++++++ src/Split.hs | 21 +-------------------- 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/src/Line.hs b/src/Line.hs index 3b9f94392..5c416a94f 100644 --- a/src/Line.hs +++ b/src/Line.hs @@ -1 +1,23 @@ module Line where + +import Data.Monoid +import Data.List (intercalate) + +data Line a = + Line [a] + | EmptyLine + deriving (Eq, Functor) + +unLine :: Line a -> [a] +unLine EmptyLine = [] +unLine (Line elements) = elements + +instance Show a => Show (Line a) where + show (Line elements) = "[" ++ intercalate ", " (show <$> elements) ++ "]" + show EmptyLine = "EmptyLine" + +instance Monoid (Line a) where + mempty = EmptyLine + mappend EmptyLine line = line + mappend line EmptyLine = line + mappend (Line xs) (Line ys) = Line (xs <> ys) diff --git a/src/Split.hs b/src/Split.hs index 6ebf5f81e..ddcdb9698 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -2,6 +2,7 @@ module Split where import Prelude hiding (div, head, span) import Diff +import Line import Patch import Term import Syntax @@ -15,7 +16,6 @@ import qualified Text.Blaze.Html5.Attributes as A import Text.Blaze.Html.Renderer.Utf8 import Data.Monoid import qualified Data.Set as Set -import Data.List (intercalate) type ClassName = String @@ -82,25 +82,6 @@ instance ToMarkup a => ToMarkup (Line a) where toMarkup EmptyLine = codeTd False Nothing toMarkup (Line contents) = codeTd False . Just . mconcat $ toMarkup <$> contents -data Line a = - Line [a] - | EmptyLine - deriving (Eq, Functor) - -unLine :: Line a -> [a] -unLine EmptyLine = [] -unLine (Line elements) = elements - -instance Show a => Show (Line a) where - show (Line elements) = "[" ++ intercalate ", " (show <$> elements) ++ "]" - show EmptyLine = "EmptyLine" - -instance Monoid (Line a) where - mempty = EmptyLine - mappend EmptyLine line = line - mappend line EmptyLine = line - mappend (Line xs) (Line ys) = Line (xs <> ys) - -- | A diff with only one side’s annotations. type SplitDiff leaf annotation = Free (Annotated leaf annotation) (Term leaf annotation) From 4c395ff1d1a38409371fad356e060d073e464d96 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 17:22:07 -0500 Subject: [PATCH 227/259] Import the Line module in the tests. --- test/SplitSpec.hs | 1 + 1 file changed, 1 insertion(+) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index cdfd8e424..286c01bb7 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -10,6 +10,7 @@ import Test.QuickCheck hiding (Fixed) import Control.Comonad.Cofree import Control.Monad.Free hiding (unfold) import qualified Data.Maybe as Maybe +import Line import Patch import Syntax import ArbitraryTerm From cdaea42fd2d2ef150540472c91c363b0e3244543 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 17:23:10 -0500 Subject: [PATCH 228/259] Move the ToMarkup instances over Line to the Line module. --- src/Line.hs | 23 +++++++++++++++++++++++ src/Split.hs | 21 --------------------- 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/src/Line.hs b/src/Line.hs index 5c416a94f..ee546a155 100644 --- a/src/Line.hs +++ b/src/Line.hs @@ -2,6 +2,8 @@ module Line where import Data.Monoid import Data.List (intercalate) +import Text.Blaze.Html5 hiding (map) +import qualified Text.Blaze.Html5.Attributes as A data Line a = Line [a] @@ -21,3 +23,24 @@ instance Monoid (Line a) where mappend EmptyLine line = line mappend line EmptyLine = line mappend (Line xs) (Line ys) = Line (xs <> ys) + +instance ToMarkup a => ToMarkup (Int, Line a, Int, Line a) where + toMarkup (m, left, n, right) = tr $ toMarkup (m, left) <> toMarkup (n, right) <> string "\n" + +instance ToMarkup a => ToMarkup (Int, Line a) where + toMarkup (_, line@EmptyLine) = numberTd "" <> toMarkup line <> string "\n" + -- toMarkup (num, line@(Line _)) = td (string $ show num) ! A.class_ (stringValue "blob-num blob-num-replacement") <> toMarkup line <> string "\n" + toMarkup (num, line@(Line _)) = numberTd (show num) <> toMarkup line <> string "\n" + +numberTd :: String -> Html +numberTd "" = td mempty ! A.class_ (stringValue "blob-num blob-num-empty empty-cell") +numberTd s = td (string s) ! A.class_ (stringValue "blob-num") + +codeTd :: Bool -> Maybe Html -> Html +codeTd _ Nothing = td mempty ! A.class_ (stringValue "blob-code blob-code-empty empty-cell") +codeTd True (Just el) = td el ! A.class_ (stringValue "blob-code blob-code-replacement") +codeTd False (Just el) = td el ! A.class_ (stringValue "blob-code") + +instance ToMarkup a => ToMarkup (Line a) where + toMarkup EmptyLine = codeTd False Nothing + toMarkup (Line contents) = codeTd False . Just . mconcat $ toMarkup <$> contents diff --git a/src/Split.hs b/src/Split.hs index ddcdb9698..d927f1d2f 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -61,27 +61,6 @@ data Row a = Row { unLeft :: Line a, unRight :: Line a } instance Show a => Show (Row a) where show (Row left right) = "\n" ++ show left ++ " | " ++ show right -instance ToMarkup a => ToMarkup (Int, Line a, Int, Line a) where - toMarkup (m, left, n, right) = tr $ toMarkup (m, left) <> toMarkup (n, right) <> string "\n" - -instance ToMarkup a => ToMarkup (Int, Line a) where - toMarkup (_, line@EmptyLine) = numberTd "" <> toMarkup line <> string "\n" - -- toMarkup (num, line@(Line _)) = td (string $ show num) ! A.class_ (stringValue "blob-num blob-num-replacement") <> toMarkup line <> string "\n" - toMarkup (num, line@(Line _)) = numberTd (show num) <> toMarkup line <> string "\n" - -numberTd :: String -> Html -numberTd "" = td mempty ! A.class_ (stringValue "blob-num blob-num-empty empty-cell") -numberTd s = td (string s) ! A.class_ (stringValue "blob-num") - -codeTd :: Bool -> Maybe Html -> Html -codeTd _ Nothing = td mempty ! A.class_ (stringValue "blob-code blob-code-empty empty-cell") -codeTd True (Just el) = td el ! A.class_ (stringValue "blob-code blob-code-replacement") -codeTd False (Just el) = td el ! A.class_ (stringValue "blob-code") - -instance ToMarkup a => ToMarkup (Line a) where - toMarkup EmptyLine = codeTd False Nothing - toMarkup (Line contents) = codeTd False . Just . mconcat $ toMarkup <$> contents - -- | A diff with only one side’s annotations. type SplitDiff leaf annotation = Free (Annotated leaf annotation) (Term leaf annotation) From b256d46f836e467c0cacd1a9b6b08b64b9553a5c Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 17:24:08 -0500 Subject: [PATCH 229/259] Stub in a Row module. --- semantic-diff.cabal | 1 + src/Row.hs | 1 + 2 files changed, 2 insertions(+) create mode 100644 src/Row.hs diff --git a/semantic-diff.cabal b/semantic-diff.cabal index 3d5f56637..156bd94d8 100644 --- a/semantic-diff.cabal +++ b/semantic-diff.cabal @@ -19,6 +19,7 @@ library , Algorithm , Interpreter , Line + , Row , OrderedMap , Patch , SES diff --git a/src/Row.hs b/src/Row.hs new file mode 100644 index 000000000..c1e73784f --- /dev/null +++ b/src/Row.hs @@ -0,0 +1 @@ +module Row where From e2cc92bdf7be2d604e48d65edf3336c82c6771e8 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 17:24:58 -0500 Subject: [PATCH 230/259] Move Row into the Row module. --- src/Row.hs | 8 ++++++++ src/Split.hs | 8 +------- test/SplitSpec.hs | 1 + 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/Row.hs b/src/Row.hs index c1e73784f..52b6982f3 100644 --- a/src/Row.hs +++ b/src/Row.hs @@ -1 +1,9 @@ module Row where + +import Line + +data Row a = Row { unLeft :: Line a, unRight :: Line a } + deriving (Eq, Functor) + +instance Show a => Show (Row a) where + show (Row left right) = "\n" ++ show left ++ " | " ++ show right diff --git a/src/Split.hs b/src/Split.hs index d927f1d2f..80adf34c9 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -3,6 +3,7 @@ module Split where import Prelude hiding (div, head, span) import Diff import Line +import Row import Patch import Term import Syntax @@ -54,13 +55,6 @@ split diff before after = return . renderHtml numberRows rows@((leftCount, _, rightCount, _):_) (Row EmptyLine right@(Line _)) = (leftCount, EmptyLine, rightCount + 1, right):rows numberRows rows@((leftCount, _, rightCount, _):_) (Row left right) = (leftCount + 1, left, rightCount + 1, right):rows - -data Row a = Row { unLeft :: Line a, unRight :: Line a } - deriving (Eq, Functor) - -instance Show a => Show (Row a) where - show (Row left right) = "\n" ++ show left ++ " | " ++ show right - -- | A diff with only one side’s annotations. type SplitDiff leaf annotation = Free (Annotated leaf annotation) (Term leaf annotation) diff --git a/test/SplitSpec.hs b/test/SplitSpec.hs index 286c01bb7..da8b89344 100644 --- a/test/SplitSpec.hs +++ b/test/SplitSpec.hs @@ -11,6 +11,7 @@ import Control.Comonad.Cofree import Control.Monad.Free hiding (unfold) import qualified Data.Maybe as Maybe import Line +import Row import Patch import Syntax import ArbitraryTerm From 74fbc6e5395e50213335e9b5b6715e291ea8a7d4 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 17:26:24 -0500 Subject: [PATCH 231/259] Move openLineBy into the Line module. --- src/Line.hs | 8 ++++++++ src/Split.hs | 8 -------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Line.hs b/src/Line.hs index ee546a155..4f5c84c27 100644 --- a/src/Line.hs +++ b/src/Line.hs @@ -14,6 +14,14 @@ unLine :: Line a -> [a] unLine EmptyLine = [] unLine (Line elements) = elements +maybeLast :: Foldable f => f a -> Maybe a +maybeLast = foldl (flip $ const . Just) Nothing + +openLineBy :: (a -> Maybe a) -> [Line a] -> Maybe (Line a) +openLineBy _ [] = Nothing +openLineBy f (EmptyLine : rest) = openLineBy f rest +openLineBy f (line : _) = const line <$> (f =<< maybeLast (unLine line)) + instance Show a => Show (Line a) where show (Line elements) = "[" ++ intercalate ", " (show <$> elements) ++ "]" show EmptyLine = "EmptyLine" diff --git a/src/Split.hs b/src/Split.hs index 80adf34c9..d826dccdd 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -129,9 +129,6 @@ splitAnnotatedByLines sources ranges categories syntax = case syntax of contextLines :: (Info -> a) -> Range -> Set.Set Category -> String -> [Line a] contextLines constructor range categories source = Line . (:[]) . constructor . (`Info` categories) <$> actualLineRanges range source -maybeLast :: Foldable f => f a -> Maybe a -maybeLast = foldl (flip $ const . Just) Nothing - adjoinRowsBy :: (a -> Maybe a) -> (a -> Maybe a) -> [Row a] -> Row a -> [Row a] adjoinRowsBy _ _ [] row = [row] @@ -167,11 +164,6 @@ openDiff :: String -> 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 -openLineBy :: (a -> Maybe a) -> [Line a] -> Maybe (Line a) -openLineBy _ [] = Nothing -openLineBy f (EmptyLine : rest) = openLineBy f rest -openLineBy f (line : _) = const line <$> (f =<< maybeLast (unLine line)) - adjoinLinesBy :: (a -> Maybe a) -> [Line a] -> Line a -> [Line a] adjoinLinesBy _ [] line = [line] adjoinLinesBy f (EmptyLine : xs) line | Just _ <- openLineBy f xs = EmptyLine : adjoinLinesBy f xs line From c92ba49b4d4a4e963928cc2facd42aa82fc0485c Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 17:27:09 -0500 Subject: [PATCH 232/259] Move adjoinLinesBy into the Line module. --- src/Line.hs | 6 ++++++ src/Split.hs | 6 ------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Line.hs b/src/Line.hs index 4f5c84c27..945536e40 100644 --- a/src/Line.hs +++ b/src/Line.hs @@ -22,6 +22,12 @@ openLineBy _ [] = Nothing openLineBy f (EmptyLine : rest) = openLineBy f rest openLineBy f (line : _) = const line <$> (f =<< maybeLast (unLine line)) +adjoinLinesBy :: (a -> Maybe a) -> [Line a] -> Line a -> [Line a] +adjoinLinesBy _ [] line = [line] +adjoinLinesBy f (EmptyLine : xs) line | Just _ <- openLineBy f xs = EmptyLine : adjoinLinesBy f xs line +adjoinLinesBy f (prev:rest) line | Just _ <- openLineBy f [ prev ] = (prev <> line) : rest +adjoinLinesBy _ lines line = line : lines + instance Show a => Show (Line a) where show (Line elements) = "[" ++ intercalate ", " (show <$> elements) ++ "]" show EmptyLine = "EmptyLine" diff --git a/src/Split.hs b/src/Split.hs index d826dccdd..4d5c19a1f 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -164,12 +164,6 @@ openDiff :: String -> 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 -adjoinLinesBy :: (a -> Maybe a) -> [Line a] -> Line a -> [Line a] -adjoinLinesBy _ [] line = [line] -adjoinLinesBy f (EmptyLine : xs) line | Just _ <- openLineBy f xs = EmptyLine : adjoinLinesBy f xs line -adjoinLinesBy f (prev:rest) line | Just _ <- openLineBy f [ prev ] = (prev <> line) : rest -adjoinLinesBy _ lines line = line : lines - 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) From b1659945697c447e8f0f56a54cae60252d02ef1d Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 17:27:56 -0500 Subject: [PATCH 233/259] Move adjoinRowsBy into the Row module. --- src/Row.hs | 24 ++++++++++++++++++++++++ src/Split.hs | 23 ----------------------- 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/src/Row.hs b/src/Row.hs index 52b6982f3..4fbbaa121 100644 --- a/src/Row.hs +++ b/src/Row.hs @@ -5,5 +5,29 @@ import Line data Row a = Row { unLeft :: Line a, unRight :: Line a } deriving (Eq, Functor) +adjoinRowsBy :: (a -> Maybe a) -> (a -> Maybe a) -> [Row a] -> Row a -> [Row a] +adjoinRowsBy _ _ [] row = [row] + +adjoinRowsBy f g rows (Row left' right') | Just _ <- openLineBy f $ unLeft <$> rows, Just _ <- openLineBy g $ unRight <$> rows = zipWith Row lefts rights + where lefts = adjoinLinesBy f (unLeft <$> rows) left' + rights = adjoinLinesBy g (unRight <$> rows) right' + +adjoinRowsBy f _ rows (Row left' right') | Just _ <- openLineBy f $ unLeft <$> rows = case right' of + EmptyLine -> rest + _ -> Row EmptyLine right' : rest + where rest = zipWith Row lefts rights + lefts = adjoinLinesBy f (unLeft <$> rows) left' + rights = unRight <$> rows + +adjoinRowsBy _ g rows (Row left' right') | Just _ <- openLineBy g $ unRight <$> rows = case left' of + EmptyLine -> rest + _ -> Row left' EmptyLine : rest + where rest = zipWith Row lefts rights + lefts = unLeft <$> rows + rights = adjoinLinesBy g (unRight <$> rows) right' + +adjoinRowsBy _ _ rows row = row : rows + + instance Show a => Show (Row a) where show (Row left right) = "\n" ++ show left ++ " | " ++ show right diff --git a/src/Split.hs b/src/Split.hs index 4d5c19a1f..73e7722f5 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -129,29 +129,6 @@ splitAnnotatedByLines sources ranges categories syntax = case syntax of contextLines :: (Info -> a) -> Range -> Set.Set Category -> String -> [Line a] contextLines constructor range categories source = Line . (:[]) . constructor . (`Info` categories) <$> actualLineRanges range source -adjoinRowsBy :: (a -> Maybe a) -> (a -> Maybe a) -> [Row a] -> Row a -> [Row a] -adjoinRowsBy _ _ [] row = [row] - -adjoinRowsBy f g rows (Row left' right') | Just _ <- openLineBy f $ unLeft <$> rows, Just _ <- openLineBy g $ unRight <$> rows = zipWith Row lefts rights - where lefts = adjoinLinesBy f (unLeft <$> rows) left' - rights = adjoinLinesBy g (unRight <$> rows) right' - -adjoinRowsBy f _ rows (Row left' right') | Just _ <- openLineBy f $ unLeft <$> rows = case right' of - EmptyLine -> rest - _ -> Row EmptyLine right' : rest - where rest = zipWith Row lefts rights - lefts = adjoinLinesBy f (unLeft <$> rows) left' - rights = unRight <$> rows - -adjoinRowsBy _ g rows (Row left' right') | Just _ <- openLineBy g $ unRight <$> rows = case left' of - EmptyLine -> rest - _ -> Row left' EmptyLine : rest - where rest = zipWith Row lefts rights - lefts = unLeft <$> rows - rights = adjoinLinesBy g (unRight <$> rows) right' - -adjoinRowsBy _ _ rows row = row : rows - openRange :: String -> Range -> Maybe Range openRange source range = case (source !!) <$> maybeLastIndex range of Just '\n' -> Nothing From 7e98ee3de59b99258937a552e2244e6082452e13 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 17:53:47 -0500 Subject: [PATCH 234/259] Add a function to map a line into a Renderable line. --- src/Split.hs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Split.hs b/src/Split.hs index 73e7722f5..ba7ab5a43 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -33,7 +33,7 @@ split diff before after = return . renderHtml . mconcat $ toMarkup <$> reverse numbered where rows = toRenderable <$> fst (splitDiffByLines diff (0, 0) (before, after)) - toRenderable (Row a b) = Row (Renderable . (,) before <$> a) (Renderable . (,) after <$> b) + toRenderable (Row a b) = Row (renderable before a) (renderable after b) numbered = foldl numberRows [] rows maxNumber = case numbered of [] -> 0 @@ -45,6 +45,8 @@ split diff before after = return . renderHtml columnWidth = max (20 + digits maxNumber * 8) 40 + renderable source = fmap (Renderable . (,) source) + numberRows :: [(Int, Line a, Int, Line a)] -> Row a -> [(Int, Line a, Int, Line a)] numberRows [] (Row EmptyLine EmptyLine) = [] numberRows [] (Row left@(Line _) EmptyLine) = [(1, left, 0, EmptyLine)] From e9c7c46130d2b493b8d4ef6f0925abd3e8d2d1e8 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 17:54:01 -0500 Subject: [PATCH 235/259] Add a function to test for changes in a diff. --- src/Split.hs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Split.hs b/src/Split.hs index ba7ab5a43..9b469dcbd 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -47,6 +47,8 @@ split diff before after = return . renderHtml renderable source = fmap (Renderable . (,) source) + hasChanges diff = foldl (||) False $ const True <$> diff + numberRows :: [(Int, Line a, Int, Line a)] -> Row a -> [(Int, Line a, Int, Line a)] numberRows [] (Row EmptyLine EmptyLine) = [] numberRows [] (Row left@(Line _) EmptyLine) = [(1, left, 0, EmptyLine)] From b89218a94476433f1b126ec47213ed33c21d53bf Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 17:55:03 -0500 Subject: [PATCH 236/259] Add a ToMarkup instance over Bool/Int/Line a triples. --- src/Line.hs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Line.hs b/src/Line.hs index 945536e40..88b72b4d8 100644 --- a/src/Line.hs +++ b/src/Line.hs @@ -45,6 +45,10 @@ instance ToMarkup a => ToMarkup (Int, Line a) where toMarkup (_, line@EmptyLine) = numberTd "" <> toMarkup line <> string "\n" -- toMarkup (num, line@(Line _)) = td (string $ show num) ! A.class_ (stringValue "blob-num blob-num-replacement") <> toMarkup line <> string "\n" toMarkup (num, line@(Line _)) = numberTd (show num) <> toMarkup line <> string "\n" +instance ToMarkup a => ToMarkup (Bool, Int, Line a) where + toMarkup (_, _, line@EmptyLine) = numberTd "" <> toMarkup line <> string "\n" + toMarkup (True, num, line@(Line _)) = td (string $ show num) ! A.class_ (stringValue "blob-num blob-num-replacement") <> toMarkup line <> string "\n" + toMarkup (_, num, line@(Line _)) = numberTd (show num) <> toMarkup line <> string "\n" numberTd :: String -> Html numberTd "" = td mempty ! A.class_ (stringValue "blob-num blob-num-empty empty-cell") From e974ea43af09dc185044bc163622f1e6d045c019 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 17:55:30 -0500 Subject: [PATCH 237/259] Add a function to render numbered lines to markup with indication of changes. --- src/Split.hs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Split.hs b/src/Split.hs index 9b469dcbd..87b9311bf 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -45,6 +45,9 @@ split diff before after = return . renderHtml columnWidth = max (20 + digits maxNumber * 8) 40 + numberedLinesToMarkup :: (Int, Line (SplitDiff a Info), Int, Line (SplitDiff a Info)) -> Markup + numberedLinesToMarkup (m, left, n, right) = tr $ toMarkup (foldl (||) False $ hasChanges <$> unLine left, m, renderable before left) <> toMarkup (foldl (||) False $ hasChanges <$> unLine right, n, renderable after right) <> string "\n" + renderable source = fmap (Renderable . (,) source) hasChanges diff = foldl (||) False $ const True <$> diff From 44e04ec17f739cb30edc4bf857afc5e163431aa8 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 17:55:54 -0500 Subject: [PATCH 238/259] Render numbered lines to markup using the new function. --- src/Split.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 87b9311bf..c07108baf 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -30,9 +30,9 @@ split diff before after = return . renderHtml . body . (table ! A.class_ (stringValue "diff")) $ ((colgroup $ (col ! A.width (stringValue . show $ columnWidth)) <> col <> (col ! A.width (stringValue . show $ columnWidth)) <> col) <>) - . mconcat $ toMarkup <$> reverse numbered + . mconcat $ numberedLinesToMarkup <$> reverse numbered where - rows = toRenderable <$> fst (splitDiffByLines diff (0, 0) (before, after)) + rows = fst (splitDiffByLines diff (0, 0) (before, after)) toRenderable (Row a b) = Row (renderable before a) (renderable after b) numbered = foldl numberRows [] rows maxNumber = case numbered of From 02afbd132a03a7c6f937097f69dc5f753ebc0d91 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 17:56:10 -0500 Subject: [PATCH 239/259] Remove the Int, Line, Int, Line instance of ToMarkup. --- src/Line.hs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Line.hs b/src/Line.hs index 88b72b4d8..f933aa303 100644 --- a/src/Line.hs +++ b/src/Line.hs @@ -38,9 +38,6 @@ instance Monoid (Line a) where mappend line EmptyLine = line mappend (Line xs) (Line ys) = Line (xs <> ys) -instance ToMarkup a => ToMarkup (Int, Line a, Int, Line a) where - toMarkup (m, left, n, right) = tr $ toMarkup (m, left) <> toMarkup (n, right) <> string "\n" - instance ToMarkup a => ToMarkup (Int, Line a) where toMarkup (_, line@EmptyLine) = numberTd "" <> toMarkup line <> string "\n" -- toMarkup (num, line@(Line _)) = td (string $ show num) ! A.class_ (stringValue "blob-num blob-num-replacement") <> toMarkup line <> string "\n" From c83c67cc9932d04a6c8c2337c21ce7e92f121576 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 17:56:19 -0500 Subject: [PATCH 240/259] Remove the Int, Line pair instance of ToMarkup. --- src/Line.hs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Line.hs b/src/Line.hs index f933aa303..dbf1359ad 100644 --- a/src/Line.hs +++ b/src/Line.hs @@ -38,10 +38,6 @@ instance Monoid (Line a) where mappend line EmptyLine = line mappend (Line xs) (Line ys) = Line (xs <> ys) -instance ToMarkup a => ToMarkup (Int, Line a) where - toMarkup (_, line@EmptyLine) = numberTd "" <> toMarkup line <> string "\n" - -- toMarkup (num, line@(Line _)) = td (string $ show num) ! A.class_ (stringValue "blob-num blob-num-replacement") <> toMarkup line <> string "\n" - toMarkup (num, line@(Line _)) = numberTd (show num) <> toMarkup line <> string "\n" instance ToMarkup a => ToMarkup (Bool, Int, Line a) where toMarkup (_, _, line@EmptyLine) = numberTd "" <> toMarkup line <> string "\n" toMarkup (True, num, line@(Line _)) = td (string $ show num) ! A.class_ (stringValue "blob-num blob-num-replacement") <> toMarkup line <> string "\n" From b25da81f81d233ef9d623de4934414329550a93a Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 17:56:28 -0500 Subject: [PATCH 241/259] Remove toRenderable. --- src/Split.hs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Split.hs b/src/Split.hs index c07108baf..751576a2e 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -33,7 +33,6 @@ split diff before after = return . renderHtml . mconcat $ numberedLinesToMarkup <$> reverse numbered where rows = fst (splitDiffByLines diff (0, 0) (before, after)) - toRenderable (Row a b) = Row (renderable before a) (renderable after b) numbered = foldl numberRows [] rows maxNumber = case numbered of [] -> 0 From 946b1067b3478a7298afb14b1fb8296b31644c8b Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 17:57:16 -0500 Subject: [PATCH 242/259] Use `or` to test for changes. --- src/Split.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Split.hs b/src/Split.hs index 751576a2e..6a06d27ba 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -45,11 +45,11 @@ split diff before after = return . renderHtml columnWidth = max (20 + digits maxNumber * 8) 40 numberedLinesToMarkup :: (Int, Line (SplitDiff a Info), Int, Line (SplitDiff a Info)) -> Markup - numberedLinesToMarkup (m, left, n, right) = tr $ toMarkup (foldl (||) False $ hasChanges <$> unLine left, m, renderable before left) <> toMarkup (foldl (||) False $ hasChanges <$> unLine right, n, renderable after right) <> string "\n" + numberedLinesToMarkup (m, left, n, right) = tr $ toMarkup (or $ hasChanges <$> unLine left, m, renderable before left) <> toMarkup (or $ hasChanges <$> unLine right, n, renderable after right) <> string "\n" renderable source = fmap (Renderable . (,) source) - hasChanges diff = foldl (||) False $ const True <$> diff + hasChanges diff = or $ const True <$> diff numberRows :: [(Int, Line a, Int, Line a)] -> Row a -> [(Int, Line a, Int, Line a)] numberRows [] (Row EmptyLine EmptyLine) = [] From cd5abba7435ed46a04c6b42fc077c7b9527753b4 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 17:58:11 -0500 Subject: [PATCH 243/259] Derive a Foldable instance for Line. --- src/Line.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Line.hs b/src/Line.hs index dbf1359ad..e33c13e90 100644 --- a/src/Line.hs +++ b/src/Line.hs @@ -8,7 +8,7 @@ import qualified Text.Blaze.Html5.Attributes as A data Line a = Line [a] | EmptyLine - deriving (Eq, Functor) + deriving (Eq, Functor, Foldable) unLine :: Line a -> [a] unLine EmptyLine = [] From 9b87a785b5ffdd71b9330854ef34a047a989c44b Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 17:59:26 -0500 Subject: [PATCH 244/259] No need to unLine. --- src/Split.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Split.hs b/src/Split.hs index 6a06d27ba..4580fd0ea 100644 --- a/src/Split.hs +++ b/src/Split.hs @@ -45,7 +45,7 @@ split diff before after = return . renderHtml columnWidth = max (20 + digits maxNumber * 8) 40 numberedLinesToMarkup :: (Int, Line (SplitDiff a Info), Int, Line (SplitDiff a Info)) -> Markup - numberedLinesToMarkup (m, left, n, right) = tr $ toMarkup (or $ hasChanges <$> unLine left, m, renderable before left) <> toMarkup (or $ hasChanges <$> unLine right, n, renderable after right) <> string "\n" + numberedLinesToMarkup (m, left, n, right) = tr $ toMarkup (or $ hasChanges <$> left, m, renderable before left) <> toMarkup (or $ hasChanges <$> right, n, renderable after right) <> string "\n" renderable source = fmap (Renderable . (,) source) From 6c6139aac90502f85bbd0724a1996c18dac72da0 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 18:06:42 -0500 Subject: [PATCH 245/259] =?UTF-8?q?Don=E2=80=99t=20depend=20on=20numberTd.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Line.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Line.hs b/src/Line.hs index e33c13e90..5e86cd09f 100644 --- a/src/Line.hs +++ b/src/Line.hs @@ -39,9 +39,9 @@ instance Monoid (Line a) where mappend (Line xs) (Line ys) = Line (xs <> ys) instance ToMarkup a => ToMarkup (Bool, Int, Line a) where - toMarkup (_, _, line@EmptyLine) = numberTd "" <> toMarkup line <> string "\n" + toMarkup (_, _, line@EmptyLine) = td mempty ! A.class_ (stringValue "blob-num blob-num-empty empty-cell") <> toMarkup line <> string "\n" toMarkup (True, num, line@(Line _)) = td (string $ show num) ! A.class_ (stringValue "blob-num blob-num-replacement") <> toMarkup line <> string "\n" - toMarkup (_, num, line@(Line _)) = numberTd (show num) <> toMarkup line <> string "\n" + toMarkup (_, num, line@(Line _)) = td (string $ show num) ! A.class_ (stringValue "blob-num") <> toMarkup line <> string "\n" numberTd :: String -> Html numberTd "" = td mempty ! A.class_ (stringValue "blob-num blob-num-empty empty-cell") From de1482af2c589071f236eccf636a397d5ed7275f Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 18:06:49 -0500 Subject: [PATCH 246/259] Remove numberTd. --- src/Line.hs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Line.hs b/src/Line.hs index 5e86cd09f..cff4c2fb6 100644 --- a/src/Line.hs +++ b/src/Line.hs @@ -43,10 +43,6 @@ instance ToMarkup a => ToMarkup (Bool, Int, Line a) where toMarkup (True, num, line@(Line _)) = td (string $ show num) ! A.class_ (stringValue "blob-num blob-num-replacement") <> toMarkup line <> string "\n" toMarkup (_, num, line@(Line _)) = td (string $ show num) ! A.class_ (stringValue "blob-num") <> toMarkup line <> string "\n" -numberTd :: String -> Html -numberTd "" = td mempty ! A.class_ (stringValue "blob-num blob-num-empty empty-cell") -numberTd s = td (string s) ! A.class_ (stringValue "blob-num") - codeTd :: Bool -> Maybe Html -> Html codeTd _ Nothing = td mempty ! A.class_ (stringValue "blob-code blob-code-empty empty-cell") codeTd True (Just el) = td el ! A.class_ (stringValue "blob-code blob-code-replacement") From cfe2cd336e49db8a530bffcab45da44f7bf504b1 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 18:13:43 -0500 Subject: [PATCH 247/259] Define toMarkup over Bool/Int/Line triples by pattern matching. --- src/Line.hs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Line.hs b/src/Line.hs index cff4c2fb6..21a2f61d9 100644 --- a/src/Line.hs +++ b/src/Line.hs @@ -39,6 +39,11 @@ instance Monoid (Line a) where mappend (Line xs) (Line ys) = Line (xs <> ys) instance ToMarkup a => ToMarkup (Bool, Int, Line a) where + toMarkup (hasChanges, num, line) = case line of + EmptyLine -> td mempty ! A.class_ (stringValue "blob-num blob-num-empty empty-cell") <> td mempty ! A.class_ (stringValue "blob-code blob-code-empty empty-cell") <> string "\n" + _ -> cell "num" (string $ show num) <> cell "code" (toMarkup line) <> string "\n" + where cell kind = td ! A.class_ (toClass kind) + toClass kind = stringValue $ "blob-" ++ kind ++ if hasChanges then " blob-" ++ kind ++ "-replacement" else "" toMarkup (_, _, line@EmptyLine) = td mempty ! A.class_ (stringValue "blob-num blob-num-empty empty-cell") <> toMarkup line <> string "\n" toMarkup (True, num, line@(Line _)) = td (string $ show num) ! A.class_ (stringValue "blob-num blob-num-replacement") <> toMarkup line <> string "\n" toMarkup (_, num, line@(Line _)) = td (string $ show num) ! A.class_ (stringValue "blob-num") <> toMarkup line <> string "\n" From fbda7e11c1025a1ae01073fcf6a08d54a2694635 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 18:14:01 -0500 Subject: [PATCH 248/259] Remove the old definitions. --- src/Line.hs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Line.hs b/src/Line.hs index 21a2f61d9..9b1a3133e 100644 --- a/src/Line.hs +++ b/src/Line.hs @@ -44,9 +44,6 @@ instance ToMarkup a => ToMarkup (Bool, Int, Line a) where _ -> cell "num" (string $ show num) <> cell "code" (toMarkup line) <> string "\n" where cell kind = td ! A.class_ (toClass kind) toClass kind = stringValue $ "blob-" ++ kind ++ if hasChanges then " blob-" ++ kind ++ "-replacement" else "" - toMarkup (_, _, line@EmptyLine) = td mempty ! A.class_ (stringValue "blob-num blob-num-empty empty-cell") <> toMarkup line <> string "\n" - toMarkup (True, num, line@(Line _)) = td (string $ show num) ! A.class_ (stringValue "blob-num blob-num-replacement") <> toMarkup line <> string "\n" - toMarkup (_, num, line@(Line _)) = td (string $ show num) ! A.class_ (stringValue "blob-num") <> toMarkup line <> string "\n" codeTd :: Bool -> Maybe Html -> Html codeTd _ Nothing = td mempty ! A.class_ (stringValue "blob-code blob-code-empty empty-cell") From 30c281c185b2c3fc58da4f8845a3875bcb0e2abc Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 18:14:36 -0500 Subject: [PATCH 249/259] Inline the cell class. --- src/Line.hs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Line.hs b/src/Line.hs index 9b1a3133e..165cb6fab 100644 --- a/src/Line.hs +++ b/src/Line.hs @@ -42,8 +42,7 @@ instance ToMarkup a => ToMarkup (Bool, Int, Line a) where toMarkup (hasChanges, num, line) = case line of EmptyLine -> td mempty ! A.class_ (stringValue "blob-num blob-num-empty empty-cell") <> td mempty ! A.class_ (stringValue "blob-code blob-code-empty empty-cell") <> string "\n" _ -> cell "num" (string $ show num) <> cell "code" (toMarkup line) <> string "\n" - where cell kind = td ! A.class_ (toClass kind) - toClass kind = stringValue $ "blob-" ++ kind ++ if hasChanges then " blob-" ++ kind ++ "-replacement" else "" + where cell kind = td ! A.class_ (stringValue $ "blob-" ++ kind ++ if hasChanges then " blob-" ++ kind ++ "-replacement" else "") codeTd :: Bool -> Maybe Html -> Html codeTd _ Nothing = td mempty ! A.class_ (stringValue "blob-code blob-code-empty empty-cell") From 1241cbeff9db2628dfc33251176b793ca7dfaa96 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 18:18:10 -0500 Subject: [PATCH 250/259] Revert "Inline the cell class." This reverts commit 2e484d1dbd3c694165bdcff6a32486256d93041e. --- src/Line.hs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Line.hs b/src/Line.hs index 165cb6fab..9b1a3133e 100644 --- a/src/Line.hs +++ b/src/Line.hs @@ -42,7 +42,8 @@ instance ToMarkup a => ToMarkup (Bool, Int, Line a) where toMarkup (hasChanges, num, line) = case line of EmptyLine -> td mempty ! A.class_ (stringValue "blob-num blob-num-empty empty-cell") <> td mempty ! A.class_ (stringValue "blob-code blob-code-empty empty-cell") <> string "\n" _ -> cell "num" (string $ show num) <> cell "code" (toMarkup line) <> string "\n" - where cell kind = td ! A.class_ (stringValue $ "blob-" ++ kind ++ if hasChanges then " blob-" ++ kind ++ "-replacement" else "") + where cell kind = td ! A.class_ (toClass kind) + toClass kind = stringValue $ "blob-" ++ kind ++ if hasChanges then " blob-" ++ kind ++ "-replacement" else "" codeTd :: Bool -> Maybe Html -> Html codeTd _ Nothing = td mempty ! A.class_ (stringValue "blob-code blob-code-empty empty-cell") From 985afd797b1c557b3e326bdf3e109215ab9e5d24 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 18:18:15 -0500 Subject: [PATCH 251/259] Revert "Remove the old definitions." This reverts commit bdc9d50a5bf0e05ea6cd04e5603ab85911cc4314. --- src/Line.hs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Line.hs b/src/Line.hs index 9b1a3133e..21a2f61d9 100644 --- a/src/Line.hs +++ b/src/Line.hs @@ -44,6 +44,9 @@ instance ToMarkup a => ToMarkup (Bool, Int, Line a) where _ -> cell "num" (string $ show num) <> cell "code" (toMarkup line) <> string "\n" where cell kind = td ! A.class_ (toClass kind) toClass kind = stringValue $ "blob-" ++ kind ++ if hasChanges then " blob-" ++ kind ++ "-replacement" else "" + toMarkup (_, _, line@EmptyLine) = td mempty ! A.class_ (stringValue "blob-num blob-num-empty empty-cell") <> toMarkup line <> string "\n" + toMarkup (True, num, line@(Line _)) = td (string $ show num) ! A.class_ (stringValue "blob-num blob-num-replacement") <> toMarkup line <> string "\n" + toMarkup (_, num, line@(Line _)) = td (string $ show num) ! A.class_ (stringValue "blob-num") <> toMarkup line <> string "\n" codeTd :: Bool -> Maybe Html -> Html codeTd _ Nothing = td mempty ! A.class_ (stringValue "blob-code blob-code-empty empty-cell") From 759b008000f3bf770d40ac86fd1ffe2e9406260c Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 18:18:19 -0500 Subject: [PATCH 252/259] Revert "Define toMarkup over Bool/Int/Line triples by pattern matching." This reverts commit 7f5f4ca3e690ccab67ac4d1536d80c415e51b791. --- src/Line.hs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Line.hs b/src/Line.hs index 21a2f61d9..cff4c2fb6 100644 --- a/src/Line.hs +++ b/src/Line.hs @@ -39,11 +39,6 @@ instance Monoid (Line a) where mappend (Line xs) (Line ys) = Line (xs <> ys) instance ToMarkup a => ToMarkup (Bool, Int, Line a) where - toMarkup (hasChanges, num, line) = case line of - EmptyLine -> td mempty ! A.class_ (stringValue "blob-num blob-num-empty empty-cell") <> td mempty ! A.class_ (stringValue "blob-code blob-code-empty empty-cell") <> string "\n" - _ -> cell "num" (string $ show num) <> cell "code" (toMarkup line) <> string "\n" - where cell kind = td ! A.class_ (toClass kind) - toClass kind = stringValue $ "blob-" ++ kind ++ if hasChanges then " blob-" ++ kind ++ "-replacement" else "" toMarkup (_, _, line@EmptyLine) = td mempty ! A.class_ (stringValue "blob-num blob-num-empty empty-cell") <> toMarkup line <> string "\n" toMarkup (True, num, line@(Line _)) = td (string $ show num) ! A.class_ (stringValue "blob-num blob-num-replacement") <> toMarkup line <> string "\n" toMarkup (_, num, line@(Line _)) = td (string $ show num) ! A.class_ (stringValue "blob-num") <> toMarkup line <> string "\n" From 124ff65c91b2bd1d5405a01594a64f9dc1b8e295 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 18:19:30 -0500 Subject: [PATCH 253/259] Remove the pattern matches on Line. --- src/Line.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Line.hs b/src/Line.hs index cff4c2fb6..7a702b3ff 100644 --- a/src/Line.hs +++ b/src/Line.hs @@ -40,8 +40,8 @@ instance Monoid (Line a) where instance ToMarkup a => ToMarkup (Bool, Int, Line a) where toMarkup (_, _, line@EmptyLine) = td mempty ! A.class_ (stringValue "blob-num blob-num-empty empty-cell") <> toMarkup line <> string "\n" - toMarkup (True, num, line@(Line _)) = td (string $ show num) ! A.class_ (stringValue "blob-num blob-num-replacement") <> toMarkup line <> string "\n" - toMarkup (_, num, line@(Line _)) = td (string $ show num) ! A.class_ (stringValue "blob-num") <> toMarkup line <> string "\n" + toMarkup (True, num, line) = td (string $ show num) ! A.class_ (stringValue "blob-num blob-num-replacement") <> toMarkup line <> string "\n" + toMarkup (_, num, line) = td (string $ show num) ! A.class_ (stringValue "blob-num") <> toMarkup line <> string "\n" codeTd :: Bool -> Maybe Html -> Html codeTd _ Nothing = td mempty ! A.class_ (stringValue "blob-code blob-code-empty empty-cell") From ac867437f0e627748478cd05c24a13ff5a3840b6 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 18:20:20 -0500 Subject: [PATCH 254/259] Handle the hasChanges case inline. --- src/Line.hs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Line.hs b/src/Line.hs index 7a702b3ff..44904a31e 100644 --- a/src/Line.hs +++ b/src/Line.hs @@ -40,8 +40,7 @@ instance Monoid (Line a) where instance ToMarkup a => ToMarkup (Bool, Int, Line a) where toMarkup (_, _, line@EmptyLine) = td mempty ! A.class_ (stringValue "blob-num blob-num-empty empty-cell") <> toMarkup line <> string "\n" - toMarkup (True, num, line) = td (string $ show num) ! A.class_ (stringValue "blob-num blob-num-replacement") <> toMarkup line <> string "\n" - toMarkup (_, num, line) = td (string $ show num) ! A.class_ (stringValue "blob-num") <> toMarkup line <> string "\n" + toMarkup (hasChanges, num, line) = td (string $ show num) ! A.class_ (stringValue $ if hasChanges then "blob-num blob-num-replacement" else "blob-num") <> toMarkup line <> string "\n" codeTd :: Bool -> Maybe Html -> Html codeTd _ Nothing = td mempty ! A.class_ (stringValue "blob-code blob-code-empty empty-cell") From cbd09870104244337b277c5f72af213f7c3fae2f Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 18:22:33 -0500 Subject: [PATCH 255/259] Mark up the code cell inline too. --- src/Line.hs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Line.hs b/src/Line.hs index 44904a31e..61f67dc45 100644 --- a/src/Line.hs +++ b/src/Line.hs @@ -40,7 +40,9 @@ instance Monoid (Line a) where instance ToMarkup a => ToMarkup (Bool, Int, Line a) where toMarkup (_, _, line@EmptyLine) = td mempty ! A.class_ (stringValue "blob-num blob-num-empty empty-cell") <> toMarkup line <> string "\n" - toMarkup (hasChanges, num, line) = td (string $ show num) ! A.class_ (stringValue $ if hasChanges then "blob-num blob-num-replacement" else "blob-num") <> toMarkup line <> string "\n" + toMarkup (hasChanges, num, Line contents) + = td (string $ show num) ! A.class_ (stringValue $ if hasChanges then "blob-num blob-num-replacement" else "blob-num") + <> td (mconcat $ toMarkup <$> contents) ! A.class_ (stringValue $ if hasChanges then "blob-code blob-code-replacement" else "blob-code") <> string "\n" codeTd :: Bool -> Maybe Html -> Html codeTd _ Nothing = td mempty ! A.class_ (stringValue "blob-code blob-code-empty empty-cell") From 91bf531af9c2423bb9d970973ca286b93eadaad3 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 18:23:34 -0500 Subject: [PATCH 256/259] Mark up empty code cells directly. --- src/Line.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Line.hs b/src/Line.hs index 61f67dc45..e34e8ced8 100644 --- a/src/Line.hs +++ b/src/Line.hs @@ -39,7 +39,7 @@ instance Monoid (Line a) where mappend (Line xs) (Line ys) = Line (xs <> ys) instance ToMarkup a => ToMarkup (Bool, Int, Line a) where - toMarkup (_, _, line@EmptyLine) = td mempty ! A.class_ (stringValue "blob-num blob-num-empty empty-cell") <> toMarkup line <> string "\n" + toMarkup (_, _, EmptyLine) = td mempty ! A.class_ (stringValue "blob-num blob-num-empty empty-cell") <> td mempty ! A.class_ (stringValue "blob-code blob-code-empty empty-cell") <> string "\n" toMarkup (hasChanges, num, Line contents) = td (string $ show num) ! A.class_ (stringValue $ if hasChanges then "blob-num blob-num-replacement" else "blob-num") <> td (mconcat $ toMarkup <$> contents) ! A.class_ (stringValue $ if hasChanges then "blob-code blob-code-replacement" else "blob-code") <> string "\n" From 3f2af1826aa9dd17233b129396a7ef638272e3a5 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 18:23:58 -0500 Subject: [PATCH 257/259] Remove the ToMarkup instance for Line. --- src/Line.hs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Line.hs b/src/Line.hs index e34e8ced8..38dfe6793 100644 --- a/src/Line.hs +++ b/src/Line.hs @@ -48,7 +48,3 @@ codeTd :: Bool -> Maybe Html -> Html codeTd _ Nothing = td mempty ! A.class_ (stringValue "blob-code blob-code-empty empty-cell") codeTd True (Just el) = td el ! A.class_ (stringValue "blob-code blob-code-replacement") codeTd False (Just el) = td el ! A.class_ (stringValue "blob-code") - -instance ToMarkup a => ToMarkup (Line a) where - toMarkup EmptyLine = codeTd False Nothing - toMarkup (Line contents) = codeTd False . Just . mconcat $ toMarkup <$> contents From 773f98c13ece373aea4d99e782f5e8461fbbc8bd Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Dec 2015 18:24:20 -0500 Subject: [PATCH 258/259] Remove codeTd. --- src/Line.hs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Line.hs b/src/Line.hs index 38dfe6793..c1d748f8b 100644 --- a/src/Line.hs +++ b/src/Line.hs @@ -43,8 +43,3 @@ instance ToMarkup a => ToMarkup (Bool, Int, Line a) where toMarkup (hasChanges, num, Line contents) = td (string $ show num) ! A.class_ (stringValue $ if hasChanges then "blob-num blob-num-replacement" else "blob-num") <> td (mconcat $ toMarkup <$> contents) ! A.class_ (stringValue $ if hasChanges then "blob-code blob-code-replacement" else "blob-code") <> string "\n" - -codeTd :: Bool -> Maybe Html -> Html -codeTd _ Nothing = td mempty ! A.class_ (stringValue "blob-code blob-code-empty empty-cell") -codeTd True (Just el) = td el ! A.class_ (stringValue "blob-code blob-code-replacement") -codeTd False (Just el) = td el ! A.class_ (stringValue "blob-code") From cb56c621e0c08828ab15dc1214f56771246af71b Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sun, 27 Dec 2015 12:16:19 -0500 Subject: [PATCH 259/259] Whoops. --- src/Range.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Range.hs b/src/Range.hs index 554c98509..c7cdb88ab 100644 --- a/src/Range.hs +++ b/src/Range.hs @@ -4,7 +4,7 @@ import Control.Applicative ((<|>)) import qualified Data.Char as Char import Data.Maybe (fromMaybe) - -- | A half-open interval of integers, defined by start & end indices. +-- | A half-open interval of integers, defined by start & end indices. data Range = Range { start :: !Int, end :: !Int } deriving (Eq, Show)