module Text.Tabular.AsciiWide where
import Data.List (intersperse, transpose)
import Text.Tabular
import Hledger.Utils.String
render :: Bool
-> (rh -> String)
-> (ch -> String)
-> (a -> String)
-> Table rh ch a
-> String
render pretty fr fc f (Table rh ch cells) =
unlines $ [ bar SingleLine
, renderColumns pretty sizes ch2
, bar DoubleLine
] ++
(renderRs $ fmap renderR $ zipHeader [] cells $ fmap fr rh) ++
[ bar SingleLine ]
where
bar = concat . renderHLine pretty sizes ch2
ch2 = Group DoubleLine [Header "", fmap fc ch]
cells2 = headerContents ch2
: zipWith (\h cs -> h : map f cs) rhStrings cells
renderR (cs,h) = renderColumns pretty sizes $ Group DoubleLine
[ Header h
, fmap fst $ zipHeader "" (map f cs) ch]
rhStrings = map fr $ headerContents rh
sizes = map (maximum . map strWidth) . transpose $ cells2
renderRs (Header s) = [s]
renderRs (Group p hs) = concat . intersperse sep . map renderRs $ hs
where sep = renderHLine pretty sizes ch2 p
verticalBar :: Bool -> Char
verticalBar pretty = if pretty then '│' else '|'
leftBar :: Bool -> String
leftBar pretty = verticalBar pretty : " "
rightBar :: Bool -> String
rightBar pretty = " " ++ [verticalBar pretty]
midBar :: Bool -> String
midBar pretty = " " ++ verticalBar pretty : " "
doubleMidBar :: Bool -> String
doubleMidBar pretty = if pretty then " ║ " else " || "
horizontalBar :: Bool -> Char
horizontalBar pretty = if pretty then '─' else '-'
doubleHorizontalBar :: Bool -> Char
doubleHorizontalBar pretty = if pretty then '═' else '='
renderColumns :: Bool
-> [Int]
-> Header String
-> String
renderColumns pretty is h = leftBar pretty ++ coreLine ++ rightBar pretty
where
coreLine = concatMap helper $ flattenHeader $ zipHeader 0 is h
helper = either hsep (uncurry padLeftWide)
hsep :: Properties -> String
hsep NoLine = " "
hsep SingleLine = midBar pretty
hsep DoubleLine = doubleMidBar pretty
renderHLine :: Bool
-> [Int]
-> Header String
-> Properties
-> [String]
renderHLine _ _ _ NoLine = []
renderHLine pretty w h SingleLine = [renderHLine' pretty SingleLine w (horizontalBar pretty) h]
renderHLine pretty w h DoubleLine = [renderHLine' pretty DoubleLine w (doubleHorizontalBar pretty) h]
doubleCross :: Bool -> String
doubleCross pretty = if pretty then "╬" else "++"
doubleVerticalCross :: Bool -> String
doubleVerticalCross pretty = if pretty then "╫" else "++"
cross :: Bool -> Char
cross pretty = if pretty then '┼' else '+'
renderHLine' :: Bool -> Properties -> [Int] -> Char -> Header String -> String
renderHLine' pretty prop is sep h = [ cross pretty, sep ] ++ coreLine ++ [sep, cross pretty]
where
coreLine = concatMap helper $ flattenHeader $ zipHeader 0 is h
helper = either vsep dashes
dashes (i,_) = replicate i sep
vsep NoLine = replicate 2 sep
vsep SingleLine = sep : cross pretty : [sep]
vsep DoubleLine = sep : cross' ++ [sep]
cross' = case prop of
DoubleLine -> doubleCross pretty
_ -> doubleVerticalCross pretty