diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Blessings.hs | 96 |
1 files changed, 90 insertions, 6 deletions
diff --git a/src/Blessings.hs b/src/Blessings.hs index 559db3e..8b55e24 100644 --- a/src/Blessings.hs +++ b/src/Blessings.hs @@ -264,11 +264,95 @@ stripSGR = \case Empty -> Empty +normalize' :: (Eq a, Monoid a) => Blessings a -> Blessings a -> Blessings a +normalize' t t' = + if t' == t + then t + else normalize t' + + +normalize :: (Eq a, Monoid a) => Blessings a -> Blessings a +normalize = \case + Append Empty t -> normalize t + Append t Empty -> normalize t + Append (Append t1 t2) t3 -> normalize $ Append t1 (Append t2 t3) + Append (Plain s1) (Plain s2) -> normalize $ Plain (s1 <> s2) + + Append (Plain s1) (Append (Plain s2) t1) -> + normalize (Append (Plain (s1 <> s2)) t1) + + t@(Append t1@(SGR pm1 t11) t2@(Append (SGR pm2 t21) t22)) -> + let + pm1' = normalizePm pm1 + pm2' = normalizePm pm2 + in + if pm1' == pm2' + then normalize (Append (SGR pm1 (Append t11 t21)) t22) + else normalize' t $ Append (normalize t1) (normalize t2) + + t@(Append t1@(SGR pm1 t11) t2@(SGR pm2 t21)) -> + let + pm1' = normalizePm pm1 + pm2' = normalizePm pm2 + in + if pm1' == pm2' + then normalize (SGR pm1' (Append t11 t21)) + else normalize' t $ Append (normalize t1) (normalize t2) + + t@(Append t1 t2) -> normalize' t $ Append (normalize t1) (normalize t2) + SGR _ Empty -> Empty + SGR [] t -> normalize t + t@(SGR pm t1) -> normalize' t $ SGR (normalizePm pm) (normalize t1) + Plain x | x == mempty -> Empty + t@(Plain _) -> t + Empty -> Empty + + +data NormalizedPm + = NormalizedPm + { foregroundColor :: [Word8] + , backgroundColor :: [Word8] + } + +emptyNormalizedPm :: NormalizedPm +emptyNormalizedPm + = NormalizedPm + { foregroundColor = [] + , backgroundColor = [] + } + +normalizePm :: [Word8] -> [Word8] +normalizePm pm0 = + collectEffective emptyNormalizedPm $ skipCanceled pm0 pm0 + where + collectEffective p = \case + -- direct-color + (38 : 2 : r : g : b : pm) -> collectEffective (p { foregroundColor = [38, 2, r, g, b] }) pm + (48 : 2 : r : g : b : pm) -> collectEffective (p { backgroundColor = [48, 2, r, g, b] }) pm + -- indexed-color + (38 : 5 : i : pm) -> collectEffective (p { foregroundColor = [38, 5, i] }) pm + (48 : 5 : i : pm) -> collectEffective (p { backgroundColor = [48, 5, i] }) pm + (ps : pm) + -- 8-color (must be analyzed after direct- and indexed-colors) + | 30 <= ps && ps <= 39 -> collectEffective (p { foregroundColor = [ps] }) pm + | 40 <= ps && ps <= 49 -> collectEffective (p { backgroundColor = [ps] }) pm + -- ignore everything else + | otherwise -> ps : collectEffective p pm + [] -> foregroundColor p <> backgroundColor p + + skipCanceled xs = \case + (38 : 2 : _ : _ : _ : pm) -> skipCanceled xs pm + (38 : 5 : _ : pm) -> skipCanceled xs pm + xs'@(0 : pm) -> skipCanceled xs' pm + (_ : pm) -> skipCanceled xs pm + [] -> xs + + pp :: (Blessable a) => Blessings a -> a pp t = render emptyRenderState t "" -instance Blessable a => Blessable (Blessings a) where +instance (Eq a, 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 @@ -287,9 +371,9 @@ instance Blessable a => Blessable (Blessings a) where then t2' else Append t1' t2' Plain s -> - Plain (Bless.drop n s) + normalize $ Plain (Bless.drop n s) SGR pm t -> - SGR pm (Bless.drop n t) + normalize $ SGR pm (Bless.drop n t) Empty -> Empty @@ -303,15 +387,15 @@ instance Blessable a => Blessable (Blessings a) where then t1' <> Bless.take n' t2 else t1' Plain s -> - Plain (Bless.take n s) + normalize $ Plain (Bless.take n s) SGR pm t -> - SGR pm (Bless.take n t) + normalize $ SGR pm (Bless.take n t) Empty -> Empty intercalate i = \case [] -> mempty [t] -> t - (t:ts) -> t <> i <> Bless.intercalate i ts + (t:ts) -> normalize $ t <> i <> Bless.intercalate i ts fromWord8 = Plain . Bless.fromWord8 |