{-# 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 String expected 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 [String] xs = case [String] xs of [Char '\\'] : (String -> Maybe (String, String) splitEscape -> Just (String escape, String ys)) : [String] zs -> (String "\\" 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 String z : [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 a -> Bool _ [] = [] breakList a -> Bool p [a] xs = case (a -> Bool) -> [a] -> ([a], [a]) forall a. (a -> Bool) -> [a] -> ([a], [a]) break a -> Bool p [a] xs of ([a] y, [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 ([a] z, [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 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 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 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 String xs = case (Char -> Bool) -> String -> (String, String) forall a. (a -> Bool) -> [a] -> ([a], [a]) span Char -> Bool isDigit String xs of (String "", String _) -> Maybe (String, String) forall a. Maybe a Nothing (String, String) r -> (String, String) -> Maybe (String, String) forall a. a -> Maybe a Just (String, String) r escapes :: [String] escapes :: [String] escapes = [ String "ACK" , String "CAN" , String "DC1" , String "DC2" , String "DC3" , String "DC4" , String "DEL" , String "DLE" , String "ENQ" , String "EOT" , String "ESC" , String "ETB" , String "ETX" , String "NAK" , String "NUL" , String "SOH" , String "STX" , String "SUB" , String "SYN" , String "EM" , String "FS" , String "GS" , String "RS" , String "SI" , String "SO" , String "US" , String "a" , String "b" , String "f" , String "n" , String "r" , String "t" , String "v" , String "&" , String "'" , String "\"" , String "\\" ]