packages feed

text-generic-pretty-1.2.1: src/Text/PrettyPrint/GenericPrettyStructure.hs

{-# LANGUAGE DefaultSignatures     #-}
{-# LANGUAGE FlexibleContexts      #-}
{-# LANGUAGE FlexibleInstances     #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE NoImplicitPrelude     #-}
{-# LANGUAGE OverloadedStrings     #-}
{-# LANGUAGE TypeOperators         #-}

module Text.PrettyPrint.GenericPrettyStructure
  ( PrettyStructure(..)
  , Generic
  , displayPrettyStructure
  , prettyStructure
  ) where

import qualified Data.HashMap.Strict
import qualified Data.IntMap
import           Data.IxSet.Typed             (Indexable)
import qualified Data.IxSet.Typed
import qualified Data.Map
import           Data.String.Conversions      (cs)
import qualified Data.Text                    as T
import           Data.Text.Lazy               (Text, append,
                                               fromStrict,
                                               intercalate, singleton,
                                               unlines, unwords)
import           Data.Time
import           GHC.Generics
import           Protolude                    hiding (Text, bool,
                                               intercalate,
                                               intersperse)
import           Text.PrettyPrint.Leijen.Text hiding (Pretty (..),
                                               (<$>), (<>))
import qualified Text.PrettyPrint.Leijen.Text as PP

-- | The class 'PrettyStructure' is the equivalent of 'Prelude.Show'
--
-- It provides conversion of values to prettyStructure printable PrettyStructure.Text's.
--
class PrettyStructure a where
  prettyStructure :: a -> Doc
  default prettyStructure :: (Generic a, GPrettyStructure (Rep a)) =>
    a -> Doc
  prettyStructure x =
    string "prettyStructure begin" PP.<$>
    nest 3 (fillSep ((gprettyStructure . from) x)) PP.<$>
    string "prettyStructure end"

--   prettyStructure x = case (gprettyStructure . from) x of
--                (o:[]) -> o
--                os -> PP.list os
--'GPrettyStructure' is a helper class used to output the Sum-of-Products type, since it has kind *->*,
-- so can't be an instance of 'PrettyStructure'
class GPrettyStructure f
      -- |'gprettyStructure' is the (*->*) kind equivalent of 'docPrec'
                                                                        where
  gprettyStructure :: f x -> [Doc]

-- if empty, output nothing, this is a null constructor
instance GPrettyStructure U1 where
  gprettyStructure _ = [string "M1 U Begin" PP.<> string "M1 U End"]

--                                 , append "datatypeName: " ((show . datatypeName) a)
--                                 , append "moduleName: " ((cs . moduleName) d)
--                                 , append "packageName: " ((cs .  packageName) d)
--                                 , append "isNewtype: " ((show . isNewtype) d)
-- ignore datatype meta-information
instance (GPrettyStructure f) =>
         GPrettyStructure (M1 D c f) where
  gprettyStructure (M1 a) =
    [ (string "M1 D Begin") PP.<$>
      ((nest 3 . fillSep) (gprettyStructure a)) PP.<$> (string "M1 D End")
    ]

instance (GPrettyStructure f, Selector c) =>
         GPrettyStructure (M1 S c f) where
  gprettyStructure s@(M1 a) =
    [string "M1 S Begin" PP.<$>
        (nest 3 . fillSep) [ string ("selName: " <> (cs . selName) s)
                            , fillSep (gprettyStructure a)]
        PP.<$> string "M1 S End"
    ]

-- constructor
-- here the real type and parens flag is set and propagated forward via t and n, the precedence factor is updated
instance (GPrettyStructure f, Constructor c) =>
         GPrettyStructure (M1 C c f) where
  gprettyStructure c@(M1 a) =
    [  string "M1 C Begin" PP.<$>
        (nest 3 . fillSep)[
                            string ("conName: " <> (cs . conName) c)
                            , string ("conFixity: " <> (show . conFixity) c)
                            , string ("conIsRecord: " <> (show . conIsRecord) c)
                            , fillSep (gprettyStructure a)
                         ]
        PP.<$> string "M1 C End"
    ]

-- ignore tagging, call docPrec since these are concrete types
instance (PrettyStructure f) =>
         GPrettyStructure (K1 t f) where
  gprettyStructure (K1 a) =
--     [string "M1 K Begin" <+> (nest 3 . prettyStructure) a PP.<+> string "M1 K End"]
    [string "M1 K Begin" PP.<$> (nest 3 . prettyStructure) a PP.<$> string "M1 K End"]

-- just continue to the corresponding side of the OR
instance (GPrettyStructure a, GPrettyStructure b) =>
         GPrettyStructure (a :+: b) where
  gprettyStructure (L1 x) =
    [ string "M1 :+: L1 Begin" PP.<$>
           (nest 3 . fillSep) (gprettyStructure x)
           PP.<$> string "M1 :+: L1 End"
    ]
--     [ vcat [ string "M1 :+: L1 Begin"
--            , (nest 1 . nest 3 . fillSep) (gprettyStructure x)
--            , string "\nM1 :+: L1 End"]
--     ]
--     [ string "M1 :+: L1 Begin" <+>
--         (nest 3 . fillSep) (gprettyStructure x)
--         PP.<> string "\nM1 :+: L1 End"
--     ]
  gprettyStructure (R1 x) =
    [ string "M1 :*: R1 Begin" PP.<$>
        (nest 3 . fillSep) (gprettyStructure x)
        PP.<$> string "M1 :*: R1 End"
    ]

-- output both sides of the product, possible separated by a comma or an infix operator
instance (GPrettyStructure a, GPrettyStructure b) =>
         GPrettyStructure (a :*: b) where
  gprettyStructure (x :*: y) =
    [ sep
        [ string "M1 :*: Begin"
        , (nest 1 . sep) (gprettyStructure x)
        , string ":*:"
        , (nest 1 . sep) (gprettyStructure y)
        , string "M1 :*: End"
        ]
    ]

instance PrettyStructure Char where
  prettyStructure = char

instance PrettyStructure Text where
  prettyStructure = string

instance PrettyStructure T.Text where
  prettyStructure = string . fromStrict

instance PrettyStructure Int where
  prettyStructure = int

instance PrettyStructure Integer where
  prettyStructure = integer

instance PrettyStructure Float where
  prettyStructure = float

instance PrettyStructure Double where
  prettyStructure = double

instance PrettyStructure Rational where
  prettyStructure = rational

instance PrettyStructure Bool where
  prettyStructure = bool

instance PrettyStructure ByteString where
  prettyStructure = string . cs

instance PrettyStructure a =>
         PrettyStructure [a] where
  prettyStructure = PP.list . fmap prettyStructure

instance PrettyStructure a =>
         PrettyStructure (Maybe a) where
  prettyStructure Nothing  = "Nothing"
  prettyStructure (Just x) = sep [string "Just", prettyStructure x]

instance (PrettyStructure a, PrettyStructure b) =>
         PrettyStructure (Either a b) where
  prettyStructure (Left x) = sep [string "Left", prettyStructure x]
  prettyStructure (Right y) = sep [string "Right", prettyStructure y]

instance (PrettyStructure a, PrettyStructure b) =>
         PrettyStructure (a, b) where
  prettyStructure (a, b) = tupled [prettyStructure a, prettyStructure b]

instance (PrettyStructure a, PrettyStructure b) =>
         PrettyStructure (Data.Map.Map a b) where
  prettyStructure v =
    sep [string "fromList ", (prettyStructure . Data.Map.toList) v]

instance PrettyStructure UTCTime where
  prettyStructure = text . cs . formatTime defaultTimeLocale rfc822DateFormat

instance (Show a, Indexable ixs a) =>
         PrettyStructure (Data.IxSet.Typed.IxSet ixs a) where
  prettyStructure = text . show

instance PrettyStructure Word where
  prettyStructure = (prettyStructure :: Integer -> Doc) . fromIntegral

instance PrettyStructure Word8 where
  prettyStructure = (prettyStructure :: Integer -> Doc) . fromIntegral

instance PrettyStructure Word16 where
  prettyStructure = (prettyStructure :: Integer -> Doc) . fromIntegral

instance PrettyStructure Word32 where
  prettyStructure = (prettyStructure :: Integer -> Doc) . fromIntegral

instance PrettyStructure Word64 where
  prettyStructure = (prettyStructure :: Integer -> Doc) . fromIntegral

instance PrettyStructure Int8 where
  prettyStructure = (prettyStructure :: Integer -> Doc) . fromIntegral

instance PrettyStructure Int16 where
  prettyStructure = (prettyStructure :: Integer -> Doc) . fromIntegral

instance PrettyStructure Int32 where
  prettyStructure = (prettyStructure :: Integer -> Doc) . fromIntegral

instance PrettyStructure Int64 where
  prettyStructure = (prettyStructure :: Integer -> Doc) . fromIntegral

displayPrettyStructureL
  :: PrettyStructure a
  => a -> Text
displayPrettyStructureL = PP.displayT . PP.renderPretty 1.0 70 . prettyStructure

displayPrettyStructure
  :: PrettyStructure a
  => a -> T.Text
displayPrettyStructure = toStrict . displayPrettyStructureL