futhark-0.22.2: src/Futhark/Util/Table.hs
-- | Basic table building for prettier futhark-test output.
module Futhark.Util.Table
( hPutTable,
mkEntry,
Entry,
AnsiStyle,
Color (..),
color,
)
where
import Data.List (intersperse, transpose)
import Futhark.Util (maxinum)
import Futhark.Util.Pretty hiding (sep, width)
import System.IO (Handle)
data RowTemplate = RowTemplate [Int] Int deriving (Show)
-- | A table entry. Consists of the content as well as how it should
-- be styled..
data Entry = Entry {entryText :: String, _entryStyle :: AnsiStyle}
-- | Makes a table entry.
mkEntry :: String -> AnsiStyle -> Entry
mkEntry = Entry
buildRowTemplate :: [[Entry]] -> Int -> RowTemplate
buildRowTemplate rows = RowTemplate widths
where
widths = map (maxinum . map (length . entryText)) . transpose $ rows
buildRow :: RowTemplate -> [Entry] -> Doc AnsiStyle
buildRow (RowTemplate widths pad) entries = cells <> hardline
where
bar = "\x2502"
cells = mconcat (zipWith buildCell entries widths) <> bar
buildCell (Entry entry sgr) width =
let padding = width - length entry + pad
in bar <> " " <> annotate sgr (pretty entry) <> mconcat (replicate padding " ")
buildSep :: Char -> Char -> Char -> RowTemplate -> Doc AnsiStyle
buildSep lCorner rCorner sep (RowTemplate widths pad) =
corners . concatMap cellFloor $ widths
where
cellFloor width = replicate (width + pad + 1) '\x2500' <> [sep]
corners [] = ""
corners s = pretty lCorner <> pretty (init s) <> pretty rCorner
-- | Produce a table from a list of entries and a padding amount that
-- determines padding from the right side of the widest entry in each column.
hPutTable :: Handle -> [[Entry]] -> Int -> IO ()
hPutTable h rows pad = hPutDoc h $ buildTop template <> sepRows <> buildBottom template <> hardline
where
sepRows = mconcat $ intersperse (buildFloor template) builtRows
builtRows = map (buildRow template) rows
template = buildRowTemplate rows pad
buildTop rt = buildSep '\x250C' '\x2510' '\x252C' rt <> hardline
buildFloor rt = buildSep '\x251C' '\x2524' '\x253C' rt <> hardline
buildBottom = buildSep '\x2514' '\x2518' '\x2534'