module Bricks.IndentedString
(
InStr (..)
, inStr'join
, inStr'level
, inStr'dedent
, inStr'trim
, inStr'toList
, InStr'1 (..)
, inStr'1'nonEmpty
, inStr'1'empty
, inStr'1'modifyLevel
) where
import Bricks.Expression
import Bricks.Internal.Prelude
import Bricks.Internal.Seq (Seq, (<|))
import qualified Bricks.Internal.Seq as Seq
import qualified Bricks.Internal.Text as Text
newtype InStr = InStr { inStr'toSeq :: Seq InStr'1 }
deriving (Monoid, Semigroup)
instance Show InStr
where
show = show . inStr'toList
inStr'toList :: InStr -> [InStr'1]
inStr'toList =
Seq.toList . inStr'toSeq
data InStr'1 =
InStr'1
{ inStr'1'level :: Natural
, inStr'1'str :: Str'Dynamic
}
instance Show InStr'1
where
show (InStr'1 n s) = "indent-" <> show n <> " " <> show s
inStr'join :: InStr -> Str'Dynamic
inStr'join xs =
Str'Dynamic . Seq.concat $
Seq.intersperse
(Seq.singleton (Str'1'Literal "\n"))
(f <$> inStr'toSeq xs)
where
f :: InStr'1 -> Seq Str'1
f (InStr'1 n parts) = Str'1'Literal (Text.replicate (fromIntegral n) " ")
<| strDynamic'toSeq parts
inStr'1'nonEmpty :: InStr'1 -> Bool
inStr'1'nonEmpty =
not . inStr'1'empty
inStr'1'empty :: InStr'1 -> Bool
inStr'1'empty (InStr'1{ inStr'1'str = Str'Dynamic x }) =
Seq.null x
inStr'level :: InStr -> Natural
inStr'level =
maybe 0 id
. Seq.minimum
. Seq.map inStr'1'level
. Seq.filter inStr'1'nonEmpty
. inStr'toSeq
inStr'1'modifyLevel :: (Natural -> Natural) -> (InStr'1 -> InStr'1)
inStr'1'modifyLevel f x@InStr'1{inStr'1'level = a} =
x{ inStr'1'level = f a }
inStr'dedent :: InStr -> InStr
inStr'dedent xs =
let
b = inStr'level xs
f a = if a >= b then a b else 0
in
InStr $ inStr'1'modifyLevel f <$> inStr'toSeq xs
inStr'trim :: InStr -> InStr
inStr'trim =
InStr . trimWhile inStr'1'empty . inStr'toSeq
where
trimWhile f = Seq.dropWhileL f . Seq.dropWhileR f