module Text.Layout.Table.Primitives.ColumnModifier where
import Control.Arrow ((&&&))
import Data.List
import Text.Layout.Table.Cell
import Text.Layout.Table.Primitives.AlignInfo
import Text.Layout.Table.Spec.AlignSpec
import Text.Layout.Table.Spec.ColSpec
import Text.Layout.Table.Spec.CutMark
import Text.Layout.Table.Spec.LenSpec
import Text.Layout.Table.Spec.OccSpec
import Text.Layout.Table.Spec.Position
import Text.Layout.Table.Spec.Util
import Text.Layout.Table.StringBuilder
data ColModInfo
= FillAligned OccSpec AlignInfo
| FillTo Int
| FitTo Int (Maybe (OccSpec, AlignInfo))
showCMI :: ColModInfo -> String
showCMI :: ColModInfo -> String
showCMI ColModInfo
cmi = case ColModInfo
cmi of
FillAligned OccSpec
_ AlignInfo
ai -> String
"FillAligned .. " String -> String -> String
forall a. [a] -> [a] -> [a]
++ AlignInfo -> String
showAI AlignInfo
ai
FillTo Int
i -> String
"FillTo " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
i
FitTo Int
i Maybe (OccSpec, AlignInfo)
_ -> String
"FitTo " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
i String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
".."
widthCMI :: ColModInfo -> Int
widthCMI :: ColModInfo -> Int
widthCMI ColModInfo
cmi = case ColModInfo
cmi of
FillAligned OccSpec
_ AlignInfo
ai -> AlignInfo -> Int
widthAI AlignInfo
ai
FillTo Int
maxLen -> Int
maxLen
FitTo Int
lim Maybe (OccSpec, AlignInfo)
_ -> Int
lim
unalignedCMI :: ColModInfo -> ColModInfo
unalignedCMI :: ColModInfo -> ColModInfo
unalignedCMI ColModInfo
cmi = case ColModInfo
cmi of
FillAligned OccSpec
_ AlignInfo
ai -> Int -> ColModInfo
FillTo (Int -> ColModInfo) -> Int -> ColModInfo
forall a b. (a -> b) -> a -> b
$ AlignInfo -> Int
widthAI AlignInfo
ai
FitTo Int
i Maybe (OccSpec, AlignInfo)
_ -> Int -> Maybe (OccSpec, AlignInfo) -> ColModInfo
FitTo Int
i Maybe (OccSpec, AlignInfo)
forall a. Maybe a
Nothing
ColModInfo
_ -> ColModInfo
cmi
ensureWidthCMI :: Int -> Position H -> ColModInfo -> ColModInfo
ensureWidthCMI :: Int -> Position H -> ColModInfo -> ColModInfo
ensureWidthCMI Int
w Position H
pos ColModInfo
cmi = case ColModInfo
cmi of
FillAligned OccSpec
oS ai :: AlignInfo
ai@(AlignInfo Int
lw Maybe Int
optRW)
->
let neededW :: Int
neededW = Int
w Int -> Int -> Int
forall a. Num a => a -> a -> a
- AlignInfo -> Int
widthAI AlignInfo
ai
in if Int
neededW Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0
then ColModInfo
cmi
else OccSpec -> AlignInfo -> ColModInfo
FillAligned OccSpec
oS (AlignInfo -> ColModInfo) -> AlignInfo -> ColModInfo
forall a b. (a -> b) -> a -> b
$ case Position H
pos of
Position H
Start -> case Maybe Int
optRW of
Just Int
rw -> Int -> Maybe Int -> AlignInfo
AlignInfo Int
lw (Maybe Int -> AlignInfo) -> Maybe Int -> AlignInfo
forall a b. (a -> b) -> a -> b
$ Int -> Maybe Int
forall a. a -> Maybe a
Just (Int
rw Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
neededW)
Maybe Int
Nothing -> Int -> Maybe Int -> AlignInfo
AlignInfo (Int
lw Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
neededW) Maybe Int
optRW
Position H
End -> Int -> Maybe Int -> AlignInfo
AlignInfo (Int
lw Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
neededW) Maybe Int
optRW
Position H
Center -> case Maybe Int
optRW of
Just Int
_ -> let (Int
q, Int
r) = Int
w Int -> Int -> (Int, Int)
forall a. Integral a => a -> a -> (a, a)
`divMod` Int
2
in Int -> Maybe Int -> AlignInfo
AlignInfo Int
q (Maybe Int -> AlignInfo) -> Maybe Int -> AlignInfo
forall a b. (a -> b) -> a -> b
$ Int -> Maybe Int
forall a. a -> Maybe a
Just (Int
q Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
r)
Maybe Int
Nothing -> Int -> Maybe Int -> AlignInfo
AlignInfo (Int
lw Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
neededW) Maybe Int
optRW
FillTo Int
maxLen -> Int -> ColModInfo
FillTo (Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
maxLen Int
w)
ColModInfo
_ -> ColModInfo
cmi
ensureWidthOfCMI :: String -> Position H -> ColModInfo -> ColModInfo
ensureWidthOfCMI :: String -> Position H -> ColModInfo -> ColModInfo
ensureWidthOfCMI = Int -> Position H -> ColModInfo -> ColModInfo
ensureWidthCMI (Int -> Position H -> ColModInfo -> ColModInfo)
-> (String -> Int)
-> String
-> Position H
-> ColModInfo
-> ColModInfo
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Int
forall a. Cell a => a -> Int
visibleLength
fitTitlesCMI :: [String] -> [Position H] -> [ColModInfo] -> [ColModInfo]
fitTitlesCMI :: [String] -> [Position H] -> [ColModInfo] -> [ColModInfo]
fitTitlesCMI = (String -> Position H -> ColModInfo -> ColModInfo)
-> [String] -> [Position H] -> [ColModInfo] -> [ColModInfo]
forall a b c d. (a -> b -> c -> d) -> [a] -> [b] -> [c] -> [d]
zipWith3 String -> Position H -> ColModInfo -> ColModInfo
ensureWidthOfCMI
columnModifier
:: (Cell a, StringBuilder b)
=> Position H
-> CutMark
-> ColModInfo
-> (a -> b)
columnModifier :: Position H -> CutMark -> ColModInfo -> a -> b
columnModifier Position H
pos CutMark
cms ColModInfo
colModInfo = case ColModInfo
colModInfo of
FillAligned OccSpec
oS AlignInfo
ai -> OccSpec -> AlignInfo -> a -> b
forall a b.
(Cell a, StringBuilder b) =>
OccSpec -> AlignInfo -> a -> b
align OccSpec
oS AlignInfo
ai
FillTo Int
maxLen -> Position H -> Int -> a -> b
forall a b o.
(Cell a, StringBuilder b) =>
Position o -> Int -> a -> b
pad Position H
pos Int
maxLen
FitTo Int
lim Maybe (OccSpec, AlignInfo)
mT ->
(a -> b)
-> ((OccSpec, AlignInfo) -> a -> b)
-> Maybe (OccSpec, AlignInfo)
-> a
-> b
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (Position H -> CutMark -> Int -> a -> b
forall a b o.
(Cell a, StringBuilder b) =>
Position o -> CutMark -> Int -> a -> b
trimOrPad Position H
pos CutMark
cms Int
lim) ((OccSpec -> AlignInfo -> a -> b) -> (OccSpec, AlignInfo) -> a -> b
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry ((OccSpec -> AlignInfo -> a -> b)
-> (OccSpec, AlignInfo) -> a -> b)
-> (OccSpec -> AlignInfo -> a -> b)
-> (OccSpec, AlignInfo)
-> a
-> b
forall a b. (a -> b) -> a -> b
$ Position H -> CutMark -> Int -> OccSpec -> AlignInfo -> a -> b
forall a b o.
(Cell a, StringBuilder b) =>
Position o -> CutMark -> Int -> OccSpec -> AlignInfo -> a -> b
alignFixed Position H
pos CutMark
cms Int
lim) Maybe (OccSpec, AlignInfo)
mT
deriveColModInfos :: Cell a => [(LenSpec, AlignSpec)] -> [Row a] -> [ColModInfo]
deriveColModInfos :: [(LenSpec, AlignSpec)] -> [Row a] -> [ColModInfo]
deriveColModInfos [(LenSpec, AlignSpec)]
specs = ((Row a -> ColModInfo) -> Row a -> ColModInfo)
-> [Row a -> ColModInfo] -> [Row a] -> [ColModInfo]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (Row a -> ColModInfo) -> Row a -> ColModInfo
forall a b. (a -> b) -> a -> b
($) (((LenSpec, AlignSpec) -> Row a -> ColModInfo)
-> [(LenSpec, AlignSpec)] -> [Row a -> ColModInfo]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (LenSpec, AlignSpec) -> Row a -> ColModInfo
forall a. Cell a => (LenSpec, AlignSpec) -> [a] -> ColModInfo
fSel [(LenSpec, AlignSpec)]
specs) ([Row a] -> [ColModInfo])
-> ([Row a] -> [Row a]) -> [Row a] -> [ColModInfo]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Row a] -> [Row a]
forall a. [[a]] -> [[a]]
transpose
where
fSel :: (LenSpec, AlignSpec) -> [a] -> ColModInfo
fSel (LenSpec
lenS, AlignSpec
alignS) = case AlignSpec
alignS of
AlignSpec
NoAlign -> let fitTo :: Int -> b -> ColModInfo
fitTo Int
i = ColModInfo -> b -> ColModInfo
forall a b. a -> b -> a
const (ColModInfo -> b -> ColModInfo) -> ColModInfo -> b -> ColModInfo
forall a b. (a -> b) -> a -> b
$ Int -> Maybe (OccSpec, AlignInfo) -> ColModInfo
FitTo Int
i Maybe (OccSpec, AlignInfo)
forall a. Maybe a
Nothing
expandUntil' :: (Bool -> Bool) -> Int -> Int -> ColModInfo
expandUntil' Bool -> Bool
f Int
i Int
max' = if Bool -> Bool
f (Int
max' Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
i)
then Int -> ColModInfo
FillTo Int
max'
else Int -> Int -> ColModInfo
forall b. Int -> b -> ColModInfo
fitTo Int
i Int
max'
fun :: Int -> ColModInfo
fun = case LenSpec
lenS of
LenSpec
Expand -> Int -> ColModInfo
FillTo
Fixed i -> Int -> Int -> ColModInfo
forall b. Int -> b -> ColModInfo
fitTo Int
i
ExpandUntil i -> (Bool -> Bool) -> Int -> Int -> ColModInfo
expandUntil' Bool -> Bool
forall a. a -> a
id Int
i
FixedUntil i -> (Bool -> Bool) -> Int -> Int -> ColModInfo
expandUntil' Bool -> Bool
not Int
i
in Int -> ColModInfo
fun (Int -> ColModInfo) -> ([a] -> Int) -> [a] -> ColModInfo
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Int] -> Int
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum ([Int] -> Int) -> ([a] -> [Int]) -> [a] -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> Int) -> [a] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map a -> Int
forall a. Cell a => a -> Int
visibleLength
AlignOcc OccSpec
oS -> let fitToAligned :: Int -> AlignInfo -> ColModInfo
fitToAligned Int
i = Int -> Maybe (OccSpec, AlignInfo) -> ColModInfo
FitTo Int
i (Maybe (OccSpec, AlignInfo) -> ColModInfo)
-> (AlignInfo -> Maybe (OccSpec, AlignInfo))
-> AlignInfo
-> ColModInfo
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (OccSpec, AlignInfo) -> Maybe (OccSpec, AlignInfo)
forall a. a -> Maybe a
Just ((OccSpec, AlignInfo) -> Maybe (OccSpec, AlignInfo))
-> (AlignInfo -> (OccSpec, AlignInfo))
-> AlignInfo
-> Maybe (OccSpec, AlignInfo)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (,) OccSpec
oS
fillAligned :: AlignInfo -> ColModInfo
fillAligned = OccSpec -> AlignInfo -> ColModInfo
FillAligned OccSpec
oS
expandUntil' :: (Bool -> Bool) -> Int -> AlignInfo -> ColModInfo
expandUntil' Bool -> Bool
f Int
i AlignInfo
ai = if Bool -> Bool
f (AlignInfo -> Int
widthAI AlignInfo
ai Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
i)
then AlignInfo -> ColModInfo
fillAligned AlignInfo
ai
else Int -> AlignInfo -> ColModInfo
fitToAligned Int
i AlignInfo
ai
fun :: AlignInfo -> ColModInfo
fun = case LenSpec
lenS of
LenSpec
Expand -> AlignInfo -> ColModInfo
fillAligned
Fixed i -> Int -> AlignInfo -> ColModInfo
fitToAligned Int
i
ExpandUntil i -> (Bool -> Bool) -> Int -> AlignInfo -> ColModInfo
expandUntil' Bool -> Bool
forall a. a -> a
id Int
i
FixedUntil i -> (Bool -> Bool) -> Int -> AlignInfo -> ColModInfo
expandUntil' Bool -> Bool
not Int
i
in AlignInfo -> ColModInfo
fun (AlignInfo -> ColModInfo)
-> ([a] -> AlignInfo) -> [a] -> ColModInfo
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> AlignInfo) -> [a] -> AlignInfo
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap (OccSpec -> a -> AlignInfo
forall a. Cell a => OccSpec -> a -> AlignInfo
deriveAlignInfo OccSpec
oS)
deriveColModInfos' :: Cell a => [ColSpec] -> [Row a] -> [ColModInfo]
deriveColModInfos' :: [ColSpec] -> [Row a] -> [ColModInfo]
deriveColModInfos' = [(LenSpec, AlignSpec)] -> [Row a] -> [ColModInfo]
forall a.
Cell a =>
[(LenSpec, AlignSpec)] -> [Row a] -> [ColModInfo]
deriveColModInfos ([(LenSpec, AlignSpec)] -> [Row a] -> [ColModInfo])
-> ([ColSpec] -> [(LenSpec, AlignSpec)])
-> [ColSpec]
-> [Row a]
-> [ColModInfo]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ColSpec -> (LenSpec, AlignSpec))
-> [ColSpec] -> [(LenSpec, AlignSpec)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (ColSpec -> LenSpec
lenSpec (ColSpec -> LenSpec)
-> (ColSpec -> AlignSpec) -> ColSpec -> (LenSpec, AlignSpec)
forall (a :: * -> * -> *) b c c'.
Arrow a =>
a b c -> a b c' -> a b (c, c')
&&& ColSpec -> AlignSpec
alignSpec)
deriveColMods
:: (Cell a, StringBuilder b)
=> [ColSpec]
-> [Row a]
-> [a -> b]
deriveColMods :: [ColSpec] -> [Row a] -> [a -> b]
deriveColMods [ColSpec]
specs [Row a]
tab =
((Position H, CutMark) -> ColModInfo -> a -> b)
-> [(Position H, CutMark)] -> [ColModInfo] -> [a -> b]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith ((Position H -> CutMark -> ColModInfo -> a -> b)
-> (Position H, CutMark) -> ColModInfo -> a -> b
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry Position H -> CutMark -> ColModInfo -> a -> b
forall a b.
(Cell a, StringBuilder b) =>
Position H -> CutMark -> ColModInfo -> a -> b
columnModifier) ((ColSpec -> (Position H, CutMark))
-> [ColSpec] -> [(Position H, CutMark)]
forall a b. (a -> b) -> [a] -> [b]
map (ColSpec -> Position H
position (ColSpec -> Position H)
-> (ColSpec -> CutMark) -> ColSpec -> (Position H, CutMark)
forall (a :: * -> * -> *) b c c'.
Arrow a =>
a b c -> a b c' -> a b (c, c')
&&& ColSpec -> CutMark
cutMark) [ColSpec]
specs) [ColModInfo]
cmis
where
cmis :: [ColModInfo]
cmis = [ColSpec] -> [Row a] -> [ColModInfo]
forall a. Cell a => [ColSpec] -> [Row a] -> [ColModInfo]
deriveColModInfos' [ColSpec]
specs [Row a]
tab
deriveAlignInfo :: Cell a => OccSpec -> a -> AlignInfo
deriveAlignInfo :: OccSpec -> a -> AlignInfo
deriveAlignInfo OccSpec
occSpec = (Char -> Bool) -> a -> AlignInfo
forall a. Cell a => (Char -> Bool) -> a -> AlignInfo
measureAlignment (OccSpec -> Char -> Bool
predicate OccSpec
occSpec)