{-# LANGUAGE CPP #-} {-# LANGUAGE ViewPatterns #-} module Test.Hspec.Core.Formatters.Diff ( Diff (..) , diff #ifdef TEST , partition , breakList #endif ) where import Prelude () import Test.Hspec.Core.Compat import Data.Char import Data.List (stripPrefix) import Data.Algorithm.Diff diff :: String -> String -> [Diff String] diff :: String -> String -> [Diff String] diff expected :: String expected actual :: String actual = (Diff [String] -> Diff String) -> [Diff [String]] -> [Diff String] forall a b. (a -> b) -> [a] -> [b] map (([String] -> String) -> Diff [String] -> Diff String forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmap [String] -> String forall (t :: * -> *) a. Foldable t => t [a] -> [a] concat) ([Diff [String]] -> [Diff String]) -> [Diff [String]] -> [Diff String] forall a b. (a -> b) -> a -> b $ [String] -> [String] -> [Diff [String]] forall t. Eq t => [t] -> [t] -> [Diff [t]] getGroupedDiff (String -> [String] partition String expected) (String -> [String] partition String actual) partition :: String -> [String] partition :: String -> [String] partition = (String -> Bool) -> [String] -> [String] forall a. (a -> Bool) -> [a] -> [a] filter (Bool -> Bool not (Bool -> Bool) -> (String -> Bool) -> String -> Bool forall b c a. (b -> c) -> (a -> b) -> a -> c . String -> Bool forall (t :: * -> *) a. Foldable t => t a -> Bool null) ([String] -> [String]) -> (String -> [String]) -> String -> [String] forall b c a. (b -> c) -> (a -> b) -> a -> c . [String] -> [String] mergeBackslashes ([String] -> [String]) -> (String -> [String]) -> String -> [String] forall b c a. (b -> c) -> (a -> b) -> a -> c . (Char -> Bool) -> String -> [String] forall a. (a -> Bool) -> [a] -> [[a]] breakList Char -> Bool isAlphaNum where mergeBackslashes :: [String] -> [String] mergeBackslashes xs :: [String] xs = case [String] xs of ['\\'] : (String -> Maybe (String, String) splitEscape -> Just (escape :: String escape, ys :: String ys)) : zs :: [String] zs -> ("\\" String -> String -> String forall a. [a] -> [a] -> [a] ++ String escape) String -> [String] -> [String] forall a. a -> [a] -> [a] : String ys String -> [String] -> [String] forall a. a -> [a] -> [a] : [String] -> [String] mergeBackslashes [String] zs z :: String z : zs :: [String] zs -> String z String -> [String] -> [String] forall a. a -> [a] -> [a] : [String] -> [String] mergeBackslashes [String] zs [] -> [] breakList :: (a -> Bool) -> [a] -> [[a]] breakList :: (a -> Bool) -> [a] -> [[a]] breakList _ [] = [] breakList p :: a -> Bool p xs :: [a] xs = case (a -> Bool) -> [a] -> ([a], [a]) forall a. (a -> Bool) -> [a] -> ([a], [a]) break a -> Bool p [a] xs of (y :: [a] y, ys :: [a] ys) -> (a -> [a]) -> [a] -> [[a]] forall a b. (a -> b) -> [a] -> [b] map a -> [a] forall (m :: * -> *) a. Monad m => a -> m a return [a] y [[a]] -> [[a]] -> [[a]] forall a. [a] -> [a] -> [a] ++ case (a -> Bool) -> [a] -> ([a], [a]) forall a. (a -> Bool) -> [a] -> ([a], [a]) span a -> Bool p [a] ys of (z :: [a] z, zs :: [a] zs) -> [a] z [a] -> [[a]] -> [[a]] forall (t :: * -> *) a. Foldable t => t a -> [t a] -> [t a] `cons` (a -> Bool) -> [a] -> [[a]] forall a. (a -> Bool) -> [a] -> [[a]] breakList a -> Bool p [a] zs where cons :: t a -> [t a] -> [t a] cons x :: t a x | t a -> Bool forall (t :: * -> *) a. Foldable t => t a -> Bool null t a x = [t a] -> [t a] forall a. a -> a id | Bool otherwise = (t a x t a -> [t a] -> [t a] forall a. a -> [a] -> [a] :) splitEscape :: String -> Maybe (String, String) splitEscape :: String -> Maybe (String, String) splitEscape xs :: String xs = String -> Maybe (String, String) splitNumericEscape String xs Maybe (String, String) -> Maybe (String, String) -> Maybe (String, String) forall (f :: * -> *) a. Alternative f => f a -> f a -> f a <|> ([Maybe (String, String)] -> Maybe (String, String) forall (t :: * -> *) (m :: * -> *) a. (Foldable t, MonadPlus m) => t (m a) -> m a msum ([Maybe (String, String)] -> Maybe (String, String)) -> [Maybe (String, String)] -> Maybe (String, String) forall a b. (a -> b) -> a -> b $ (String -> Maybe (String, String)) -> [String] -> [Maybe (String, String)] forall a b. (a -> b) -> [a] -> [b] map String -> Maybe (String, String) split [String] escapes) where split :: String -> Maybe (String, String) split :: String -> Maybe (String, String) split escape :: String escape = (,) String escape (String -> (String, String)) -> Maybe String -> Maybe (String, String) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> String -> String -> Maybe String forall a. Eq a => [a] -> [a] -> Maybe [a] stripPrefix String escape String xs splitNumericEscape :: String -> Maybe (String, String) splitNumericEscape :: String -> Maybe (String, String) splitNumericEscape xs :: String xs = case (Char -> Bool) -> String -> (String, String) forall a. (a -> Bool) -> [a] -> ([a], [a]) span Char -> Bool isDigit String xs of ("", _) -> Maybe (String, String) forall a. Maybe a Nothing r :: (String, String) r -> (String, String) -> Maybe (String, String) forall a. a -> Maybe a Just (String, String) r escapes :: [String] escapes :: [String] escapes = [ "ACK" , "CAN" , "DC1" , "DC2" , "DC3" , "DC4" , "DEL" , "DLE" , "ENQ" , "EOT" , "ESC" , "ETB" , "ETX" , "NAK" , "NUL" , "SOH" , "STX" , "SUB" , "SYN" , "EM" , "FS" , "GS" , "RS" , "SI" , "SO" , "US" , "a" , "b" , "f" , "n" , "r" , "t" , "v" , "&" , "'" , "\"" , "\\" ]