1 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
2 {-# LANGUAGE UndecidableInstances #-}
3 module Symantic.Formatter.Class
4 ( module Symantic.Formatter.Class
10 --import Control.Applicative (Applicative(..))
12 import Data.Char (Char)
13 import Data.Foldable (Foldable)
14 import Data.Function ((.), ($))
15 --import Data.Function ((.), ($), id, const)
16 --import Data.Functor (Functor(..), (<$>))
18 --import Data.Kind (Type)
19 import Data.Maybe (Maybe(..))
20 import Data.Ord (Ord(..))
21 import Prelude (fromIntegral, pred)
22 import Data.String (String)
23 --import Data.Text (Text)
24 import Data.Traversable (Traversable)
25 import Numeric.Natural (Natural)
26 import qualified Data.Functor as Fct
27 import qualified Data.Foldable as Fold
28 --import qualified Data.Text.Lazy.Builder as TLB
29 import qualified System.Console.ANSI as ANSI
30 import Symantic.Derive
38 Emptyable repr => ProductFunctor repr =>
39 Foldable f => f (repr ()) -> repr ()
40 concat = Fold.foldr (.>) empty
50 newtype Horiz repr a = Horiz { unHoriz :: repr a }
51 deriving (Eq, Show, Semigroup)
52 type instance Derived (Horiz repr) = repr
53 instance Derivable (Horiz repr) where
55 instance LiftDerived (Horiz repr) where
57 instance LiftDerived1 (Horiz repr)
58 instance LiftDerived2 (Horiz repr)
59 instance LiftDerived3 (Horiz repr)
60 instance Emptyable repr => Emptyable (Horiz repr)
61 --instance Semigroupable repr => Semigroupable (Horiz repr)
62 instance ProductFunctor repr => ProductFunctor (Horiz repr) where
63 (<.) = liftDerived2 (<.)
64 (.>) = liftDerived2 (.>)
68 ) => Spaceable (Horiz repr)
72 instance From [SGR] repr => From [SGR] (Horiz repr) where
75 class Inject a repr ty where
76 inject :: a -> repr ty
77 instance Inject String repr H => Inject Int repr H where
78 inject = inject . show
79 instance Inject String repr H => Inject Integer repr H where
80 inject = inject . show
81 instance Inject String repr H => Inject Natural repr H where
82 inject = inject . show
83 instance Inject String repr H => Inject [SGR] repr H where
84 inject = inject . ANSI.setSGRCode
85 instance Inject Text repr a => Inject TL.Text repr a where
86 inject = inject . TL.toStrict
91 class From a repr where
93 default from :: From String repr => Show a => a -> repr
97 instance From repr String => From (Line repr) String where
99 instance From repr String => From (Word repr) String where
101 instance From [SGR] String where
102 from = ANSI.setSGRCode
105 instance From repr Text => From (Line repr) Text where
107 instance From repr Text => From (Word repr) Text where
109 instance From [SGR] Text where
110 from = from . ANSI.setSGRCode
113 instance From repr TL.Text => From (Line repr) TL.Text where
115 instance From repr TL.Text => From (Word repr) TL.Text where
117 instance From [SGR] TL.Text where
118 from = from . ANSI.setSGRCode
121 instance From repr TLB.Builder => From (Line repr) TLB.Builder where
123 instance From repr TLB.Builder => From (Word repr) TLB.Builder where
125 instance From [SGR] TLB.Builder where
126 from = from . ANSI.setSGRCode
128 runTextBuilder :: TLB.Builder -> TL.Text
129 runTextBuilder = TLB.toLazyText
132 -- * Class 'Spaceable'
134 ( ProductFunctor repr
136 ) => Spaceable repr where
138 -- | @'spaces' ind = 'replicate' ind 'space'@
139 spaces :: Column -> repr ()
140 default space :: FromDerived Spaceable repr => repr ()
141 default spaces :: Column -> repr ()
142 spaces i = replicate (fromIntegral i) space
143 space = liftDerived space
144 -- | @x '<+>' y = x '<>' 'space' '<>' y@
145 (<+>) :: repr a -> repr b -> repr (a,b)
146 x <+> y = x <.> space .> y
147 (+>) :: repr () -> repr a -> repr a
148 x +> y = x .> space .> y
149 (<+) :: repr a -> repr () -> repr a
150 x <+ y = x <. space <. y
152 -- * Class 'Newlineable'
153 class Newlineable repr where
155 default newline :: FromDerived Newlineable repr => repr ()
156 newline = liftDerived newline
160 ProductFunctor repr =>
162 f (repr ()) -> repr ()
163 unlines = Fold.foldr (\x acc -> x.>newline.>acc) empty
164 unlines_ :: Listable repr => repr a -> repr [a]
165 unlines_ = intercalate_ newline
166 -- | @x '</>' y = x '<>' 'newline' '<>' y@
167 (</>) :: ProductFunctor repr => repr a -> repr b -> repr (a,b)
168 x </> y = x <.> newline .> y
170 ProductFunctor repr =>
173 f (repr ()) -> repr ()
174 catV = intercalate newline
178 instance Spaceable (f String) where
181 spaces n = List.replicate (fromIntegral n) ' '
182 instance Spaceable Text where
185 spaces n = Text.replicate (fromIntegral n) " "
186 instance Spaceable TL.Text where
189 spaces n = TL.replicate (fromIntegral n) " "
190 instance Spaceable TLB.Builder where
191 newline = TLB.singleton '\n'
192 space = TLB.singleton ' '
193 spaces = TLB.fromText . spaces
197 Foldable f => Emptyable repr =>
198 ProductFunctor repr =>
199 repr () -> f (repr ()) -> repr ()
201 | Fold.null rs = empty
202 | otherwise = Fold.foldr1 (\x y -> x.>sep.>y) rs
205 Emptyable repr => ProductFunctor repr =>
206 Int -> repr () -> repr ()
209 | otherwise = t .> replicate (pred cnt) t
212 ProductFunctor repr =>
213 repr () -> repr () -> repr a -> repr a
214 between o c x = o.>x<.c
215 parens, braces, brackets, angles ::
216 ProductFunctor repr =>
218 Inferable Char repr =>
220 parens = between (void '(' infer) (void ')' infer)
221 braces = between (void '{' infer) (void '}' infer)
222 brackets = between (void '[' infer) (void ']' infer)
223 angles = between (void '<' infer) (void '>' infer)
225 -- * Class 'Decorable'
226 class Decorable repr where
227 bold :: repr a -> repr a
228 underline :: repr a -> repr a
229 italic :: repr a -> repr a
230 default bold :: FromDerived1 Decorable repr => repr a -> repr a
231 default underline :: FromDerived1 Decorable repr => repr a -> repr a
232 default italic :: FromDerived1 Decorable repr => repr a -> repr a
233 bold = liftDerived1 bold
234 underline = liftDerived1 underline
235 italic = liftDerived1 italic
237 -- * Class 'Colorable16'
238 class Colorable16 repr where
239 reverse :: repr a -> repr a
243 black :: repr a -> repr a
244 red :: repr a -> repr a
245 green :: repr a -> repr a
246 yellow :: repr a -> repr a
247 blue :: repr a -> repr a
248 magenta :: repr a -> repr a
249 cyan :: repr a -> repr a
250 white :: repr a -> repr a
253 blacker :: repr a -> repr a
254 redder :: repr a -> repr a
255 greener :: repr a -> repr a
256 yellower :: repr a -> repr a
257 bluer :: repr a -> repr a
258 magentaer :: repr a -> repr a
259 cyaner :: repr a -> repr a
260 whiter :: repr a -> repr a
264 onBlack :: repr a -> repr a
265 onRed :: repr a -> repr a
266 onGreen :: repr a -> repr a
267 onYellow :: repr a -> repr a
268 onBlue :: repr a -> repr a
269 onMagenta :: repr a -> repr a
270 onCyan :: repr a -> repr a
271 onWhite :: repr a -> repr a
274 onBlacker :: repr a -> repr a
275 onRedder :: repr a -> repr a
276 onGreener :: repr a -> repr a
277 onYellower :: repr a -> repr a
278 onBluer :: repr a -> repr a
279 onMagentaer :: repr a -> repr a
280 onCyaner :: repr a -> repr a
281 onWhiter :: repr a -> repr a
283 default reverse :: FromDerived1 Colorable16 repr => repr a -> repr a
284 default black :: FromDerived1 Colorable16 repr => repr a -> repr a
285 default red :: FromDerived1 Colorable16 repr => repr a -> repr a
286 default green :: FromDerived1 Colorable16 repr => repr a -> repr a
287 default yellow :: FromDerived1 Colorable16 repr => repr a -> repr a
288 default blue :: FromDerived1 Colorable16 repr => repr a -> repr a
289 default magenta :: FromDerived1 Colorable16 repr => repr a -> repr a
290 default cyan :: FromDerived1 Colorable16 repr => repr a -> repr a
291 default white :: FromDerived1 Colorable16 repr => repr a -> repr a
292 default blacker :: FromDerived1 Colorable16 repr => repr a -> repr a
293 default redder :: FromDerived1 Colorable16 repr => repr a -> repr a
294 default greener :: FromDerived1 Colorable16 repr => repr a -> repr a
295 default yellower :: FromDerived1 Colorable16 repr => repr a -> repr a
296 default bluer :: FromDerived1 Colorable16 repr => repr a -> repr a
297 default magentaer :: FromDerived1 Colorable16 repr => repr a -> repr a
298 default cyaner :: FromDerived1 Colorable16 repr => repr a -> repr a
299 default whiter :: FromDerived1 Colorable16 repr => repr a -> repr a
300 default onBlack :: FromDerived1 Colorable16 repr => repr a -> repr a
301 default onRed :: FromDerived1 Colorable16 repr => repr a -> repr a
302 default onGreen :: FromDerived1 Colorable16 repr => repr a -> repr a
303 default onYellow :: FromDerived1 Colorable16 repr => repr a -> repr a
304 default onBlue :: FromDerived1 Colorable16 repr => repr a -> repr a
305 default onMagenta :: FromDerived1 Colorable16 repr => repr a -> repr a
306 default onCyan :: FromDerived1 Colorable16 repr => repr a -> repr a
307 default onWhite :: FromDerived1 Colorable16 repr => repr a -> repr a
308 default onBlacker :: FromDerived1 Colorable16 repr => repr a -> repr a
309 default onRedder :: FromDerived1 Colorable16 repr => repr a -> repr a
310 default onGreener :: FromDerived1 Colorable16 repr => repr a -> repr a
311 default onYellower :: FromDerived1 Colorable16 repr => repr a -> repr a
312 default onBluer :: FromDerived1 Colorable16 repr => repr a -> repr a
313 default onMagentaer :: FromDerived1 Colorable16 repr => repr a -> repr a
314 default onCyaner :: FromDerived1 Colorable16 repr => repr a -> repr a
315 default onWhiter :: FromDerived1 Colorable16 repr => repr a -> repr a
317 reverse = liftDerived1 reverse
318 black = liftDerived1 black
319 red = liftDerived1 red
320 green = liftDerived1 green
321 yellow = liftDerived1 yellow
322 blue = liftDerived1 blue
323 magenta = liftDerived1 magenta
324 cyan = liftDerived1 cyan
325 white = liftDerived1 white
326 blacker = liftDerived1 blacker
327 redder = liftDerived1 redder
328 greener = liftDerived1 greener
329 yellower = liftDerived1 yellower
330 bluer = liftDerived1 bluer
331 magentaer = liftDerived1 magentaer
332 cyaner = liftDerived1 cyaner
333 whiter = liftDerived1 whiter
334 onBlack = liftDerived1 onBlack
335 onRed = liftDerived1 onRed
336 onGreen = liftDerived1 onGreen
337 onYellow = liftDerived1 onYellow
338 onBlue = liftDerived1 onBlue
339 onMagenta = liftDerived1 onMagenta
340 onCyan = liftDerived1 onCyan
341 onWhite = liftDerived1 onWhite
342 onBlacker = liftDerived1 onBlacker
343 onRedder = liftDerived1 onRedder
344 onGreener = liftDerived1 onGreener
345 onYellower = liftDerived1 onYellower
346 onBluer = liftDerived1 onBluer
347 onMagentaer = liftDerived1 onMagentaer
348 onCyaner = liftDerived1 onCyaner
349 onWhiter = liftDerived1 onWhiter
351 -- * Class 'Indentable'
352 class Spaceable repr => Indentable repr where
353 -- | @('align' doc)@ make @doc@ uses current 'Column' as 'Indent' level.
354 align :: repr a -> repr a
355 -- | @('setIndent' p ind doc)@ make @doc@ uses @ind@ as 'Indent' level.
356 -- Using @p@ as 'Indent' text.
357 setIndent :: repr () -> Indent -> repr a -> repr a
358 -- | @('incrIndent' p ind doc)@ make @doc@ uses current 'Indent' plus @ind@ as 'Indent' level.
359 -- Appending @p@ to the current 'Indent' text.
360 incrIndent :: repr () -> Indent -> repr a -> repr a
361 hang :: Indent -> repr a -> repr a
362 hang ind = align . incrIndent (spaces ind) ind
363 -- | @('fill' w doc)@ write @doc@,
364 -- then if @doc@ is not wider than @w@,
365 -- write the difference with 'spaces'.
366 fill :: Width -> repr a -> repr a
367 -- | @('fillOrBreak' w doc)@ write @doc@,
368 -- then if @doc@ is not wider than @w@, write the difference with 'spaces'
369 -- otherwise write a 'newline' indented to to the start 'Column' of @doc@ plus @w@.
370 fillOrBreak :: Width -> repr a -> repr a
372 default align :: FromDerived1 Indentable repr => repr a -> repr a
373 default incrIndent :: FromDerived2 Indentable repr => repr () -> Indent -> repr a -> repr a
374 default setIndent :: FromDerived2 Indentable repr => repr () -> Indent -> repr a -> repr a
375 default fill :: FromDerived1 Indentable repr => Width -> repr a -> repr a
376 default fillOrBreak :: FromDerived1 Indentable repr => Width -> repr a -> repr a
378 align = liftDerived1 align
379 setIndent p i = liftDerived2 (`setIndent`i) p
380 incrIndent p i = liftDerived2 (`incrIndent`i) p
381 fill = liftDerived1 . fill
382 fillOrBreak = liftDerived1 . fillOrBreak
384 -- * Class 'Listable'
385 class Listable repr where
386 ul :: Traversable f => f (repr ()) -> repr ()
387 ol :: Traversable f => f (repr ()) -> repr ()
389 FromDerived Listable repr => Derivable repr =>
390 Traversable f => f (repr ()) -> repr ()
392 FromDerived Listable repr => Derivable repr =>
393 Traversable f => f (repr ()) -> repr ()
394 ul xs = liftDerived $ ul $ derive Fct.<$> xs
395 ol xs = liftDerived $ ol $ derive Fct.<$> xs
396 unorderedList :: repr a -> repr [a]
397 orderedList :: repr a -> repr [a]
398 list_ :: repr () -> repr () -> repr () -> repr a -> repr [a]
399 default unorderedList :: FromDerived1 Listable repr => repr a -> repr [a]
400 default orderedList :: FromDerived1 Listable repr => repr a -> repr [a]
401 default list_ :: FromDerived4 Listable repr => repr () -> repr () -> repr () -> repr a -> repr [a]
402 unorderedList = liftDerived1 unorderedList
403 orderedList = liftDerived1 orderedList
404 list_ = liftDerived4 list_
405 intercalate_ :: repr () -> repr a -> repr [a]
406 default intercalate_ ::
407 FromDerived2 Listable repr =>
408 repr () -> repr a -> repr [a]
409 intercalate_ = liftDerived2 intercalate_
411 Voidable repr => Inferable Char repr =>
413 braceList = list_ (void '{' infer) (void ',' infer) (void '}' infer)
415 Voidable repr => Inferable Char repr =>
417 bracketList = list_ (void '[' infer) (void ',' infer) (void ']' infer)
419 Voidable repr => Inferable Char repr =>
421 parenList = list_ (void '(' infer) (void ',' infer) (void ')' infer)
423 Voidable repr => Inferable Char repr =>
425 angleList = list_ (void '<' infer) (void ',' infer) (void '>' infer)
427 -- * Class 'Wrappable'
428 class Wrappable repr where
429 setWidth :: Maybe Width -> repr a -> repr a
430 -- getWidth :: (Maybe Width -> repr a) -> repr a
431 breakpoint :: repr ()
432 breakspace :: repr ()
433 breakalt :: repr a -> repr a -> repr a
435 default breakpoint :: FromDerived Wrappable repr => repr ()
436 default breakspace :: FromDerived Wrappable repr => repr ()
437 default breakalt :: FromDerived2 Wrappable repr => repr a -> repr a -> repr a
438 default endline :: FromDerived Wrappable repr => repr ()
439 breakpoint = liftDerived breakpoint
440 breakspace = liftDerived breakspace
441 breakalt = liftDerived2 breakalt
442 endline = liftDerived endline
444 ProductFunctor repr =>
448 f (repr ()) -> repr ()
449 unwords_ :: Listable repr => repr a -> repr [a]
450 unwords = intercalate breakspace
451 unwords_ = intercalate_ breakspace
453 -- * Class 'Justifiable'
454 class Justifiable repr where
455 justify :: repr a -> repr a
457 -- * Class 'Inferable'
458 class Inferable a repr where
460 default infer :: FromDerived (Inferable a) repr => repr a
461 infer = liftDerived infer
462 string :: Inferable String repr => repr String
464 int :: Inferable Int repr => repr Int
466 natural :: Inferable Natural repr => repr Natural