{-# LANGUAGE CPP #-} {-# LANGUAGE ViewPatterns #-} module Test.Hspec.Core.Formatters.Diff ( Diff (..) , recover , diff #ifdef TEST , recoverString , partition , breakList #endif ) where import Prelude () import Control.Arrow import Test.Hspec.Core.Compat hiding (First) import Data.Char import qualified Data.Algorithm.Diff as Diff import Text.Show.Unicode (urecover) data Diff = First String | Second String | Both String deriving (Diff -> Diff -> Bool (Diff -> Diff -> Bool) -> (Diff -> Diff -> Bool) -> Eq Diff forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a /= :: Diff -> Diff -> Bool $c/= :: Diff -> Diff -> Bool == :: Diff -> Diff -> Bool $c== :: Diff -> Diff -> Bool Eq, Int -> Diff -> ShowS [Diff] -> ShowS Diff -> String (Int -> Diff -> ShowS) -> (Diff -> String) -> ([Diff] -> ShowS) -> Show Diff forall a. (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a showList :: [Diff] -> ShowS $cshowList :: [Diff] -> ShowS show :: Diff -> String $cshow :: Diff -> String showsPrec :: Int -> Diff -> ShowS $cshowsPrec :: Int -> Diff -> ShowS Show) recover :: Bool -> String -> String -> (String, String) recover :: Bool -> String -> String -> (String, String) recover Bool unicode String expected String actual = case (Bool -> String -> Maybe String recoverString Bool unicode String expected, Bool -> String -> Maybe String recoverString Bool unicode String actual) of (Just String expected_, Just String actual_) -> (String expected_, String actual_) (Maybe String, Maybe String) _ -> (ShowS rec String expected, ShowS rec String actual) where rec :: ShowS rec = if Bool unicode then ShowS urecover else ShowS forall a. a -> a id recoverString :: Bool -> String -> Maybe String recoverString :: Bool -> String -> Maybe String recoverString Bool unicode String input = case String -> Maybe String forall a. Read a => String -> Maybe a readMaybe String input of Just String r | String -> Bool shouldParseBack String r -> String -> Maybe String forall a. a -> Maybe a Just String r Maybe String _ -> Maybe String forall a. Maybe a Nothing where shouldParseBack :: String -> Bool shouldParseBack = Bool -> Bool -> Bool (&&) (Bool -> Bool -> Bool) -> (String -> Bool) -> String -> Bool -> Bool forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> (Char -> Bool) -> String -> Bool forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool all Char -> Bool isSafe (String -> Bool -> Bool) -> (String -> Bool) -> String -> Bool forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b <*> String -> Bool isMultiLine isMultiLine :: String -> Bool isMultiLine = String -> [String] lines (String -> [String]) -> ([String] -> Bool) -> String -> Bool forall k (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k). Category cat => cat a b -> cat b c -> cat a c >>> [String] -> Int forall (t :: * -> *) a. Foldable t => t a -> Int length ([String] -> Int) -> (Int -> Bool) -> [String] -> Bool forall k (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k). Category cat => cat a b -> cat b c -> cat a c >>> (Int -> Int -> Bool forall a. Ord a => a -> a -> Bool > Int 1) isSafe :: Char -> Bool isSafe Char c = (Bool unicode Bool -> Bool -> Bool || Char -> Bool isAscii Char c) Bool -> Bool -> Bool && (Bool -> Bool not (Bool -> Bool) -> Bool -> Bool forall a b. (a -> b) -> a -> b $ Char -> Bool isControl Char c) Bool -> Bool -> Bool || Char c Char -> Char -> Bool forall a. Eq a => a -> a -> Bool == Char '\n' diff :: String -> String -> [Diff] diff :: String -> String -> [Diff] diff String expected String actual = (Diff [String] -> Diff) -> [Diff [String]] -> [Diff] forall a b. (a -> b) -> [a] -> [b] map (Diff String -> Diff toDiff (Diff String -> Diff) -> (Diff [String] -> Diff String) -> Diff [String] -> Diff forall b c a. (b -> c) -> (a -> b) -> a -> c . ([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]) -> [Diff [String]] -> [Diff] forall a b. (a -> b) -> a -> b $ [String] -> [String] -> [Diff [String]] forall t. Eq t => [t] -> [t] -> [Diff [t]] Diff.getGroupedDiff (String -> [String] partition String expected) (String -> [String] partition String actual) toDiff :: Diff.Diff String -> Diff toDiff :: Diff String -> Diff toDiff Diff String d = case Diff String d of Diff.First String xs -> String -> Diff First String xs Diff.Second String xs -> String -> Diff Second String xs Diff.Both String xs String _ -> String -> Diff Both String xs 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] -> [String] mergeBackslashes [String] xs = case [String] xs of [Char '\\'] : (String -> Maybe (String, String) splitEscape -> Just (String escape, String ys)) : [String] zs -> (String "\\" String -> ShowS 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 "\\" ]