diff options
Diffstat (limited to 'src/Blessings.hs')
-rw-r--r-- | src/Blessings.hs | 130 |
1 files changed, 71 insertions, 59 deletions
diff --git a/src/Blessings.hs b/src/Blessings.hs index 56c1af0..21cbabd 100644 --- a/src/Blessings.hs +++ b/src/Blessings.hs @@ -1,10 +1,17 @@ {-# LANGUAGE LambdaCase #-} +{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} -module Blessings where +module Blessings + ( module Export + , module Blessings + ) where +import qualified Prelude +import Blessings.Internal as Export (Blessable) +import qualified Blessings.Internal as Bless +import Prelude hiding (length,drop,take) import Control.Applicative -import Data.List import Data.String import Data.Ix (inRange) @@ -181,7 +188,7 @@ filterPm :: (Pm -> Maybe Int) -> Pm -> Pm filterPm f = rec [] where rec ys xs@(xhead:xtail) = maybe (rec (ys ++ [xhead]) xtail) - (rec ys . flip drop xs) + (rec ys . flip Prelude.drop xs) (f xs) rec ys _ = ys @@ -204,13 +211,14 @@ type RenderState = [(FColor, BColor, Blink, Bold, Underline)] emptyRenderState :: RenderState emptyRenderState = [(ECMA48FColor 39, ECMA48BColor 49, NoBlink, NoBold, NoUnderline)] -renderString :: RenderState -> Blessings String -> String -> String -renderString _ (Plain s) y = s ++ y +render :: (Blessable a) => RenderState -> Blessings a -> a -> a + +render _ (Plain s) y = s <> y -- TODO merge successive sequences: \ESC[32m\ESC[1m -> \ESC[31;1m -renderString rs@((fc, bc, bl, b, u):_) (SGR c t) y = - renderSGR bra ++ renderString rs' t (renderSGR ket ++ y) +render rs@((fc, bc, bl, b, u):_) (SGR c t) y = + renderSGR bra <> render rs' t (renderSGR ket <> y) where fc' = maybe fc id $ fromPm c bc' = maybe bc id $ fromPm c @@ -227,57 +235,61 @@ renderString rs@((fc, bc, bl, b, u):_) (SGR c t) y = (if b' /= b then (toPm b', toPm b) else ([],[])) : (if u' /= u then (toPm u', toPm u) else ([],[])) : [] -renderString _ (SGR _ _) _ = - error "renderString called w/o proper initial state" +render _ (SGR _ _) _ = + error "render called w/o proper initial state" -- where a proper initial state is s.th. like emptyRenderState -renderString r (Append t1 t2) y = - renderString r t1 $ renderString r t2 y - -renderString _ Empty y = y - - -len :: Blessings String -> Int -len (Plain x) = length x -len (SGR _ x) = len x -len (Append t1 t2) = len t1 + len t2 -len Empty = 0 - - -pp :: Blessings String -> String -pp t = renderString emptyRenderState t "" - - -renderSGR :: Pm -> String -renderSGR [] = [] -renderSGR xs = ("\ESC["++) . (++"m") . intercalate ";" $ map show xs - - -blessingsDrop :: Int -> Blessings String -> Blessings String -blessingsDrop n = \case - Append t1 t2 -> - case compare n (len t1) of - LT -> Append (blessingsDrop n t1) t2 - EQ -> t2 - GT -> blessingsDrop (n - len t1) t2 - Plain s -> - Plain (drop n s) - SGR pm t -> - SGR pm (blessingsDrop n t) - Empty -> - Empty - - -blessingsTake :: Int -> Blessings String -> Blessings String -blessingsTake n = \case - Append t1 t2 -> - case compare n (len t1) of - LT -> blessingsTake n t1 - EQ -> t1 - GT -> Append t1 (blessingsTake (n - len t1) t2) - Plain s -> - Plain (take n s) - SGR pm t -> - SGR pm (blessingsTake n t) - Empty -> - Empty +render r (Append t1 t2) y = + render r t1 $ render r t2 y + +render _ Empty y = y + + +renderSGR :: (Blessable a) => Pm -> a +renderSGR [] = mempty +renderSGR pm = + ("\ESC["<>) . (<>"m") . Bless.intercalate ";" . map Bless.fromInt $ pm + + +pp :: (Blessable a) => Blessings a -> a +pp t = render emptyRenderState t "" + + +instance Blessable a => Blessable (Blessings a) where + length (Plain x) = Bless.length x + length (SGR _ t) = Bless.length t + length (Append t1 t2) = Bless.length t1 + Bless.length t2 + length Empty = 0 + + drop n = \case + Append t1 t2 -> + case compare n (Bless.length t1) of + LT -> Bless.drop n t1 <> t2 + EQ -> t2 + GT -> Bless.drop (n - Bless.length t1) t2 + Plain s -> + Plain (Bless.drop n s) + SGR pm t -> + SGR pm (Bless.drop n t) + Empty -> + Empty + + take n = \case + Append t1 t2 -> + case compare n (Bless.length t1) of + LT -> Bless.take n t1 + EQ -> t1 + GT -> t1 <> Bless.take (n - Bless.length t1) t2 + Plain s -> + Plain (Bless.take n s) + SGR pm t -> + SGR pm (Bless.take n t) + Empty -> + Empty + + intercalate i = \case + [] -> mempty + [t] -> t + (t:ts) -> t <> i <> Bless.intercalate i ts + + fromInt = Plain . Bless.fromInt |