module Blammo.Logging.Terminal.LogPiece
  ( LogPiece
  , logPiece
  , render
  , visibleLength
  , bytestring

  -- * Built-in pieces
  , offset
  ) where

import Prelude

import Data.ByteString (ByteString)
import Data.Semigroup (Sum(..))
import Data.String (IsString(..))
import Data.Text (Text, pack)
import qualified Data.Text as T
import Data.Text.Encoding (encodeUtf8)

data LogPiece = LogPiece
  { LogPiece -> Text
lpRendered :: Text
  , LogPiece -> Sum Int
lpVisibleLength :: Sum Int
  }
  -- TODO: When we drop support for ghc-8.6:
  -- deriving stock Generic
  -- deriving (Semigroup, Monoid) via (GenericSemigroupMonoid LogPiece)

instance Semigroup LogPiece where
  LogPiece
a <> :: LogPiece -> LogPiece -> LogPiece
<> LogPiece
b = LogPiece
    { lpRendered :: Text
lpRendered = LogPiece -> Text
lpRendered LogPiece
a forall a. Semigroup a => a -> a -> a
<> LogPiece -> Text
lpRendered LogPiece
b
    , lpVisibleLength :: Sum Int
lpVisibleLength = LogPiece -> Sum Int
lpVisibleLength LogPiece
a forall a. Semigroup a => a -> a -> a
<> LogPiece -> Sum Int
lpVisibleLength LogPiece
b
    }

instance Monoid LogPiece where
  mempty :: LogPiece
mempty = Text -> Sum Int -> LogPiece
LogPiece forall a. Monoid a => a
mempty forall a. Monoid a => a
mempty

instance IsString LogPiece where
  fromString :: String -> LogPiece
fromString = (Text -> Text) -> Text -> LogPiece
logPiece forall a. a -> a
id forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
pack

logPiece
  :: (Text -> Text)
  -- ^ Non-visible decoration, such as color escapes
  -> Text
  -- ^ Raw
  -> LogPiece
logPiece :: (Text -> Text) -> Text -> LogPiece
logPiece Text -> Text
f Text
t =
  LogPiece { lpRendered :: Text
lpRendered = Text -> Text
f Text
t, lpVisibleLength :: Sum Int
lpVisibleLength = forall a. a -> Sum a
Sum forall a b. (a -> b) -> a -> b
$ Text -> Int
T.length Text
t }

render :: LogPiece -> Text
render :: LogPiece -> Text
render = LogPiece -> Text
lpRendered

bytestring :: LogPiece -> ByteString
bytestring :: LogPiece -> ByteString
bytestring = Text -> ByteString
encodeUtf8 forall b c a. (b -> c) -> (a -> b) -> a -> c
. LogPiece -> Text
render

visibleLength :: LogPiece -> Int
visibleLength :: LogPiece -> Int
visibleLength = forall a. Sum a -> a
getSum forall b c a. (b -> c) -> (a -> b) -> a -> c
. LogPiece -> Sum Int
lpVisibleLength

offset :: Int -> LogPiece
offset :: Int -> LogPiece
offset Int
n = LogPiece { lpRendered :: Text
lpRendered = Int -> Text -> Text
T.replicate Int
n Text
" ", lpVisibleLength :: Sum Int
lpVisibleLength = forall a. a -> Sum a
Sum Int
n }