-- | Pretty-print 'Show' output and JSON.
module Shower
  ( shower,
    printer,
    showerString
  ) where

import Data.Bifunctor (bimap)
import Text.Megaparsec (parse, errorBundlePretty, eof)
import Shower.Parser (pShower)
import Shower.Printer (showerRender)

-- | A drop-in replacement for @print@ that has nice layout.
-- Use it in GHCi with @-interactive-print=Shower.printer@:
--
-- @
-- ghci> :set -interactive-print=Shower.printer
-- ghci> ([1..15], ['a'..'z'])
-- ([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
--  "abcdefghijklmnopqrstuvwxyz")
-- @
--
-- NB: does not handle infinite data structures at the moment.
printer :: Show a => a -> IO ()
printer :: forall a. Show a => a -> IO ()
printer a
a = String -> IO ()
putStrLn (forall a. Show a => a -> String
shower a
a)

-- | A drop-in replacement for @show@ that has nice layout.
-- NB: does not handle infinite data structures at the moment.
shower :: Show a => a -> String
shower :: forall a. Show a => a -> String
shower a
a =
  case String -> Either String String
showerString String
s of
    Left String
_ -> String
s
    Right String
s' -> String
s'
  where
    s :: String
s = forall a. Show a => a -> String
show a
a

-- | Parse and pretty-print 'show' output or @JSON@.
showerString :: String -> Either String String
showerString :: String -> Either String String
showerString String
s =
  forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap forall s e.
(VisualStream s, TraversableStream s, ShowErrorComponent e) =>
ParseErrorBundle s e -> String
errorBundlePretty ShowerDoc -> String
showerRender (forall e s a.
Parsec e s a -> String -> s -> Either (ParseErrorBundle s e) a
parse (forall a. Shower a => Parsec Void String a
pShower forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall e s (m :: * -> *). MonadParsec e s m => m ()
eof) String
"" String
s)