summaryrefslogtreecommitdiffstats
path: root/src/Blessings/Seq2.hs
blob: 69e41ae450d07f5e2fea0f72073e5c4a37497952 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
{-# OPTIONS_GHC -Wno-orphans #-}
{-# LANGUAGE TypeFamilies #-}
module Blessings.Seq2 where

import Blessings
import Data.DList qualified as D
import Data.Seq2
import Data.Text (Text)
import Data.Text qualified as T


instance Seq2 Blessings Text where
  type Element Text = Char
  split2 = split2By (not . T.null) T.split


split2By :: (Monoid a) => (a -> Bool) -> (t -> a -> [a]) -> t -> Blessings a -> [Blessings a]
split2By isNonEmpty split p = finalize . cataBlessings algPlain algSGR algAppend
  where

    ------------------------------------------------------------------
    -- Accumulator:
    --
    --   Nothing                  = no chunks
    --   Just (open, front, last) = front ++ [last]
    --
    -- front :: DList (Blessings Text)    = all chunks except the last
    -- last  :: Blessings Text            = last chunk
    ------------------------------------------------------------------

    finalize Nothing            = []
    finalize (Just (_, f, l))   = D.toList f ++ [l]

    algPlain t =
      case split p t of
        -- [] -> undefined -- Data.Text.split returned []
        [x] ->
          Just ( isNonEmpty x
               , D.empty
               , Plain x
               )
        xs ->
          Just ( isNonEmpty (last xs)
               , D.fromList (map Plain (init xs))
               , Plain (last xs)
               )

    algSGR _ Nothing = Nothing
    algSGR s (Just (o, f, l)) =
      Just ( o
           , D.map (SGR s) f
           , SGR s l
           )

    algAppend Nothing r = r
    algAppend l Nothing = l
    algAppend (Just (ox, fx, lx)) (Just (oy, fy, ly))
      | ox && oy  = mergeOpen fx lx fy ly oy
      | otherwise = noMerge   fx lx fy ly oy

    mergeOpen fx lx fy ly oy =
      case fy of
        D.Nil ->
          Just (oy, fx, Append lx ly)

        D.Cons f fs ->
          Just ( oy
               , fx `D.snoc` Append lx f `D.append` D.fromList fs
               , ly
               )

        _ -> undefined -- impossible since all DList are constructed safely

    noMerge fx lx fy ly oy =
      Just ( oy
           , fx `D.snoc` lx `D.append` fy
           , ly
           )