1 {-# LANGUAGE FlexibleInstances #-}
2 {-# LANGUAGE MultiParamTypeClasses #-}
3 {-# LANGUAGE NamedFieldPuns #-}
4 module Hcompta.CLI.Lib.Leijen.Table where
7 import Data.Char (Char)
8 import Data.Foldable (Foldable(..))
9 import Data.Foldable (any)
10 import qualified Data.List
11 import Data.List (map, replicate)
12 import Data.Maybe (Maybe(..))
13 import Data.Maybe (fromMaybe)
14 import Data.Ord (Ord(..))
15 import Data.Text (Text)
16 import qualified Data.Text as Text
17 import qualified Data.Text.Lazy as TL
18 import Prelude (($), (.), Int, Integral(..), Num(..), fromIntegral, id, zipWith)
20 import qualified Hcompta.Lib.Leijen as W
21 import Hcompta.Lib.Leijen ((<>), toDoc, ToDoc(..))
27 -- * The 'Column' type
31 { column_title :: Text
33 , column_align :: Align
34 , column_rows :: [Cell]
36 instance ToDoc () [Column] where
38 let rows = Data.List.transpose $ map column_rows cols
39 let has_title = any (not . Text.null . column_title) cols
41 W.intercalate (W.bold $ W.dullblack $ W.char '|')
42 (\col@Column{column_title} -> do
43 let cell_width = Text.length column_title
44 let under = W.bold $ W.dullblack $ W.char '_'
45 let cell_content = W.enclose under under $
47 (\c -> case c of { ' ' -> under; _ -> W.char c })
48 (Text.unpack column_title)
49 let pad len = W.bold $ W.dullblack $
50 W.text $ TL.pack $ replicate len '_'
52 Cell{cell_width, cell_content, cell_align=Just Align_Center}
55 (if has_title then (:) titles else id) $
57 ( W.intercalate (W.space <> do W.bold $ W.dullblack $ W.char '|') id
62 (if null cols then W.empty else W.line)
63 column :: Text -> Align -> [Cell] -> Column
64 column column_title column_align column_rows =
67 , column_width = max (Text.length column_title) $
68 foldr (max . cell_width) 0 column_rows
73 -- ** The 'Align' type
79 align :: Maybe (Int -> W.Doc) -> Column -> Cell -> W.Doc
81 Column{column_width, column_align}
82 Cell{cell_width, cell_content, cell_align} =
83 let pad = column_width - cell_width in
84 let fill = fromMaybe (`W.fill` W.empty) filling in
85 case fromMaybe column_align cell_align of
86 Align_Left -> cell_content <> fill pad
88 let half = fromInteger $ quot (toInteger pad) 2 in
89 fill half <> cell_content <> fill (pad - half)
90 Align_Right -> fill pad <> cell_content
93 (Cell_Line {cell_pad}) =
94 W.bold $ W.dullblack $ W.text $
95 TL.replicate (fromIntegral column_width) $
102 { cell_align :: Maybe Align
104 , cell_content :: W.Doc
114 , cell_content = W.empty
115 , cell_align = Nothing
117 instance ToDoc Column Cell where
118 toDoc = align Nothing