1 {-# LANGUAGE PolyKinds #-}
 
   2 {-# LANGUAGE ViewPatterns #-}
 
   3 module Language.Symantic.Document.Sym where
 
   5 import Data.Char (Char)
 
   6 import Data.Eq (Eq(..))
 
   7 import Data.Foldable (Foldable(..))
 
   8 import Data.Maybe (Maybe(..))
 
   9 import Data.Function ((.))
 
  10 import Data.Functor (Functor(..))
 
  12 import Data.Semigroup (Semigroup(..))
 
  13 import Data.String (String, IsString)
 
  14 import Data.Text (Text)
 
  15 import Prelude (Integer)
 
  16 import qualified Data.List as L
 
  17 import qualified Data.Text as T
 
  18 import qualified Data.Text.Lazy as TL
 
  21 class (IsString d, Semigroup d) => Doc_Text d where
 
  27         integer :: Integer -> d
 
  32         charH   :: Char    -> d -- XXX: MUST NOT be '\n'
 
  33         stringH :: String  -> d -- XXX: MUST NOT contain '\n'
 
  34         textH   :: Text    -> d -- XXX: MUST NOT contain '\n'
 
  35         ltextH  :: TL.Text -> d -- XXX: MUST NOT contain '\n'
 
  36         catH    :: Foldable f => f d -> d
 
  37         catV    :: Foldable f => f d -> d
 
  41         default spaces  :: Doc_Text (ReprOf d) => Trans d => Int -> d
 
  42         default int     :: Doc_Text (ReprOf d) => Trans d => Int -> d
 
  43         default integer :: Doc_Text (ReprOf d) => Trans d => Integer -> d
 
  44         default charH   :: Doc_Text (ReprOf d) => Trans d => Char -> d
 
  45         default stringH :: Doc_Text (ReprOf d) => Trans d => String -> d
 
  46         default textH   :: Doc_Text (ReprOf d) => Trans d => Text -> d
 
  47         default ltextH  :: Doc_Text (ReprOf d) => Trans d => TL.Text -> d
 
  48         -- default catH    :: Doc_Text (ReprOf d) => Trans d => Foldable f => Functor f => f d -> d
 
  49         -- default catV    :: Doc_Text (ReprOf d) => Trans d => Foldable f => Functor f => f d -> d
 
  53         spaces  = trans . spaces
 
  55         integer = trans . integer
 
  56         char    = \case '\n' -> eol; c -> charH c
 
  57         string  = catV . fmap stringH . lines
 
  58         text    = catV . fmap textH   . lines
 
  59         ltext   = catV . fmap ltextH  . lines
 
  61         stringH = trans . stringH
 
  63         ltextH  = trans . ltextH
 
  64         -- catH  l = trans (catH (fmap unTrans l))
 
  65         catH    = foldr (<>) empty
 
  66         -- catV  l = trans (catV (fmap unTrans l))
 
  67         catV l | null l = empty
 
  68         catV l          = foldr1 (\a acc -> a <> eol <> acc) l
 
  69         dquote d  = "\"" <> d <> "\""
 
  70         fquote d  = "« " <> d <> " »"
 
  71         squote d  = "'"  <> d <> "'"
 
  73 -- * Class 'Doc_Color'
 
  74 class Doc_Color d where
 
 115         onMagentaer :: d -> d
 
 119         default reverse     :: Doc_Color (ReprOf d) => Trans d => d -> d
 
 120         default black       :: Doc_Color (ReprOf d) => Trans d => d -> d
 
 121         default red         :: Doc_Color (ReprOf d) => Trans d => d -> d
 
 122         default green       :: Doc_Color (ReprOf d) => Trans d => d -> d
 
 123         default yellow      :: Doc_Color (ReprOf d) => Trans d => d -> d
 
 124         default blue        :: Doc_Color (ReprOf d) => Trans d => d -> d
 
 125         default magenta     :: Doc_Color (ReprOf d) => Trans d => d -> d
 
 126         default cyan        :: Doc_Color (ReprOf d) => Trans d => d -> d
 
 127         default white       :: Doc_Color (ReprOf d) => Trans d => d -> d
 
 128         default blacker     :: Doc_Color (ReprOf d) => Trans d => d -> d
 
 129         default redder      :: Doc_Color (ReprOf d) => Trans d => d -> d
 
 130         default greener     :: Doc_Color (ReprOf d) => Trans d => d -> d
 
 131         default yellower    :: Doc_Color (ReprOf d) => Trans d => d -> d
 
 132         default bluer       :: Doc_Color (ReprOf d) => Trans d => d -> d
 
 133         default magentaer   :: Doc_Color (ReprOf d) => Trans d => d -> d
 
 134         default cyaner      :: Doc_Color (ReprOf d) => Trans d => d -> d
 
 135         default whiter      :: Doc_Color (ReprOf d) => Trans d => d -> d
 
 136         default onBlack     :: Doc_Color (ReprOf d) => Trans d => d -> d
 
 137         default onRed       :: Doc_Color (ReprOf d) => Trans d => d -> d
 
 138         default onGreen     :: Doc_Color (ReprOf d) => Trans d => d -> d
 
 139         default onYellow    :: Doc_Color (ReprOf d) => Trans d => d -> d
 
 140         default onBlue      :: Doc_Color (ReprOf d) => Trans d => d -> d
 
 141         default onMagenta   :: Doc_Color (ReprOf d) => Trans d => d -> d
 
 142         default onCyan      :: Doc_Color (ReprOf d) => Trans d => d -> d
 
 143         default onWhite     :: Doc_Color (ReprOf d) => Trans d => d -> d
 
 144         default onBlacker   :: Doc_Color (ReprOf d) => Trans d => d -> d
 
 145         default onRedder    :: Doc_Color (ReprOf d) => Trans d => d -> d
 
 146         default onGreener   :: Doc_Color (ReprOf d) => Trans d => d -> d
 
 147         default onYellower  :: Doc_Color (ReprOf d) => Trans d => d -> d
 
 148         default onBluer     :: Doc_Color (ReprOf d) => Trans d => d -> d
 
 149         default onMagentaer :: Doc_Color (ReprOf d) => Trans d => d -> d
 
 150         default onCyaner    :: Doc_Color (ReprOf d) => Trans d => d -> d
 
 151         default onWhiter    :: Doc_Color (ReprOf d) => Trans d => d -> d
 
 153         reverse     = trans1 reverse
 
 157         yellow      = trans1 yellow
 
 159         magenta     = trans1 magenta
 
 162         blacker     = trans1 blacker
 
 163         redder      = trans1 redder
 
 164         greener     = trans1 greener
 
 165         yellower    = trans1 yellower
 
 167         magentaer   = trans1 magentaer
 
 168         cyaner      = trans1 cyaner
 
 169         whiter      = trans1 whiter
 
 170         onBlack     = trans1 onBlack
 
 172         onGreen     = trans1 onGreen
 
 173         onYellow    = trans1 onYellow
 
 174         onBlue      = trans1 onBlue
 
 175         onMagenta   = trans1 onMagenta
 
 176         onCyan      = trans1 onCyan
 
 177         onWhite     = trans1 onWhite
 
 178         onBlacker   = trans1 onBlacker
 
 179         onRedder    = trans1 onRedder
 
 180         onGreener   = trans1 onGreener
 
 181         onYellower  = trans1 onYellower
 
 182         onBluer     = trans1 onBluer
 
 183         onMagentaer = trans1 onMagentaer
 
 184         onCyaner    = trans1 onCyaner
 
 185         onWhiter    = trans1 onWhiter
 
 187 -- * Class 'Doc_Decoration'
 
 188 class Doc_Decoration d where
 
 192         default bold      :: Doc_Decoration (ReprOf d) => Trans d => d -> d
 
 193         default underline :: Doc_Decoration (ReprOf d) => Trans d => d -> d
 
 194         default italic    :: Doc_Decoration (ReprOf d) => Trans d => d -> d
 
 196         underline = trans1 underline
 
 197         italic    = trans1 italic
 
 201         -- | Return the underlying @tr@ of the transformer.
 
 204         -- | Lift a tr to the transformer's.
 
 205         trans :: ReprOf tr -> tr
 
 206         -- | Unlift a tr from the transformer's.
 
 207         unTrans :: tr -> ReprOf tr
 
 209         -- | Identity transformation for a unary symantic method.
 
 210         trans1 :: (ReprOf tr -> ReprOf tr) -> (tr -> tr)
 
 211         trans1 f = trans . f . unTrans
 
 213         -- | Identity transformation for a binary symantic method.
 
 215          :: (ReprOf tr -> ReprOf tr -> ReprOf tr)
 
 217         trans2 f t1 t2 = trans (f (unTrans t1) (unTrans t2))
 
 219         -- | Identity transformation for a ternary symantic method.
 
 221          :: (ReprOf tr -> ReprOf tr -> ReprOf tr -> ReprOf tr)
 
 222          -> (tr -> tr -> tr -> tr)
 
 223         trans3 f t1 t2 t3 = trans (f (unTrans t1) (unTrans t2) (unTrans t3))
 
 226 -- * Class 'SplitOnCharWithEmpty'
 
 227 class SplitOnCharWithEmpty t where
 
 228         splitOnCharWithEmpty :: Char -> t -> [t]
 
 229 instance SplitOnCharWithEmpty Text where
 
 230         splitOnCharWithEmpty sep t =
 
 231                 case T.break (== sep) t of
 
 232                  (chunk, T.uncons -> Just (_, rest)) -> chunk : splitOnCharWithEmpty sep rest
 
 233                  (chunk, _) -> [chunk]
 
 234 instance SplitOnCharWithEmpty TL.Text where
 
 235         splitOnCharWithEmpty sep t =
 
 236                 case TL.break (== sep) t of
 
 237                  (chunk, TL.uncons -> Just (_, rest)) -> chunk : splitOnCharWithEmpty sep rest
 
 238                  (chunk, _) -> [chunk]
 
 239 instance SplitOnCharWithEmpty String where
 
 240         splitOnCharWithEmpty sep t =
 
 241                 case L.break (== sep) t of
 
 242                  (chunk, _:rest) -> chunk : splitOnCharWithEmpty sep rest
 
 243                  (chunk, []) -> [chunk]
 
 245 lines :: SplitOnCharWithEmpty t => t -> [t]
 
 246 lines = splitOnCharWithEmpty '\n'
 
 252 -- * Class 'SplitOnChar'
 
 254 class SplitOnChar t where
 
 255         splitOnChar :: Char -> t -> [t]
 
 256 instance SplitOnChar Text where
 
 258                 case Text.uncons t of
 
 262                         then splitOnChar sep xs
 
 264                                 let (chunk, rest) = Text.break (== sep) t in
 
 265                                 chunk:splitOnChar sep rest
 
 266 instance SplitOnChar String where
 
 272                         then splitOnChar sep xs
 
 274                                 let (chunk, rest) = List.break (== sep) t in
 
 275                                 chunk:splitOnChar sep rest