-- |
-- Module : Data.Herb.Pretty
-- Description : Pretty-printing of Herb structures
--
-- This provides `herbDoc` (and `herbsDoc`) that convert `Herb` (and foldable
-- containers thereof) into `Doc`.
module Data.Herb.Pretty where

import Data.Foldable (toList)
import Data.Herb

import qualified Data.Text as T
import qualified Text.PrettyPrint as PP
import Text.PrettyPrint (Doc, comma, parens, punctuate, render, sep, text, vcat)

-- | Convert a `Herb` structure into `Doc`.
herbDoc :: Herb -> Doc
herbDoc :: Herb -> Doc
herbDoc (Atom Ident
a) = String -> Doc
text (String -> Doc) -> (Ident -> String) -> Ident -> Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ident -> String
T.unpack (Ident -> Doc) -> Ident -> Doc
forall a b. (a -> b) -> a -> b
$ Ident -> Ident
escAtom Ident
a
herbDoc (Struct Ident
h [Herb]
ps) =
  Herb -> Doc
herbDoc (Ident -> Herb
Atom Ident
h) Doc -> Doc -> Doc
PP.<> Doc -> Doc
parens ([Doc] -> Doc
sep ([Doc] -> Doc) -> ([Doc] -> [Doc]) -> [Doc] -> Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Doc -> [Doc] -> [Doc]
punctuate Doc
comma ([Doc] -> Doc) -> [Doc] -> Doc
forall a b. (a -> b) -> a -> b
$ (Herb -> Doc) -> [Herb] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map Herb -> Doc
herbDoc [Herb]
ps)

-- | Convert a foldable container of `Herb` structures into `Doc` from
-- "Text.PrettyPrint", concatenating them vertically.
herbsDoc :: Foldable f => f Herb -> Doc
herbsDoc :: forall (f :: * -> *). Foldable f => f Herb -> Doc
herbsDoc = [Doc] -> Doc
vcat ([Doc] -> Doc) -> (f Herb -> [Doc]) -> f Herb -> Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Herb -> Doc) -> [Herb] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map Herb -> Doc
herbDoc ([Herb] -> [Doc]) -> (f Herb -> [Herb]) -> f Herb -> [Doc]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. f Herb -> [Herb]
forall a. f a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList

-- | Directly produce a pretty `String` representation of `Herb` using the
-- default rendering style of "Text.PrettyPrint". To render using a custom
-- style, run `Text.PrettyPrint.renderStyle` with appropriate parameters.
prettyHerb :: Herb -> String
prettyHerb :: Herb -> String
prettyHerb = Doc -> String
render (Doc -> String) -> (Herb -> Doc) -> Herb -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Herb -> Doc
herbDoc

-- | Like `prettyHerb` but for foldable containers. This adds the final newline
-- (which is missing in the default rendering by "Text.PrettyPrint".
prettyHerbs :: Foldable f => f Herb -> String
prettyHerbs :: forall (f :: * -> *). Foldable f => f Herb -> String
prettyHerbs = (String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\n") (String -> String) -> (f Herb -> String) -> f Herb -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Doc -> String
render (Doc -> String) -> (f Herb -> Doc) -> f Herb -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. f Herb -> Doc
forall (f :: * -> *). Foldable f => f Herb -> Doc
herbsDoc