{-# LANGUAGE FlexibleInstances #-}
module Text.Layout.Table.StringBuilder where

import Data.Semigroup

-- | A type that is used to construct parts of a table.
class Monoid a => StringBuilder a where
    -- | Create a builder with a 'String'.
    stringB :: String -> a

    -- | Create a builder with a single 'Char'.
    charB :: Char -> a

    -- | Create a builder with several 'Char's.
    replicateCharB :: Int -> Char -> a
    replicateCharB Int
i Char
c = Int -> a -> a
forall b a. (Integral b, Monoid a) => b -> a -> a
stimesMonoid Int
i (Char -> a
forall a. StringBuilder a => Char -> a
charB Char
c)

    {-# MINIMAL stringB, charB #-}

-- | Create a builder that contains /k/ spaces. Negative numbers are treated as
-- zero.
spacesB :: StringBuilder a => Int -> a
spacesB :: Int -> a
spacesB Int
k = Int -> Char -> a
forall a. StringBuilder a => Int -> Char -> a
replicateCharB Int
k Char
' '

instance StringBuilder String where
    stringB :: String -> String
stringB = String -> String
forall a. a -> a
id
    charB :: Char -> String
charB = (Char -> String -> String
forall a. a -> [a] -> [a]
: [])
    replicateCharB :: Int -> Char -> String
replicateCharB = Int -> Char -> String
forall a. Int -> a -> [a]
replicate

instance StringBuilder (Endo String) where
    stringB :: String -> Endo String
stringB = String -> Endo String
forall m. Semigroup m => m -> Endo m
diff
    charB :: Char -> Endo String
charB = (String -> String) -> Endo String
forall a. (a -> a) -> Endo a
Endo ((String -> String) -> Endo String)
-> (Char -> String -> String) -> Char -> Endo String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (:)
    replicateCharB :: Int -> Char -> Endo String
replicateCharB Int
i Char
c = (String -> String) -> Endo String
forall a. (a -> a) -> Endo a
Endo ((String -> String) -> Endo String)
-> (String -> String) -> Endo String
forall a b. (a -> b) -> a -> b
$ \String
s -> ((String -> String) -> String -> String)
-> String -> [String -> String] -> String
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
($) String
s ([String -> String] -> String) -> [String -> String] -> String
forall a b. (a -> b) -> a -> b
$ Int -> (String -> String) -> [String -> String]
forall a. Int -> a -> [a]
replicate Int
i (Char
c Char -> String -> String
forall a. a -> [a] -> [a]
:)