module Pretty where -- see: http://stackoverflow.com/questions/5929377/format-list-output-in-haskell import Data.List ( transpose, intercalate ) -- a type for fill functions type Filler = Int -> String -> String -- a type for describing table columns data ColDesc t = ColDesc { colTitleFill :: Filler , colTitle :: String , colValueFill :: Filler , colValue :: t -> String } -- functions that fill a string (s) to a given width (n) by adding pad -- character (c) to align left, right, or center fillLeft, fillRight, fillCenter :: a -> Int -> [a] -> [a] fillLeft c n s = s ++ replicate (n - length s) c fillRight c n s = replicate (n - length s) c ++ s fillCenter c n s = replicate l c ++ s ++ replicate r c where x = n - length s l = x `div` 2 r = x - l -- functions that fill with spaces left, right, center :: Int -> String -> String left = fillLeft ' ' right = fillRight ' ' center = fillCenter ' ' -- converts a list of items into a table according to a list -- of column descriptors ppTable :: [ColDesc t] -> [t] -> String ppTable cs ts = let header = map colTitle cs rows = [[colValue c t | c <- cs] | t <- ts] widths = [maximum $ map length col | col <- transpose $ header : rows] separator = intercalate "-+-" [replicate width '-' | width <- widths] fillCols fill cols = intercalate " | " [fill c width col | (c, width, col) <- zip3 cs widths cols] in unlines $ fillCols colTitleFill header : separator : map (fillCols colValueFill) rows renderTable :: [ColDesc t] -> [t] -> IO () renderTable cs = putStrLn . ppTable cs