-- Simple and efficient printing combinators
{-
instance Printable a => Printable (Maybe a) where
pr Nothing = nil
pr (Just x) = pr x
-}
pprint x = fmt0 0 (apply (pr x) [])
where
apply (P pr) = pr
-- The printer is designed to avoid producing redundant spaces:
-- + No indentation space on blank lines.
-- + No trailing spaces at the end of lines.
-- + No double spaces between items.
-- fmt0: at the beginning of a line, before indentation has been made
fmt0 n [] = []
fmt0 n (Nl:os) = "\n"++fmt0 n os
fmt0 n (Indent i:os) = fmt0 (n+i) os
fmt0 n (Sep:os) = fmt0 n os
fmt0 n (Str s:os) = space n++s++fmt n os
space n = replicate (n `div` 8) '\t' ++ replicate (n `mod` 8) ' '
-- fmt: in the middle of a line, after indentation and some text
fmt n [] = []
fmt n (o:os) =
case o of
Str s -> s++fmt n os
Nl -> "\n"++fmt0 n os
Indent i -> fmt (n+i) os
Sep -> fmt1 n os
-- fmt1: in the middle of a line, a space is to be inserted before next item
fmt1 n [] = []
fmt1 n (o:os) =
case o of
Str s -> ' ':s++fmt n os
Nl -> "\n"++fmt0 n os
Indent i -> fmt1 (n+i) os
Sep -> fmt1 n os