table-layout-1.0.0.0: src/Text/Layout/Table/Spec/HeaderSpec.hs
{-# LANGUAGE DeriveTraversable #-}
module Text.Layout.Table.Spec.HeaderSpec where
import Data.Bifunctor
import Data.Default.Class
import Data.List
import Text.Layout.Table.Spec.HeaderColSpec
-- | Specifies a header.
data HeaderSpec sep a
-- | A grouping of subheaders separated by delimiters with the given label
= GroupHS sep [HeaderSpec sep a]
-- | A single header column with a given 'HeaderColSpec' and content.
| HeaderHS HeaderColSpec a
-- | Do not display the header, and determine the shape as a flat list
-- sized to the table content with a given separator.
| NoneHS sep
deriving (Functor, Foldable, Traversable)
instance Bifunctor HeaderSpec where
bimap f g (GroupHS sep hs) = GroupHS (f sep) (map (bimap f g) hs)
bimap _ g (HeaderHS spec title) = HeaderHS spec (g title)
bimap f _ (NoneHS sep) = NoneHS (f sep)
-- | By the default the header is not shown.
instance Default sep => Default (HeaderSpec sep a) where
def = defHeaderSpec
-- | The default 'HeaderSpec' does not display the header and uses the default
-- separator.
defHeaderSpec :: Default sep => HeaderSpec sep a
defHeaderSpec = NoneHS def
-- | Specify no header, with columns separated by a given separator.
noneSepH :: sep -> HeaderSpec sep String
noneSepH = NoneHS
-- | Specify no header, with columns separated by a default separator.
noneH :: Default sep => HeaderSpec sep String
noneH = noneSepH def
-- | Specify every header column in detail and separate them by the given
-- separator.
fullSepH :: sep -> [HeaderColSpec] -> [a] -> HeaderSpec sep a
fullSepH sep specs = GroupHS sep . zipWith HeaderHS specs
-- | Specify every header column in detail and separate them with the default
-- separator.
fullH :: Default sep => [HeaderColSpec] -> [a] -> HeaderSpec sep a
fullH = fullSepH def
-- | Use titles with the default header column specification and separator.
titlesH :: Default sep => [a] -> HeaderSpec sep a
titlesH = fullH (repeat defHeaderColSpec)
-- | Combine the header specification for multiple columns by separating the
-- columns with a specific separator.
groupH :: sep -> [HeaderSpec sep a] -> HeaderSpec sep a
groupH = GroupHS
-- | Specify the header for a single column.
headerH :: HeaderColSpec -> a -> HeaderSpec sep a
headerH = HeaderHS
-- | Zip a 'HeaderSpec' with a list.
zipHeader :: b -> [b] -> HeaderSpec sep a -> HeaderSpec sep (b, a)
zipHeader e bs = snd . mapAccumL helper bs
where
helper (s : ss) title = (ss, (s, title))
helper [] title = ([], (e, title))
-- | Flatten a header to produce a list of content and separators.
flattenHeader :: HeaderSpec sep a -> [Either sep a]
flattenHeader (GroupHS sep hs) = intercalate [Left sep] $ map flattenHeader hs
flattenHeader (HeaderHS _ title) = [Right title]
flattenHeader (NoneHS _) = []
-- | Get the titles and column specifications from a header.
headerContents :: HeaderSpec sep a -> [(HeaderColSpec, a)]
headerContents (GroupHS _ hs) = concatMap headerContents hs
headerContents (HeaderHS spec title) = [(spec, title)]
headerContents (NoneHS _) = []