--- /dev/null
+{-# LANGUAGE ExistentialQuantification #-}
+module Golden where
+
+import Control.Monad (Monad(..))
+import Data.Char (Char)
+import Data.Function (($))
+import Data.Int (Int)
+import Data.Maybe (Maybe(..))
+import Data.Ord (Ord(..))
+import Data.Semigroup (Semigroup(..))
+import Data.String (IsString(..), String)
+import Prelude (succ)
+import System.IO (FilePath)
+import System.IO.Unsafe (unsafePerformIO)
+import Test.Tasty
+import Test.Tasty.Golden
+import Text.Printf (printf)
+import Text.Show (Show(..))
+import qualified Data.List as List
+
+import Paths_symantic_formatter
+import Symantic.Formatter
+
+golden :: TestTree
+golden =
+ testGroup "Golden"
+ [ testGroup "Plain" $
+ (\f -> List.zipWith f goldens [1::Int ..]) $ \(Golden fmt inps) fmtNum ->
+ let fmtDir = printf "Format%03d" fmtNum in
+ testGroup fmtDir $
+ (\f -> List.zipWith f inps [1::Int ..]) $ \inp inpNum ->
+ let plainFile = getGoldenDir $ printf "Plain/%s/Input%02d.expected.txt" fmtDir inpNum in
+ goldenVsStringDiff
+ (printf "Input%02d" inpNum) goldenDiff plainFile $ do
+ return $ fromString $ runPlain fmt inp
+ ]
+
+getGoldenDir :: FilePath -> FilePath
+getGoldenDir p = unsafePerformIO $ getDataFileName $ "tests/Golden/" <> p
+
+goldenDiff :: FilePath -> FilePath -> [String]
+goldenDiff ref new = ["diff", "-u", "-w", "-B", ref, new]
+
+data Golden repr = forall inp. Golden (repr inp) [inp]
+goldens ::
+ Indentable repr =>
+ Inferable Char repr =>
+ Inferable Int repr =>
+ Inferable String repr =>
+ IsString (repr ()) =>
+ Justifiable repr =>
+ Listable repr =>
+ Newlineable repr =>
+ Repeatable repr =>
+ Decorable repr =>
+ Voidable repr =>
+ Wrappable repr =>
+ [Golden repr]
+goldens =
+ [ let fun t = "function("
+ .> breakalt t (incrIndent (spaces 2) 2 (newline.>t)<.newline)
+ <. ")" in
+ Golden
+ ( setWidth (Just 19) $ fun $ fun $ fun $ fun $ fun $ bracketList (many int)
+ )
+ [ [[1..9], [1..9]]
+ , [[0..9], [0..9]]
+ ]
+ , Golden
+ ( setWidth (Just 10) $
+ justify (unorderedList (unwords_ int))
+ )
+ [ [[1..9], [1..9]] ]
+ , Golden
+ ( setWidth (Just 11) $
+ justify (orderedList (unwords_ int))
+ )
+ [ [[1..9], [1..9]] ]
+ , Golden
+ (setWidth (Just 10) $
+ justify (unorderedList (unorderedList (unwords_ int))))
+ [ [ [[1..9], [1..9]], [[1..9], [1..9]] ] ]
+ , Golden (setWidth (Just 80) string) [ lorem ]
+ -- breakspace backtracking is bounded by the removable indentation
+ -- (hence it can actually wrap a few words in reasonable time).
+ , Golden (setWidth (Just 80) (justify string)) [ lorem ]
+ , Golden
+ ("let"+>align (unlines_ (fill 6 string<+ "::" <+>string)))
+ [
+ [ ("abcdef","Char")
+ , ("abcde","Int -> Char -> Char")
+ , ("abcdefghi","Char")
+ ]
+ ]
+ , Golden
+ ("let"+>align (unlines_ (fillOrBreak 6 string<+"::"<+>align string)))
+ [
+ [ ("abcdef","Char")
+ , ("abcde","Int -> Char -> Char")
+ , ("abcdefghi","Char ->\nChar")
+ ]
+ ]
+ , Golden (setWidth (Just 10) $ nestedAlign 6) [()]
+ , Golden (setWidth (Just 10) $ nestedAlign 7) [()]
+ , Golden (setWidth (Just 10) $ nestedAlign 8) [()]
+ , Golden (setWidth (Just 10) $ nestedAlign 9) [()]
+ , Golden (setWidth (Just 10) $ nestedAlign 10) [()]
+ , Golden (setWidth (Just 10) $ justify $ string <. nestedAlign 2)
+ [ ""
+ , "a b c de "
+ ]
+ , Golden (setWidth (Just 10) $ justify string)
+ -- justify justifies
+ [ "1 2 3 4 5 6"
+ -- justify compresses enclosed spaces
+ , "1 2 3 4 5 6"
+ , " 1 2 3 4 5 6 7 8 9"
+ , " 1 2 3 4 5 6 7 8 9"
+ , "1 2 3 4 5 6 7 8 9 "
+ , "1 2 3 4 5 6 7 8 9 "
+ -- justify does not justify on explicit newlines
+ , "1 2 3 4 5 6 7\n8 9 1 2 3 4 5"
+ ]
+ , Golden (setWidth (Just 10) $ "a b ".> "12" .> align string <.> align string)
+ [ (" 34 5", "")
+ , (" 34", "")
+ , (" 34", " ")
+ , (" 34", " 5")
+ , (" 34", " 56")
+ , (" 34", " 567")
+ , (" 34", " 5678")
+ , (" 34", " 56789")
+ ]
+ -- align flushes the buffer
+ , Golden (setWidth (Just 10) $ justify $ unorderedList $ unwords_ int)
+ [ [[1..9]] ]
+ -- unorderedList flushes the buffer
+ , Golden (setWidth (Just 10) $ justify $ unorderedList $ unwords_ int)
+ [ [[1..9], [1..9]]
+ , [[1..19], [1..19]]
+ , [[100000000..100000009], [100000000..100000009]]
+ , [[1000000000..1000000009], [1000000000..1000000009]]
+ ]
+ , Golden (setWidth (Just 10) $ justify $ unorderedList $ unorderedList $ unwords_ int)
+ [ [ [ [1..9], [1..9] ], [ [1..9], [1..9] ] ] ]
+ , Golden (setWidth (Just 10) $ justify $ orderedList $ orderedList $ unwords_ int)
+ [ [ [ [1..9], [1..9] ], [ [1..9], [1..9] ] ] ]
+ ]
+
+nestedAlign ::
+ Indentable repr =>
+ Wrappable repr =>
+ IsString (repr ()) =>
+ Int -> repr a
+nestedAlign n = go 1
+ where
+ go i =
+ fromString (show i) .>
+ (if n <= i
+ then empty
+ else align (breakspace .> go (succ i)))
+
+lorem :: String
+lorem =
+ "Lorem ipsum dolor sit amet, Nulla nec tortor. Donec id elit quis purus\
+ \ consectetur consequat. Nam congue semper tellus. Sed erat dolor,\
+ \ dapibus sit amet, venenatis ornare, ultrices ut, nisi. Aliquam ante.\
+ \ Suspendisse scelerisque dui nec velit. Duis augue augue, gravida euismod,\
+ \ vulputate ac, facilisis id, sem. Morbi in orci. Nulla purus lacus,\
+ \ pulvinar vel, malesuada ac, mattis nec, quam. Nam molestie scelerisque\
+ \ quam. Nullam feugiat cursus lacus.orem ipsum dolor sit amet, consectetur\
+ \ adipiscing elit. Donec libero risus, commodo vitae, pharetra mollis,\
+ \ posuere eu, pede. Nulla nec tortor. Donec id elit quis purus consectetur\
+ \ consequat. Nam congue semper tellus. Sed erat dolor, dapibus sit\
+ \ amet, venenatis ornare, ultrices ut, nisi. Aliquam ante. Suspendisse\
+ \ scelerisque dui nec velit. Duis augue augue, gravida euismod, vulputate ac,\
+ \ facilisis id, sem. Morbi in orci. Nulla purus lacus, pulvinar vel,\
+ \ malesuada ac, mattis nec, quam. Nam molestie scelerisque quam.\
+ \ Nullam feugiat cursus lacus.orem ipsum dolor sit amet, consectetur\
+ \ adipiscing elit. Donec libero risus, commodo vitae, pharetra mollis,\
+ \ posuere eu, pede. Nulla nec tortor. Donec id elit quis purus consectetur\
+ \ consequat. Nam congue semper tellus. Sed erat dolor, dapibus sit amet,\
+ \ venenatis ornare, ultrices ut, nisi. Aliquam ante. Suspendisse\
+ \ scelerisque dui nec velit. Duis augue augue, gravida euismod, vulputate ac,\
+ \ facilisis id, sem. Morbi in orci. Nulla purus lacus, pulvinar vel,\
+ \ malesuada ac, mattis nec, quam. Nam molestie scelerisque quam. Nullam\
+ \ feugiat cursus lacus.orem ipsum dolor sit amet, consectetur adipiscing\
+ \ elit. Donec libero risus, commodo vitae, pharetra mollis, posuere eu, pede.\
+ \ Nulla nec tortor. Donec id elit quis purus consectetur consequat. Nam\
+ \ congue semper tellus. Sed erat dolor, dapibus sit amet, venenatis ornare,\
+ \ ultrices ut, nisi."
import Symantic.Formatter.Plain (Plain, runPlain)
-- * Tests
-hunits :: TestTree
-hunits = testGroup "HUnit" $
- [ hunitPlain
- ]
-
-hunitPlain :: TestTree
-hunitPlain = testList "Plain"
- [ newline ==> "\n"
- , "hello".>"world" ==> "helloworld"
- , "hello".>newline.>"world" ==> "hello\nworld"
- , "hello\nworld" ==> "hello\nworld"
- , 10`maxWidth` breakpoints ["hello", "world"] ==> "helloworld"
- , 9`maxWidth` "hello" .> breakpoint .> "world" ==> "hello\nworld"
- , 6`maxWidth` breakpoints ["he", "ll", "o!"] ==> "hello!"
- , 6`maxWidth` breakpoints ["he", "ll", "o!", "wo", "rl", "d!"] ==> "hello!\nworld!"
- , 5`maxWidth` breakpoints ["hello", "world"] ==> "hello\nworld"
- , 5`maxWidth` breakpoints ["he", "llo", "world"] ==> "hello\nworld"
- , 5`maxWidth` breakpoints ["he", "ll", "o!"] ==> "hell\no!"
- , 4`maxWidth` breakpoints ["hello", "world"] ==> "hello\nworld"
- , 4`maxWidth` breakpoints ["he", "ll", "o!"] ==> "hell\no!"
- , 4`maxWidth` breakpoints ["he", "llo", "world"] ==> "he\nllo\nworld"
- , 4`maxWidth` breakpoints ["he", "llo", "w", "orld"] ==> "he\nllow\norld"
- , 4`maxWidth` breakpoints ["he", "ll", "o!", "wo", "rl", "d!"] ==> "hell\no!wo\nrld!"
- , 3`maxWidth` breakpoints ["hello", "world"] ==> "hello\nworld"
- , 3`maxWidth` breakpoints ["he", "ll"] ==> "he\nll"
- , 3`maxWidth` breakpoints ["he", "ll", "o!"] ==> "he\nll\no!"
- , 1`maxWidth` breakpoints ["he", "ll", "o!"] ==> "he\nll\no!"
- , 4`maxWidth` concat ["__", align $ breakpoints ["he", "ll", "o!", "wo", "rl", "d!"]]
- ==> "__he\n ll\n o!\n wo\n rl\n d!"
- , testPlain
- (4`maxWidth` "__" .> align (intercalate_ breakpoint string))
+hunit :: TestTree
+hunit = testGroup "HUnit"
+ [ testList "Plain"
+ [ testPlain newline () "\n"
+ , testPlain ("hello".>"world") () "helloworld"
+ , testPlain ("hello".>newline.>"world") () "hello\nworld"
+ , testPlain ("hello\nworld") () "hello\nworld"
+ , testPlain (setWidth (Just 9) $ "hello" .> breakpoint .> "world")
+ ()
+ "hello\nworld"
+ , testPlain (setWidth (Just 10) $ intercalate_ breakpoint string)
+ ["hello", "world"]
+ "helloworld"
+ , testPlain (setWidth (Just 6) $ intercalate_ breakpoint string)
+ ["he", "ll", "o!"]
+ "hello!"
+ , testPlain (setWidth (Just 6) $ intercalate_ breakpoint string)
["he", "ll", "o!", "wo", "rl", "d!"]
- "__he\n ll\n o!\n wo\n rl\n d!"
- , 6`maxWidth` concat ["__", align $ breakpoints ["he", "ll", "o!", "wo", "rl", "d!"]]
- ==> "__hell\n o!wo\n rld!"
- , testPlain
- (6`maxWidth` "__" .> align (intercalate_ breakpoint string))
+ "hello!\nworld!"
+ , testPlain (setWidth (Just 5) $ intercalate_ breakpoint string)
+ ["hello", "world"]
+ "hello\nworld"
+ , testPlain (setWidth (Just 5) $ intercalate_ breakpoint string)
+ ["he", "llo", "world"]
+ "hello\nworld"
+ , testPlain (setWidth (Just 5) $ intercalate_ breakpoint string)
+ ["he", "ll", "o!"]
+ "hell\no!"
+ , testPlain (setWidth (Just 4) $ intercalate_ breakpoint string)
+ ["hello", "world"]
+ "hello\nworld"
+ , testPlain (setWidth (Just 4) $ intercalate_ breakpoint string)
+ ["he", "ll", "o!"]
+ "hell\no!"
+ , testPlain (setWidth (Just 4) $ intercalate_ breakpoint string)
+ ["he", "llo", "world"]
+ "he\nllo\nworld"
+ , testPlain (setWidth (Just 4) $ intercalate_ breakpoint string)
+ ["he", "llo", "w", "orld"]
+ "he\nllow\norld"
+ , testPlain (setWidth (Just 4) $ intercalate_ breakpoint string)
["he", "ll", "o!", "wo", "rl", "d!"]
- "__hell\n o!wo\n rld!"
- , 16`maxWidth` concat ["__", listHorV ["hello", "world"]] ==> "__[hello, world]"
- , testPlain
- (16`maxWidth` "__" .> bracketList string)
- ["hello", "world"]
- "__[hello, world]"
- , 4`maxWidth` concat ["__", listHorV ["hello", "world"]] ==> "__[ hello\n , world\n ]"
- , 11`maxWidth` breakspaces ["hello", "world"] ==> "hello world"
- , 10`maxWidth` breakspaces ["hello", "world"] ==> "hello\nworld"
- , 6`maxWidth` breakspaces ["hel", "lo", "wo", "rld"] ==> "hel lo\nwo rld"
- , 6`maxWidth` breakspaces ["hel", "lo", "wo", "rld", "HEL", "LO", "WO", "RLD"] ==> "hel lo\nwo rld\nHEL LO\nWO RLD"
- , 5`maxWidth` breakspaces ["hello", "world"] ==> "hello\nworld"
- , 19`maxWidth` fun (fun $ fun $ fun $ fun $ listHorV ["abcdefg", "abcdefg"])
- ==> "function(function(\n function(\n function(\n function(\n [ abcdefg\n , abcdefg\n ]\n )\n )\n )\n ))"
- , 19`maxWidth` fun (fun $ fun $ fun $ fun $ listHorV ["abcdefgh", "abcdefgh"])
- ==> "function(\n function(\n function(\n function(\n function(\n [ abcdefgh\n , abcdefgh\n ]\n )\n )\n )\n )\n )"
- , 7`maxWidth` ("hello".>breakspace.>"world") ==> "hello\nworld"
- , 7`maxWidth` ("hello ".>"world") ==> "hello\nworld"
- , " ".> "hello\nworld\n!" ==> " hello\nworld\n!"
- , "__".>align "hello\nworld\n!" ==> "__hello\n world\n !"
- , hang 2 "hello\nworld\n!" ==> "hello\n world\n !"
- , hang 2 "hello\nworld\n!".>"\nhello\n!" ==> "hello\n world\n !\nhello\n!"
- , "let " .> align (catV $
- (\(name, typ) -> fill 6 name <+ "::" +> typ)
- <$> [ ("abcdef","Doc")
- , ("abcde","Int -> Doc -> Doc")
- , ("abcdefghi","Doc") ])
- ==> "let abcdef :: Doc\n abcde :: Int -> Doc -> Doc\n abcdefghi :: Doc"
- , "let " .> align (catV $
- (\(name, typ) -> fillOrBreak 6 name <. " ::" +> typ)
- <$> [ ("abcdef","Doc")
- , ("abcde","Int -> Doc -> Doc")
- , ("abcdefghi","Doc") ])
- ==> "let abcdef :: Doc\n abcde :: Int -> Doc -> Doc\n abcdefghi\n :: Doc"
- , "let " .> align (catV $
- (\(name, typ) -> fillOrBreak 6 name <. " ::" +> typ)
- <$> [("abcdefghi","Doc ->\nDoc")])
- ==> "let abcdefghi\n :: Doc ->\n Doc"
- , "let " .> align (catV $
- (\(name, typ) -> fillOrBreak 6 name <. align (" ::" +> typ))
- <$> [("abcdefghi","Doc ->\nDoc")])
- ==> "let abcdefghi\n :: Doc ->\n Doc"
- , 10 `maxWidth` "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15" ==> "1 2 3 4 5\n6 7 8 9 10\n11 12 13\n14 15"
- , 10 `maxWidth` "a b ".>"12".>align (" 34 5") ==> "a b 12 34\n 5"
- , 10 `maxWidth` "a b ".>"12".>align (" 34" .> align "") ==> "a b 12 34"
- , 10 `maxWidth` "a b ".>"12".>align (" 34" .> align " ") ==> "a b 12 34 "
- , 10 `maxWidth` "a b ".>"12".>align (" 34" .> align " 5") ==> "a b 12 34\n 5"
- , 10 `maxWidth` "a b ".>"12".>align (" 34" .> align " 56") ==> "a b 12\n 34\n 56"
- , 10 `maxWidth` "a b ".>"12".>align (" 34" .> align " 567") ==> "a b\n12 34 567"
- , 10 `maxWidth` "a b ".>"12".>align (" 34" .> align " 5678") ==> "a b\n12 34 5678"
- , 10 `maxWidth` "a b ".>"12".>align (" 34" .> align " 56789") ==> "a b\n12 34\n 56789"
- , 10 `maxWidth` ("1234567890" .> " ") .> "1" ==> "1234567890\n1"
- , 10 `maxWidth` nestedAlign 6 ==> "1 2 3 4 5\n 6"
- , 10 `maxWidth` nestedAlign 7 ==> "1 2 3 4\n 5\n 6\n 7"
- , 10 `maxWidth` nestedAlign 8 ==> "1 2 3\n 4\n 5\n 6\n 7\n 8"
- , 10 `maxWidth` nestedAlign 9 ==> "1 2\n 3\n 4\n 5\n 6\n 7\n 8\n 9"
- , 10 `maxWidth` nestedAlign 10 ==> "1\n 2\n 3\n 4\n 5\n 6\n 7\n 8\n 9\n 10"
- -- justify justifies
- , 10 `maxWidth` justify "1 2 3 4 5 6" ==> "1 2 3 4 5\n6"
- -- justify compresses spaces
- , 10 `maxWidth` justify "1 2 3 4 5 6" ==> "1 2 3 4 5\n6"
- , 10 `maxWidth` justify " 1 2 3 4 5 6 7 8 9" ==> " 1 2 3 4 5\n6 7 8 9"
- -- justify respects concatenating words
- , 10 `maxWidth` justify (setWidth (Just 11) ("1 2 3".>"4 5 6 7")) ==> "1 2 34 5 6\n7"
- -- justify flushes the buffer before
- , 10 `maxWidth` "__" .> align (justify "1 2 3 4 5") ==> "__1 2 3 4\n 5"
- -- justify does not overflow the alignment
- , 10 `maxWidth` justify (nestedAlign 6) ==> "1 2 3 4 5\n 6"
- , 10 `maxWidth` justify ("a b c de " .> nestedAlign 2) ==> "a b c de\n1 2"
- , 10 `maxWidth` justify (bold ("12 34 56 78 ".> underline "90" .> " 123 456 789"))
- ==> "\ESC[1m12 34 56\n78 \ESC[4m90\ESC[0;1m 123\n456 789\ESC[0m"
- -- justify does not justify on explicit newlines
- , 10 `maxWidth` justify "1 2 3 4 5 6 7\n8 9 1 2 3 4 5" ==> "1 2 3 4 5\n6 7\n8 9 1 2 3\n4 5"
- -- align flushes the buffer
- , 10 `maxWidth` justify (ul ["1 2 3 4 5 6 7 8 9"])
- ==> "- 1 2 3 4\n\
- \ 5 6 7 8\n\
- \ 9"
- -- ul/ol is empty when no item
- , ul [] ==> ""
- , ol [] ==> ""
- -- ul flushes the buffer
- , 10 `maxWidth` justify (let i = "1 2 3 4 5 6 7 8 9" in ul [i, i])
- ==> "- 1 2 3 4\n\
- \ 5 6 7 8\n\
- \ 9\n\
- \- 1 2 3 4\n\
- \ 5 6 7 8\n\
- \ 9"
- , testPlain (10 `maxWidth` justify (unorderedList (unwords_ int))) (let i = [1..9] in [i, i])
- "- 1 2 3 4\n\
- \ 5 6 7 8\n\
- \ 9\n\
- \- 1 2 3 4\n\
- \ 5 6 7 8\n\
- \ 9"
- , testPlain (11 `maxWidth` justify (orderedList (unwords_ int))) (let i = [1..9] in [i, i])
- "1. 1 2 3 4\n\
- \ 5 6 7 8\n\
- \ 9\n\
- \2. 1 2 3 4\n\
- \ 5 6 7 8\n\
- \ 9"
- , 10 `maxWidth` justify (let i = "1 2 3 4 5 6 7 8 9" in
- ul [ul [i, i], ul [i, i]])
- ==> "- - 1 2 3\n\
- \ 4 5 6\n\
- \ 7 8 9\n\
- \ - 1 2 3\n\
- \ 4 5 6\n\
- \ 7 8 9\n\
- \- - 1 2 3\n\
- \ 4 5 6\n\
- \ 7 8 9\n\
- \ - 1 2 3\n\
- \ 4 5 6\n\
- \ 7 8 9"
- , 10 `maxWidth` justify (let i = "1 2 3 4 5 6 7 8 9" in
- ol [ol [i, i], ol [i, i]])
- ==> "1. 1. 1 2\n\
- \ 3 4\n\
- \ 5 6\n\
- \ 7 8\n\
- \ 9\n\
- \ 2. 1 2\n\
- \ 3 4\n\
- \ 5 6\n\
- \ 7 8\n\
- \ 9\n\
- \2. 1. 1 2\n\
- \ 3 4\n\
- \ 5 6\n\
- \ 7 8\n\
- \ 9\n\
- \ 2. 1 2\n\
- \ 3 4\n\
- \ 5 6\n\
- \ 7 8\n\
- \ 9"
- -- endline breakspaces
- , 10 `maxWidth` ("a".>endline.>" b") ==> "a\nb"
- -- endline does no justify
- , 10 `maxWidth` justify ("a b".>endline.>" c") ==> "a b\nc"
- -- endline works overflowed
- , 10 `maxWidth` justify ("abcdefghijk".>endline.>" a") ==> "abcdefghijk\na"
- -- endline prints no nothing
- , 10 `maxWidth` justify ("12345678".>endline.>"90ab".>align (" cdefghijk cdefghijk"))
- ==> "1234567890ab\n\
- \ cdefghijk\n\
- \ cdefghijk"
- -- newline stops overflow
- , 10 `maxWidth` breakalt "fits" "over".>"\n".>"12345678901"
- ==> "fits\n\
- \12345678901"
- -- breakalt triggers only if its first argument overflows,
- -- not if what's next overflows.
- , 10 `maxWidth` spaces 2.>align(breakalt "fits" "over".>newline.>"12345678901")
- ==> " fits\n\
- \ 12345678901"
- -- handle escaping correctly over custom indenting
- , 10 `maxWidth` setIndent (blue "X") 1 (red ("12".>green "4\n5" .> "6"))
- ==> "\ESC[31m12\ESC[32m4\n\ESC[34mX\ESC[0;31;32m5\ESC[0;31m6\ESC[0m"
- , 10 `maxWidth` setIndent (blue "X") 1 (justify (red ("1 2 3 4".>green " 5 6 " .> "7 ") .> "8"))
- ==> "\ESC[31m1 2 3 4\ESC[32m 5\n\ESC[34mX\ESC[0;31;32m6 \ESC[0;31m7 \ESC[0m8"
- -- breakspace backtracking is bounded by the removable indentation
- -- (hence it can actually wrap a few words in reasonable time).
- , 80 `maxWidth`
- "Lorem ipsum dolor sit amet, Nulla nec tortor. Donec id elit quis purus\
- \ consectetur consequat. Nam congue semper tellus. Sed erat dolor,\
- \ dapibus sit amet, venenatis ornare, ultrices ut, nisi. Aliquam ante.\
- \ Suspendisse scelerisque dui nec velit. Duis augue augue, gravida euismod,\
- \ vulputate ac, facilisis id, sem. Morbi in orci. Nulla purus lacus,\
- \ pulvinar vel, malesuada ac, mattis nec, quam. Nam molestie scelerisque\
- \ quam. Nullam feugiat cursus lacus.orem ipsum dolor sit amet, consectetur\
- \ adipiscing elit. Donec libero risus, commodo vitae, pharetra mollis,\
- \ posuere eu, pede. Nulla nec tortor. Donec id elit quis purus consectetur\
- \ consequat. Nam congue semper tellus. Sed erat dolor, dapibus sit\
- \ amet, venenatis ornare, ultrices ut, nisi. Aliquam ante. Suspendisse\
- \ scelerisque dui nec velit. Duis augue augue, gravida euismod, vulputate ac,\
- \ facilisis id, sem. Morbi in orci. Nulla purus lacus, pulvinar vel,\
- \ malesuada ac, mattis nec, quam. Nam molestie scelerisque quam.\
- \ Nullam feugiat cursus lacus.orem ipsum dolor sit amet, consectetur\
- \ adipiscing elit. Donec libero risus, commodo vitae, pharetra mollis,\
- \ posuere eu, pede. Nulla nec tortor. Donec id elit quis purus consectetur\
- \ consequat. Nam congue semper tellus. Sed erat dolor, dapibus sit amet,\
- \ venenatis ornare, ultrices ut, nisi. Aliquam ante. Suspendisse\
- \ scelerisque dui nec velit. Duis augue augue, gravida euismod, vulputate ac,\
- \ facilisis id, sem. Morbi in orci. Nulla purus lacus, pulvinar vel,\
- \ malesuada ac, mattis nec, quam. Nam molestie scelerisque quam. Nullam\
- \ feugiat cursus lacus.orem ipsum dolor sit amet, consectetur adipiscing\
- \ elit. Donec libero risus, commodo vitae, pharetra mollis, posuere eu, pede.\
- \ Nulla nec tortor. Donec id elit quis purus consectetur consequat. Nam\
- \ congue semper tellus. Sed erat dolor, dapibus sit amet, venenatis ornare,\
- \ ultrices ut, nisi."
- ==> "Lorem ipsum dolor sit amet, Nulla nec tortor. Donec id elit quis\
- \ purus\nconsectetur consequat. Nam congue semper tellus. Sed erat dolor, dapibus\
- \ sit\namet, venenatis ornare, ultrices ut, nisi. Aliquam ante. Suspendisse\
- \ scelerisque\ndui nec velit. Duis augue augue, gravida euismod, vulputate ac,\
- \ facilisis id,\nsem. Morbi in orci. Nulla purus lacus, pulvinar vel, malesuada\
- \ ac, mattis nec,\nquam. Nam molestie scelerisque quam. Nullam feugiat cursus\
- \ lacus.orem ipsum\ndolor sit amet, consectetur adipiscing elit. Donec libero\
- \ risus, commodo vitae,\npharetra mollis, posuere eu, pede. Nulla nec tortor.\
- \ Donec id elit quis purus\nconsectetur consequat. Nam congue semper tellus. Sed\
- \ erat dolor, dapibus sit\namet, venenatis ornare, ultrices ut, nisi. Aliquam\
- \ ante. Suspendisse scelerisque\ndui nec velit. Duis augue augue, gravida\
- \ euismod, vulputate ac, facilisis id,\nsem. Morbi in orci. Nulla purus lacus,\
- \ pulvinar vel, malesuada ac, mattis nec,\nquam. Nam molestie scelerisque quam.\
- \ Nullam feugiat cursus lacus.orem ipsum\ndolor sit amet, consectetur adipiscing\
- \ elit. Donec libero risus, commodo vitae,\npharetra mollis, posuere eu, pede.\
- \ Nulla nec tortor. Donec id elit quis purus\nconsectetur consequat. Nam congue\
- \ semper tellus. Sed erat dolor, dapibus sit\namet, venenatis ornare, ultrices\
- \ ut, nisi. Aliquam ante. Suspendisse scelerisque\ndui nec velit. Duis augue\
- \ augue, gravida euismod, vulputate ac, facilisis id,\nsem. Morbi in orci. Nulla\
- \ purus lacus, pulvinar vel, malesuada ac, mattis nec,\nquam. Nam molestie\
- \ scelerisque quam. Nullam feugiat cursus lacus.orem ipsum\ndolor sit amet,\
- \ consectetur adipiscing elit. Donec libero risus, commodo vitae,\npharetra\
- \ mollis, posuere eu, pede. Nulla nec tortor. Donec id elit quis\
- \ purus\nconsectetur consequat. Nam congue semper tellus. Sed erat dolor, dapibus\
- \ sit\namet, venenatis ornare, ultrices ut, nisi."
- , 80 `maxWidth` justify
- "Lorem ipsum dolor sit amet, Nulla nec tortor. Donec id elit quis purus\
- \ consectetur consequat. Nam congue semper tellus. Sed erat dolor,\
- \ dapibus sit amet, venenatis ornare, ultrices ut, nisi. Aliquam ante.\
- \ Suspendisse scelerisque dui nec velit. Duis augue augue, gravida euismod,\
- \ vulputate ac, facilisis id, sem. Morbi in orci. Nulla purus lacus,\
- \ pulvinar vel, malesuada ac, mattis nec, quam. Nam molestie scelerisque\
- \ quam. Nullam feugiat cursus lacus.orem ipsum dolor sit amet, consectetur\
- \ adipiscing elit. Donec libero risus, commodo vitae, pharetra mollis,\
- \ posuere eu, pede. Nulla nec tortor. Donec id elit quis purus consectetur\
- \ consequat. Nam congue semper tellus. Sed erat dolor, dapibus sit\
- \ amet, venenatis ornare, ultrices ut, nisi. Aliquam ante. Suspendisse\
- \ scelerisque dui nec velit. Duis augue augue, gravida euismod, vulputate ac,\
- \ facilisis id, sem. Morbi in orci. Nulla purus lacus, pulvinar vel,\
- \ malesuada ac, mattis nec, quam. Nam molestie scelerisque quam.\
- \ Nullam feugiat cursus lacus.orem ipsum dolor sit amet, consectetur\
- \ adipiscing elit. Donec libero risus, commodo vitae, pharetra mollis,\
- \ posuere eu, pede. Nulla nec tortor. Donec id elit quis purus consectetur\
- \ consequat. Nam congue semper tellus. Sed erat dolor, dapibus sit amet,\
- \ venenatis ornare, ultrices ut, nisi. Aliquam ante. Suspendisse\
- \ scelerisque dui nec velit. Duis augue augue, gravida euismod, vulputate ac,\
- \ facilisis id, sem. Morbi in orci. Nulla purus lacus, pulvinar vel,\
- \ malesuada ac, mattis nec, quam. Nam molestie scelerisque quam. Nullam\
- \ feugiat cursus lacus.orem ipsum dolor sit amet, consectetur adipiscing\
- \ elit. Donec libero risus, commodo vitae, pharetra mollis, posuere eu, pede.\
- \ Nulla nec tortor. Donec id elit quis purus consectetur consequat. Nam\
- \ congue semper tellus. Sed erat dolor, dapibus sit amet, venenatis ornare,\
- \ ultrices ut, nisi."
- ==> "Lorem ipsum dolor sit amet, Nulla nec tortor. Donec id elit quis purus\n\
- \consectetur consequat. Nam congue semper tellus. Sed erat dolor, dapibus sit\n\
- \amet, venenatis ornare, ultrices ut, nisi. Aliquam ante. Suspendisse scelerisque\n\
- \dui nec velit. Duis augue augue, gravida euismod, vulputate ac, facilisis id,\n\
- \sem. Morbi in orci. Nulla purus lacus, pulvinar vel, malesuada ac, mattis nec,\n\
- \quam. Nam molestie scelerisque quam. Nullam feugiat cursus lacus.orem ipsum\n\
- \dolor sit amet, consectetur adipiscing elit. Donec libero risus, commodo vitae,\n\
- \pharetra mollis, posuere eu, pede. Nulla nec tortor. Donec id elit quis purus\n\
- \consectetur consequat. Nam congue semper tellus. Sed erat dolor, dapibus sit\n\
- \amet, venenatis ornare, ultrices ut, nisi. Aliquam ante. Suspendisse scelerisque\n\
- \dui nec velit. Duis augue augue, gravida euismod, vulputate ac, facilisis id,\n\
- \sem. Morbi in orci. Nulla purus lacus, pulvinar vel, malesuada ac, mattis nec,\n\
- \quam. Nam molestie scelerisque quam. Nullam feugiat cursus lacus.orem ipsum\n\
- \dolor sit amet, consectetur adipiscing elit. Donec libero risus, commodo vitae,\n\
- \pharetra mollis, posuere eu, pede. Nulla nec tortor. Donec id elit quis purus\n\
- \consectetur consequat. Nam congue semper tellus. Sed erat dolor, dapibus sit\n\
- \amet, venenatis ornare, ultrices ut, nisi. Aliquam ante. Suspendisse scelerisque\n\
- \dui nec velit. Duis augue augue, gravida euismod, vulputate ac, facilisis id,\n\
- \sem. Morbi in orci. Nulla purus lacus, pulvinar vel, malesuada ac, mattis nec,\n\
- \quam. Nam molestie scelerisque quam. Nullam feugiat cursus lacus.orem ipsum\n\
- \dolor sit amet, consectetur adipiscing elit. Donec libero risus, commodo vitae,\n\
- \pharetra mollis, posuere eu, pede. Nulla nec tortor. Donec id elit quis purus\n\
- \consectetur consequat. Nam congue semper tellus. Sed erat dolor, dapibus sit\n\
- \amet, venenatis ornare, ultrices ut, nisi."
- ]
+ "hell\no!wo\nrld!"
+ , testPlain (setWidth (Just 3) $ intercalate_ breakpoint string)
+ ["hello", "world"]
+ "hello\nworld"
+ , testPlain (setWidth (Just 3) $ intercalate_ breakpoint string)
+ ["he", "ll"]
+ "he\nll"
+ , testPlain (setWidth (Just 3) $ intercalate_ breakpoint string)
+ ["he", "ll", "o!"]
+ "he\nll\no!"
+ , testPlain (setWidth (Just 1) $ intercalate_ breakpoint string)
+ ["he", "ll", "o!"]
+ "he\nll\no!"
+ , testPlain (setWidth (Just 4) $ "__" .> align (intercalate_ breakpoint string))
+ ["he", "ll", "o!", "wo", "rl", "d!"]
+ "__he\n ll\n o!\n wo\n rl\n d!"
+ , testPlain (setWidth (Just 6) $ "__" .> align (intercalate_ breakpoint string))
+ ["he", "ll", "o!", "wo", "rl", "d!"]
+ "__hell\n o!wo\n rld!"
+ , testPlain (setWidth (Just 16) $ "__" .> bracketList string)
+ ["hello", "world"]
+ "__[hello, world]"
+ , testPlain (setWidth (Just 11) $ intercalate_ breakspace string)
+ ["hello", "world"]
+ "hello world"
+ , testPlain (setWidth (Just 10) $ intercalate_ breakspace string)
+ ["hello", "world"]
+ "hello\nworld"
+ , testPlain (setWidth (Just 6) $ intercalate_ breakspace string)
+ ["hel", "lo", "wo", "rld"]
+ "hel lo\nwo rld"
+ , testPlain (setWidth (Just 6) $ intercalate_ breakspace string)
+ ["hel", "lo", "wo", "rld", "HEL", "LO", "WO", "RLD"] "hel lo\nwo rld\nHEL LO\nWO RLD"
+ , testPlain (setWidth (Just 5) $ intercalate_ breakspace string)
+ ["hello", "world"]
+ "hello\nworld"
+ , testPlain (setWidth (Just 7) $ ("hello".>breakspace.>"world"))
+ ()
+ "hello\nworld"
+ , testPlain (setWidth (Just 7) $ ("hello ".>"world"))
+ ()
+ "hello\nworld"
+ , testPlain (" ".> "hello\nworld\n!")
+ ()
+ " hello\nworld\n!"
+ , testPlain ("__".>align "hello\nworld\n!")
+ ()
+ "__hello\n world\n !"
+ , testPlain (hang 2 "hello\nworld\n!") ()
+ "hello\n world\n !"
+ , testPlain (hang 2 "hello\nworld\n!".>"\nhello\n!")
+ ()
+ "hello\n world\n !\nhello\n!"
+ , testPlain (setWidth (Just 10) $ unwords_ int)
+ [1..15]
+ "1 2 3 4 5\n6 7 8 9 10\n11 12 13\n14 15"
+ , testPlain (setWidth (Just 10) $ ("1234567890" .> " ") .> "1")
+ ()
+ "1234567890\n1"
+ -- justify respects concatenating words
+ , testPlain (setWidth (Just 10) $ justify (setWidth (Just 11) ("1 2 3".>"4 5 6 7")))
+ ()
+ "1 2 34 5 6\n7"
+ -- justify flushes the buffer before
+ , testPlain (setWidth (Just 10) $ "__" .> align (justify "1 2 3 4 5"))
+ ()
+ "__1 2 3 4\n 5"
+ , testPlain (setWidth (Just 10) $ justify (bold ("12 34 56 78 ".> underline "90" .> " 123 456 789")))
+ ()
+ "\ESC[1m12 34 56\n78 \ESC[4m90\ESC[0;1m 123\n456 789\ESC[0m"
+ -- handle escaping correctly over custom indenting
+ , testPlain (setWidth (Just 10) $ setIndent (blue "X") 1 (red ("12".>green "4\n5" .> "6")))
+ ()
+ "\ESC[31m12\ESC[32m4\n\ESC[34mX\ESC[0;31;32m5\ESC[0;31m6\ESC[0m"
+ , testPlain (setWidth (Just 10) $ setIndent (blue "X") 1 (justify (red ("1 2 3 4".>green " 5 6 " .> "7 ") .> "8")))
+ ()
+ "\ESC[31m1 2 3 4\ESC[32m 5\n\ESC[34mX\ESC[0;31;32m6 \ESC[0;31m7 \ESC[0m8"
+ -- unorderedList/orderedList are empty when no item
+ , testPlain (unorderedList int) [] ""
+ , testPlain (unorderedList int) [] ""
+ -- endline break spaces
+ , testPlain (setWidth (Just 10) $ ("a".>endline.>" b")) () "a\nb"
+ -- endline does no justify
+ , testPlain (setWidth (Just 10) $ justify ("a b".>endline.>" c")) () "a b\nc"
+ -- endline works overflowed
+ , testPlain (setWidth (Just 10) $ justify ("abcdefghijk".>endline.>" a")) () "abcdefghijk\na"
+ -- endline prints nothing
+ , testPlain (setWidth (Just 10) $ justify ("12345678".>endline.>"90ab".>align (" cdefghijk cdefghijk")))
+ ()
+ "1234567890ab\n\
+ \ cdefghijk\n\
+ \ cdefghijk"
+ -- newline stops overflow
+ , testPlain (setWidth (Just 10) $ breakalt "fits" "over".>"\n".>"12345678901")
+ ()
+ "fits\n\
+ \12345678901"
+ -- breakalt triggers only if its first argument overflows,
+ -- not if what's next overflows.
+ , testPlain (setWidth (Just 10) $ spaces 2.>align(breakalt "fits" "over".>newline.>"12345678901"))
+ ()
+ " fits\n\
+ \ 12345678901"
+ ]
+ ]
where
- (==>) :: IsString o => o ~ String => Plain o () -> o -> Assertion; infix 0 ==>
- fmt ==> exp = got @?= exp
- where got = runPlain fmt ()
- testPlain :: IsString o => o ~ String => Plain o a -> a -> o -> Assertion
- testPlain fmt a exp = got @?= exp
- where got = runPlain fmt a
-
-testList :: String -> [Assertion] -> TestTree
-testList n as = testGroup n $ List.zipWith testCase (show <$> [1::Int ..]) as
-
-breakpoints ::
- Emptyable repr =>
- ProductFunctor repr =>
- Wrappable repr =>
- [repr ()] -> repr ()
-breakpoints = intercalate breakpoint
-
-breakspaces ::
- Emptyable repr =>
- ProductFunctor repr =>
- Wrappable repr =>
- [repr ()] -> repr ()
-breakspaces = intercalate breakspace
-
-infix 1 `maxWidth`
-maxWidth :: Wrappable repr => Width -> repr a -> repr a
-maxWidth = setWidth . Just
-
-nestedAlign ::
- IsString (repr ()) =>
- Indentable repr =>
- Emptyable repr =>
- ProductFunctor repr =>
- Wrappable repr =>
- Int -> repr ()
-nestedAlign n = go 1
- where
- go i =
- fromString (show i) .>
- (if n <= i then empty
- else align (breakspace .> go (i+1)))
-
-listHorV ::
- IsString (repr ()) =>
- Emptyable repr =>
- Wrappable repr =>
- ProductFunctor repr =>
- Indentable repr =>
- Newlineable repr =>
- [repr ()] -> repr ()
-listHorV [] = "[]"
-listHorV [t] = "[".>t<."]"
-listHorV ts =
- breakalt
- ("[" .> intercalate ("," .> space) ts <. "]")
- (align $ "[" .> space
- .> foldr1 (\a acc -> a <. newline <. "," <. space <. acc) ts
- <. newline <. "]")
-
-fun ::
- Wrappable repr =>
- ProductFunctor repr =>
- Indentable repr =>
- Newlineable repr =>
- IsString (repr ()) =>
- repr a -> repr a
-fun t = "function("
- .> incrIndent (spaces 2) 2 (breakalt t (newline.>t<.newline))
- <. ")"
+ testList :: String -> [Assertion] -> TestTree
+ testList n as = testGroup n $ List.zipWith testCase (show <$> [1::Int ..]) as
+ testPlain :: o ~ String => Plain o a -> a -> o -> Assertion
+ testPlain fmt a exp = runPlain fmt a @?= exp