1 {-# LANGUAGE DeriveFunctor #-}
2 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
4 module Symantic.Plaintext.Output where
7 import Data.Char (Char)
8 import Data.Eq (Eq (..))
9 import Data.Foldable qualified as Fold
10 import Data.Function (id, ($), (.))
11 import Data.Function qualified as Fun
12 import Data.Functor (Functor, (<$>))
13 import Data.List qualified as List
14 import Data.Maybe (Maybe (..))
15 import Data.Monoid (Monoid (..))
16 import Data.Semigroup (Semigroup (..))
17 import Data.Semigroup qualified as SG
18 import Data.String (IsString (..), String)
19 import Data.Text qualified as T
20 import Data.Text.Lazy qualified as TL
21 import Data.Text.Lazy.Builder qualified as TLB
22 import Prelude (fromIntegral)
24 import Symantic.Plaintext.Classes
26 -- * Class 'Outputable'
30 , Convertible String o
31 , Convertible T.Text o
32 , Convertible TL.Text o
39 repeatedChar :: Width -> Char -> o
40 instance Outputable String where
43 repeatedChar w c = fromString (List.replicate (fromIntegral w) c)
44 instance Outputable T.Text where
47 repeatedChar w = T.replicate (fromIntegral w) . T.singleton
48 instance Outputable TL.Text where
51 repeatedChar w = TL.replicate (fromIntegral w) . TL.singleton
53 -- * Class 'Lengthable'
54 class Lengthable o where
57 isEmpty x = length x == 0
58 instance Lengthable Char where
60 isEmpty = Fun.const False
61 instance Lengthable String where
62 length = fromIntegral . List.length
64 instance Lengthable T.Text where
65 length = fromIntegral . T.length
67 instance Lengthable TL.Text where
68 length = fromIntegral . TL.length
71 -- * Class 'Splitable'
72 class (Lengthable o, Monoid o) => Splitable o where
73 tail :: o -> Maybe (o)
74 break :: (Char -> Bool) -> o -> (o, o)
75 span :: (Char -> Bool) -> o -> (o, o)
76 span f = break (not . f)
78 splitOnChar :: (Char -> Bool) -> o -> [o]
80 if isEmpty d0 then [] else go d0
83 let (l, r) = f `break` o
87 | isEmpty rt -> [mempty]
89 splitOnCharNoEmpty :: (Char -> Bool) -> o -> [o]
90 splitOnCharNoEmpty f x =
91 let (l, r) = f `break` x
92 in [l | not (isEmpty l)]
95 Just rt -> splitOnCharNoEmpty f rt
96 instance Splitable String where
98 tail s = Just $ List.tail s
100 instance Splitable T.Text where
102 tail s = Just $ T.tail s
104 instance Splitable TL.Text where
106 tail s = Just $ TL.tail s
110 newtype Line o = Line {unLine :: o}
111 deriving (Functor, Semigroup, Monoid, Lengthable, Splitable)
113 lines :: Splitable o => o -> [Line o]
114 linesNoEmpty :: Splitable o => o -> [Line o]
115 lines = (Line <$>) . splitOnChar (== '\n')
116 linesNoEmpty = (Line <$>) . splitOnCharNoEmpty (== '\n')
119 newtype Word o = Word {unWord :: o}
120 deriving (Functor, Semigroup, Monoid, Lengthable, Splitable)
122 words :: Splitable o => Line o -> [Word o]
123 wordsNoEmpty :: Splitable o => Line o -> [Word o]
124 words = (Word <$>) . splitOnChar (== ' ') . unLine
125 wordsNoEmpty = (Word <$>) . splitOnCharNoEmpty (== ' ') . unLine
127 -- * Class 'Convertible'
128 class Convertible i o where
130 instance Convertible Char String where
132 instance Convertible String String where
134 instance Convertible T.Text String where
136 instance Convertible TL.Text String where
138 instance Convertible Char T.Text where
139 convert = T.singleton
140 instance Convertible String T.Text where
142 instance Convertible T.Text T.Text where
144 instance Convertible TL.Text T.Text where
145 convert = TL.toStrict
146 instance Convertible Char TL.Text where
147 convert = TL.singleton
148 instance Convertible String TL.Text where
150 instance Convertible T.Text TL.Text where
151 convert = TL.fromStrict
152 instance Convertible TL.Text TL.Text where
154 instance Convertible Char TLB.Builder where
155 convert = TLB.singleton
156 instance Convertible String TLB.Builder where
158 instance Convertible T.Text TLB.Builder where
159 convert = TLB.fromText
160 instance Convertible TL.Text TLB.Builder where
161 convert = TLB.fromLazyText
162 instance Convertible TLB.Builder TLB.Builder where
164 instance Convertible i o => Convertible (Word i) (Word o) where
165 convert = Word . convert . unWord
166 instance Convertible i o => Convertible (Line i) (Line o) where
167 convert = Line . convert . unLine