1 {-# LANGUAGE DeriveFunctor #-}
2 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
3 module Symantic.Formatter.Output where
6 import Data.Char (Char)
7 import Data.Eq (Eq(..))
8 import Data.Function ((.), ($), id)
9 import Data.Functor (Functor, (<$>))
10 import Data.Maybe (Maybe(..))
11 import Data.Monoid (Monoid(..))
12 import Data.Semigroup (Semigroup(..))
13 import Data.String (String, IsString(..))
14 import Prelude (fromIntegral)
15 import qualified Data.Function as Fun
16 import qualified Data.Semigroup as SG
17 import qualified Data.Foldable as Fold
18 import qualified Data.List as List
19 import qualified Data.Text as T
20 import qualified Data.Text.Lazy as TL
21 import qualified Data.Text.Lazy.Builder as TLB
23 import Symantic.Formatter.Class
25 -- * Class 'Outputable'
29 , Convertible String o
30 , Convertible T.Text o
31 , Convertible TL.Text o
33 ) => Outputable o where
36 repeatedChar :: Width -> Char -> o
37 instance Outputable String where
40 repeatedChar w c = fromString (List.replicate (fromIntegral w) c)
41 instance Outputable T.Text where
44 repeatedChar w = T.replicate (fromIntegral w) . T.singleton
45 instance Outputable TL.Text where
48 repeatedChar w = TL.replicate (fromIntegral w) . TL.singleton
50 -- * Class 'Lengthable'
51 class Lengthable o where
54 isEmpty x = length x == 0
55 instance Lengthable Char where
57 isEmpty = Fun.const False
58 instance Lengthable String where
59 length = fromIntegral . List.length
61 instance Lengthable T.Text where
62 length = fromIntegral . T.length
64 instance Lengthable TL.Text where
65 length = fromIntegral . TL.length
68 -- * Class 'Splitable'
69 class (Lengthable o, Monoid o) => Splitable o where
70 tail :: o -> Maybe (o)
71 break :: (Char -> Bool) -> o -> (o, o)
72 span :: (Char -> Bool) -> o -> (o, o)
73 span f = break (not . f)
75 splitOnChar :: (Char -> Bool) -> o -> [o]
77 if isEmpty d0 then [] else go d0
80 let (l,r) = f`break`o in
83 Just rt | isEmpty rt -> [mempty]
85 splitOnCharNoEmpty :: (Char -> Bool) -> o -> [o]
86 splitOnCharNoEmpty f x =
87 let (l,r) = f`break`x in
88 [ l | not (isEmpty l) ] SG.<>
91 Just rt -> splitOnCharNoEmpty f rt
92 instance Splitable String where
94 tail s = Just $ List.tail s
96 instance Splitable T.Text where
98 tail s = Just $ T.tail s
100 instance Splitable TL.Text where
102 tail s = Just $ TL.tail s
106 newtype Line o = Line { unLine :: o }
107 deriving (Functor, Semigroup, Monoid, Lengthable, Splitable)
109 lines :: Splitable o => o -> [Line o]
110 linesNoEmpty :: Splitable o => o -> [Line o]
111 lines = (Line <$>) . splitOnChar (== '\n')
112 linesNoEmpty = (Line <$>) . splitOnCharNoEmpty (== '\n')
115 newtype Word o = Word { unWord :: o }
116 deriving (Functor, Semigroup, Monoid, Lengthable, Splitable)
118 words :: Splitable o => Line o -> [Word o]
119 wordsNoEmpty :: Splitable o => Line o -> [Word o]
120 words = (Word <$>) . splitOnChar (== ' ') . unLine
121 wordsNoEmpty = (Word <$>) . splitOnCharNoEmpty (== ' ') . unLine
123 -- * Class 'Convertible'
124 class Convertible i o where
126 instance Convertible Char String where
128 instance Convertible String String where
130 instance Convertible T.Text String where
132 instance Convertible TL.Text String where
134 instance Convertible Char T.Text where
135 convert = T.singleton
136 instance Convertible String T.Text where
138 instance Convertible T.Text T.Text where
140 instance Convertible TL.Text T.Text where
141 convert = TL.toStrict
142 instance Convertible Char TL.Text where
143 convert = TL.singleton
144 instance Convertible String TL.Text where
146 instance Convertible T.Text TL.Text where
147 convert = TL.fromStrict
148 instance Convertible TL.Text TL.Text where
150 instance Convertible Char TLB.Builder where
151 convert = TLB.singleton
152 instance Convertible String TLB.Builder where
154 instance Convertible T.Text TLB.Builder where
155 convert = TLB.fromText
156 instance Convertible TL.Text TLB.Builder where
157 convert = TLB.fromLazyText
158 instance Convertible TLB.Builder TLB.Builder where
160 instance Convertible i o => Convertible (Word i) (Word o) where
161 convert = Word . convert . unWord
162 instance Convertible i o => Convertible (Line i) (Line o) where
163 convert = Line . convert . unLine