{-# LANGUAGE RecordWildCards #-}
module Text.Layout.Table
(
module Data.Default.Class
, ColSpec
, column
, numCol
, fixedCol
, fixedLeftCol
, LenSpec
, expand
, fixed
, expandUntil
, fixedUntil
, Position
, H
, left
, right
, center
, AlignSpec
, noAlign
, charAlign
, predAlign
, dotAlign
, CutMark
, noCutMark
, singleCutMark
, doubleCutMark
, Row
, grid
, gridLines
, gridString
, concatRow
, concatLines
, concatGrid
, altLines
, checkeredCells
, RowGroup
, rowsG
, rowG
, colsG
, colsAllG
, HeaderColSpec
, headerColumn
, HeaderSpec
, fullH
, titlesH
, tableLines
, tableString
, justify
, justifyText
, Col
, colsAsRowsAll
, colsAsRows
, top
, bottom
, V
, module Text.Layout.Table.Style
, pad
, trimOrPad
, align
, alignFixed
, ColModInfo
, widthCMI
, unalignedCMI
, ensureWidthCMI
, ensureWidthOfCMI
, columnModifier
, AlignInfo
, widthAI
, deriveColModInfos
, deriveAlignInfo
, OccSpec
) where
import Data.List
import Data.Default.Class
import Data.Default.Instances.Base ()
import Text.Layout.Table.Cell
import Text.Layout.Table.Justify
import Text.Layout.Table.Primitives.AlignInfo
import Text.Layout.Table.Primitives.Basic
import Text.Layout.Table.Primitives.ColumnModifier
import Text.Layout.Table.Primitives.Header
import Text.Layout.Table.Primitives.Table
import Text.Layout.Table.Spec.AlignSpec
import Text.Layout.Table.Spec.ColSpec
import Text.Layout.Table.Spec.CutMark
import Text.Layout.Table.Spec.HeaderColSpec
import Text.Layout.Table.Spec.HeaderSpec
import Text.Layout.Table.Spec.LenSpec
import Text.Layout.Table.Spec.OccSpec
import Text.Layout.Table.Spec.Position
import Text.Layout.Table.Spec.RowGroup
import Text.Layout.Table.Spec.Util
import Text.Layout.Table.StringBuilder
import Text.Layout.Table.Style
import Text.Layout.Table.Vertical
dotAlign :: AlignSpec
dotAlign = charAlign '.'
numCol :: ColSpec
numCol = column def right dotAlign def
fixedCol :: Int -> Position H -> ColSpec
fixedCol l pS = column (fixed l) pS def def
fixedLeftCol :: Int -> ColSpec
fixedLeftCol i = fixedCol i left
grid :: Cell a => [ColSpec] -> [Row a] -> [Row String]
grid specs tab = zipWith ($) (deriveColMods specs tab) <$> tab
gridLines :: Cell a => [ColSpec] -> [Row a] -> [String]
gridLines specs = fmap unwords . grid specs
gridString :: Cell a => [ColSpec] -> [Row a] -> String
gridString specs = concatLines . gridLines specs
concatLines :: StringBuilder b => [b] -> b
concatLines = mconcat . intersperse (charB '\n')
concatRow
:: StringBuilder b
=> Int
-> Row b
-> b
concatRow n bs = mconcat $ intersperse (replicateCharB n ' ') bs
concatGrid :: StringBuilder b => Int -> [Row b] -> b
concatGrid n = concatLines . fmap (concatRow n)
altLines :: [a -> b] -> [a] -> [b]
altLines = zipWith ($) . cycle
checkeredCells :: (a -> b) -> (a -> b) -> [[a]] -> [[b]]
checkeredCells f g = zipWith altLines $ cycle [[f, g], [g, f]]
colsG :: Monoid a => [Position V] -> [Col a] -> RowGroup a
colsG ps = rowsG . colsAsRows ps
colsAllG :: Monoid a => Position V -> [Col a] -> RowGroup a
colsAllG p = rowsG . colsAsRowsAll p
tableLines :: Cell a
=> [ColSpec]
-> TableStyle
-> HeaderSpec
-> [RowGroup a]
-> [String]
tableLines specs TableStyle { .. } header rowGroups =
topLine : addHeaderLines (rowGroupLines ++ [bottomLine])
where
fakeColumns sym
= map (`replicateCharB` sym) colWidths
topLine = hLineDetail realTopH realTopL realTopC realTopR $ fakeColumns realTopH
bottomLine = hLineDetail groupBottomH groupBottomL groupBottomC groupBottomR $ fakeColumns groupBottomH
groupSepLine = hLineDetail groupSepH groupSepLC groupSepC groupSepRC $ fakeColumns groupSepH
headerSepLine = hLineDetail headerSepH headerSepLC headerSepC headerSepRC $ fakeColumns headerSepH
rowGroupLines =
intercalate [groupSepLine] $ map (map (hLineContent groupV) . applyRowMods . rows) rowGroups
(addHeaderLines, fitHeaderIntoCMIs, realTopH, realTopL, realTopC, realTopR)
= case header of
HeaderHS headerColSpecs hTitles
->
let headerLine = hLineContent headerV (zipWith ($) headerRowMods hTitles)
headerRowMods = zipWith3 headerCellModifier
headerColSpecs
cMSs
cMIs
in
( (headerLine :) . (headerSepLine :)
, fitTitlesCMI hTitles posSpecs
, headerTopH
, headerTopL
, headerTopC
, headerTopR
)
NoneHS ->
( id
, id
, groupTopH
, groupTopL
, groupTopC
, groupTopR
)
cMSs = map cutMark specs
posSpecs = map position specs
applyRowMods = map (zipWith ($) rowMods)
rowMods = zipWith3 columnModifier posSpecs cMSs cMIs
cMIs = fitHeaderIntoCMIs $ deriveColModInfos' specs $ concatMap rows rowGroups
colWidths = map widthCMI cMIs
tableString :: Cell a
=> [ColSpec]
-> TableStyle
-> HeaderSpec
-> [RowGroup a]
-> String
tableString specs style header rowGroups = concatLines $ tableLines specs style header rowGroups