module Text.Layout.DisplayText ( DisplayText(..)
, dt
) where
import Control.Arrow
import Data.Convertible
import Data.List
import Data.List.HIUtils
import Data.Maybe
import Data.Monoid
import Data.Ord
import Data.Ratio
import Data.String.HIUtils
import Text.Layout.Objects
import Text.Layout.Class
newtype DisplayText = DisplayText { fromDisplayText :: String }
instance Show DisplayText where
show = fromDisplayText
instance Monoid DisplayText where
mempty = DisplayText ""
a `mappend` b = DisplayText $
(fromDisplayText a) `mappend` (fromDisplayText b)
mconcat = DisplayText . mconcat . map fromDisplayText
instance IsFormat DisplayText where
formatVerbatim = DisplayText
instance Layout DisplayText DisplayText where
format = id
instance Layout Char DisplayText where
format = fromShow
formatList = fromShow
instance (Layout a DisplayText) => Layout [a] DisplayText where
format = formatList
instance (Layout a DisplayText) => Convertible a DisplayText where
safeConvert = Right . format
instance Layout () DisplayText where format = fromShow
instance Layout Integer DisplayText where format = fromShow
instance Layout Int DisplayText where format = fromShow
instance Layout Float DisplayText where format = fromShow
instance Layout Double DisplayText where format = fromShow
instance (Show (Ratio a)) => Layout (Ratio a) DisplayText where format = fromShow
instance (Show a) => Layout (Maybe a) DisplayText where format = fromShow
instance (Show a, Show b) => Layout (Either a b) DisplayText where format = fromShow
instance (Show a, Show b) => Layout (a, b) DisplayText where format = fromShow
instance (Show a, Show b, Show c) => Layout (a, b, c) DisplayText where format = fromShow
instance (Show a, Show b, Show c, Show d) => Layout (a, b, c, d) DisplayText where format = fromShow
instance (Show a, Show b, Show c, Show d, Show e) => Layout (a, b, c, d, e) DisplayText where format = fromShow
instance (Show a, Show b, Show c, Show d, Show e, Show f) => Layout (a, b, c, d, e, f) DisplayText where format = fromShow
instance (Show a, Show b, Show c, Show d, Show e, Show f, Show g) => Layout (a, b, c, d, e, f, g) DisplayText where format = fromShow
instance (Show a, Show b, Show c, Show d, Show e, Show f, Show g, Show h) => Layout (a, b, c, d, e, f, g, h) DisplayText where format = fromShow
instance (Show a, Show b, Show c, Show d, Show e, Show f, Show g, Show h, Show i) => Layout (a, b, c, d, e, f, g, h, i) DisplayText where format = fromShow
dt :: (Layout a DisplayText) => a -> DisplayText
dt = format
instance (Layout a DisplayText,
Layout b DisplayText,
Layout c DisplayText) =>
Layout (Table a b c) DisplayText where
format (Table caption (x, y) sparseRepr) = formatVerbatim s
where s = asciiTable caption (x, y) sparseRepr
asciiTable ::
( Layout a DisplayText
, Layout b DisplayText
, Layout c DisplayText ) =>
String -> (String, String) -> [((a,b), c)] -> String
asciiTable title (astr, bstr) table' = "Table: " ++ title ++ "\n"
++ thead ++ "\n" ++ tbody
where
table = map ((renderdt *** renderdt) *** renderdt) table'
renderdt :: (Convertible t DisplayText) => t -> String
renderdt = fromDisplayText . convert
colAL = sortBy (comparing fst) $ aggregateAL $ map (first fst) table
rowsAL = sortBy (comparing fst) $ aggregateAL $ map (\((a,b), c) -> (b, (a, c))) table
rows = map fst rowsAL
cols = map fst colAL
rowhdr = bstr ++ "\\/"
rhlen = maximum $ map length (rowhdr : rows)
renderrow (rn, rv) = padl rhlen rn ++ " " ++
(concat . intersperse " " . map
(renderval rv)) collengths
renderval rv (c,l) = padl l $ fromMaybe "" $ lookup c rv
padval (col,v) = maybe "" (flip padl v) $ lookup col collengths
collengths = [ (colname, maximum $ map length xs) |
(colname, colvals) <- colAL, let xs = (colname:colvals) ]
thead = thead1 ++ "\n" ++ thead2
thead1 = padl rhlen "||" ++ " " ++ astr ++ " ==>"
thead2 = padl rhlen rowhdr ++ " " ++ concat (intersperse " " (map (uncurry (flip padl)) collengths))
tbody = concat . intersperse "\n" . map renderrow $ rowsAL