{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeOperators #-}

-- | This module provides the 'KVITable' 'render' function for
-- rendering the table in a plain ASCII format.

module Data.KVITable.Render.ASCII
  (
    render
    -- re-export Render definitions to save the caller an additional import
  , RenderConfig(..)
  , defaultRenderConfig
  )
where

import qualified Data.List as L
import           Data.Maybe ( fromMaybe, isNothing )
import           Data.Text ( Text )
import qualified Data.Text as T
import           Lens.Micro ( (^.) )
import qualified Prettyprinter as PP

import           Data.KVITable
import           Data.KVITable.Render

import           Prelude hiding ( lookup )


-- | Renders the specified table in ASCII format, using the specified
-- 'RenderConfig' controls.

render :: PP.Pretty v => RenderConfig -> KVITable v -> Text
render :: forall v. Pretty v => RenderConfig -> KVITable v -> Text
render RenderConfig
cfg KVITable v
t =
  let kseq :: [Text]
kseq = forall a b. (a, b) -> a
fst forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> KVITable v
t forall s a. s -> Getting a s a -> a
^. forall v. Lens' (KVITable v) [(Text, [Text])]
keyVals
      (FmtLine
fmt, [Text]
hdr) = forall v.
Pretty v =>
RenderConfig -> KVITable v -> [Text] -> (FmtLine, [Text])
renderHdrs RenderConfig
cfg KVITable v
t [Text]
kseq
      bdy :: [Text]
bdy = forall v.
Pretty v =>
RenderConfig -> FmtLine -> [Text] -> KVITable v -> [Text]
renderSeq RenderConfig
cfg FmtLine
fmt [Text]
kseq KVITable v
t
  in [Text] -> Text
T.unlines forall a b. (a -> b) -> a -> b
$ [Text]
hdr forall a. Semigroup a => a -> a -> a
<> [Text]
bdy

----------------------------------------------------------------------

data FmtLine = FmtLine [Int] Sigils Sigils  -- last is for sepline
data Sigils = Sigils { Sigils -> Text
sep :: Text, Sigils -> Text
pad :: Text, Sigils -> Text
cap :: Text }

fmtLine :: [Int] -> FmtLine
fmtLine :: [Int] -> FmtLine
fmtLine [Int]
cols = [Int] -> Sigils -> Sigils -> FmtLine
FmtLine [Int]
cols
               Sigils { sep :: Text
sep = Text
"|", pad :: Text
pad = Text
" ", cap :: Text
cap = Text
"_" }
               Sigils { sep :: Text
sep = Text
"+", pad :: Text
pad = Text
"-", cap :: Text
cap = Text
"_" }

fmtColCnt :: FmtLine -> Int
fmtColCnt :: FmtLine -> Int
fmtColCnt (FmtLine [Int]
cols Sigils
_ Sigils
_) = forall (t :: * -> *) a. Foldable t => t a -> Int
length [Int]
cols

perColOvhd :: Int
perColOvhd :: Int
perColOvhd = Int
2 -- pad chars on either side of each column's entry

-- | Formatted width of output, including pad on either side of each
-- column's value (but not the outer set), and a separator between columns.
--
-- Note that a column size of 0 indicates that hideBlankCols is active
-- and the column was found to be empty of values, so it should not be
-- counted.
fmtWidth :: FmtLine -> Int
fmtWidth :: FmtLine -> Int
fmtWidth (FmtLine [Int]
cols Sigils
_ Sigils
_) =
  let cols' :: [Int]
cols' = forall a. (a -> Bool) -> [a] -> [a]
L.filter (forall a. Eq a => a -> a -> Bool
/= Int
0) [Int]
cols
  in forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Int]
cols' forall a. Num a => a -> a -> a
+ ((Int
perColOvhd forall a. Num a => a -> a -> a
+ Int
1) forall a. Num a => a -> a -> a
* (forall (t :: * -> *) a. Foldable t => t a -> Int
length [Int]
cols' forall a. Num a => a -> a -> a
- Int
1))

fmtEmptyCols :: FmtLine -> Bool
fmtEmptyCols :: FmtLine -> Bool
fmtEmptyCols (FmtLine [Int]
cols Sigils
_ Sigils
_) = forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Int]
cols forall a. Eq a => a -> a -> Bool
== Int
0

fmtAddColLeft :: Int -> FmtLine -> FmtLine
fmtAddColLeft :: Int -> FmtLine -> FmtLine
fmtAddColLeft Int
leftCol (FmtLine [Int]
cols Sigils
s Sigils
s') = [Int] -> Sigils -> Sigils -> FmtLine
FmtLine (Int
leftCol forall a. a -> [a] -> [a]
: [Int]
cols) Sigils
s Sigils
s'

data FmtVal = Separator | TxtVal Text | CenterVal Text

fmtRender :: FmtLine -> [FmtVal] -> Text
fmtRender :: FmtLine -> [FmtVal] -> Text
fmtRender (FmtLine [] Sigils
_sigils Sigils
_sepsigils) [] = Text
""
fmtRender (FmtLine [Int]
cols Sigils
sigils Sigils
sepsigils) [FmtVal]
vals =
  if forall (t :: * -> *) a. Foldable t => t a -> Int
length [Int]
cols forall a. Eq a => a -> a -> Bool
== forall (t :: * -> *) a. Foldable t => t a -> Int
length [FmtVal]
vals
  then let sig :: (Sigils -> t) -> FmtVal -> t
sig Sigils -> t
f FmtVal
o = case FmtVal
o of
                       FmtVal
Separator   -> Sigils -> t
f Sigils
sepsigils
                       TxtVal Text
_    -> Sigils -> t
f Sigils
sigils
                       CenterVal Text
_ -> Sigils -> t
f Sigils
sigils
           l :: Text
l = forall {t}. (Sigils -> t) -> FmtVal -> t
sig Sigils -> Text
sep forall a b. (a -> b) -> a -> b
$ forall a. [a] -> a
head [FmtVal]
vals
       in Text
l forall a. Semigroup a => a -> a -> a
<>
          [Text] -> Text
T.concat
          [ forall {t}. (Sigils -> t) -> FmtVal -> t
sig Sigils -> Text
pad FmtVal
fld forall a. Semigroup a => a -> a -> a
<>
            (case FmtVal
fld of
                FmtVal
Separator   -> [Char] -> Text
T.pack (forall a. Int -> a -> [a]
replicate Int
sz Char
'-')
                TxtVal Text
v    -> [Char] -> Text
T.pack (forall a. Int -> a -> [a]
replicate (Int
sz forall a. Num a => a -> a -> a
- Text -> Int
T.length Text
v) Char
' ') forall a. Semigroup a => a -> a -> a
<> Text
v
                CenterVal Text
t -> let (Int
w,Int
e) = (Int
sz forall a. Num a => a -> a -> a
- Text -> Int
T.length Text
t forall a. Num a => a -> a -> a
- Int
2) forall a. Integral a => a -> a -> (a, a)
`divMod` Int
2
                                   m :: Text
m = Sigils -> Text
cap Sigils
sigils
                                   ls :: Text
ls = Int -> Text -> Text
T.replicate (Int
w forall a. Num a => a -> a -> a
+ Int
0) Text
m
                                   rs :: Text
rs = Int -> Text -> Text
T.replicate (Int
w forall a. Num a => a -> a -> a
+ Int
e) Text
m
                               in if Text -> Int
T.length Text
t forall a. Num a => a -> a -> a
+ Int
2 forall a. Ord a => a -> a -> Bool
>= Int
sz
                                  then (Int -> Text -> Text
T.replicate (Int
sz forall a. Num a => a -> a -> a
- Text -> Int
T.length Text
t) Text
" ") forall a. Semigroup a => a -> a -> a
<> Text
t
                                  else Text
ls forall a. Semigroup a => a -> a -> a
<> Text
" " forall a. Semigroup a => a -> a -> a
<> Text
t forall a. Semigroup a => a -> a -> a
<> Text
" " forall a. Semigroup a => a -> a -> a
<> Text
rs
            ) forall a. Semigroup a => a -> a -> a
<>
            forall {t}. (Sigils -> t) -> FmtVal -> t
sig Sigils -> Text
pad FmtVal
fld forall a. Semigroup a => a -> a -> a
<>
            forall {t}. (Sigils -> t) -> FmtVal -> t
sig Sigils -> Text
sep FmtVal
fld  -- KWQ or if next fld is Nothing
          | (Int
sz,FmtVal
fld) <- forall a b. [a] -> [b] -> [(a, b)]
zip [Int]
cols [FmtVal]
vals, Int
sz forall a. Eq a => a -> a -> Bool
/= Int
0
          ]
  else forall a. HasCallStack => [Char] -> a
error ([Char]
"Insufficient arguments (" forall a. Semigroup a => a -> a -> a
<>
              forall a. Show a => a -> [Char]
show (forall (t :: * -> *) a. Foldable t => t a -> Int
length [FmtVal]
vals) forall a. Semigroup a => a -> a -> a
<> [Char]
")" forall a. Semigroup a => a -> a -> a
<>
              [Char]
" for FmtLine " forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> [Char]
show (forall (t :: * -> *) a. Foldable t => t a -> Int
length [Int]
cols))

----------------------------------------------------------------------

data HeaderLine = HdrLine FmtLine HdrVals Trailer
type HdrVals = [FmtVal]
type Trailer = Text

hdrFmt :: HeaderLine -> FmtLine
hdrFmt :: HeaderLine -> FmtLine
hdrFmt (HdrLine FmtLine
fmt [FmtVal]
_ Text
_) = FmtLine
fmt

renderHdrs :: PP.Pretty v => RenderConfig -> KVITable v -> [Key] -> (FmtLine, [Text])
renderHdrs :: forall v.
Pretty v =>
RenderConfig -> KVITable v -> [Text] -> (FmtLine, [Text])
renderHdrs RenderConfig
cfg KVITable v
t [Text]
keys =
  ( FmtLine
lastFmt
  , [ FmtLine -> [FmtVal] -> Text
fmtRender FmtLine
fmt [FmtVal]
hdrvals
      forall a. Semigroup a => a -> a -> a
<> (if Text -> Bool
T.null Text
trailer then Text
"" else (Text
" <- " forall a. Semigroup a => a -> a -> a
<> Text
trailer))
    | (HdrLine FmtLine
fmt [FmtVal]
hdrvals Text
trailer) <- [HeaderLine]
hrows
    ] forall a. Semigroup a => a -> a -> a
<>
    [ FmtLine -> [FmtVal] -> Text
fmtRender FmtLine
lastFmt (forall a. Int -> a -> [a]
replicate (FmtLine -> Int
fmtColCnt FmtLine
lastFmt) FmtVal
Separator) ])
  where
    hrows :: [HeaderLine]
hrows = forall v.
Pretty v =>
RenderConfig -> KVITable v -> [Text] -> [HeaderLine]
hdrstep RenderConfig
cfg KVITable v
t [Text]
keys
    lastFmt :: FmtLine
lastFmt = if forall (t :: * -> *) a. Foldable t => t a -> Bool
null [HeaderLine]
hrows then [Int] -> FmtLine
fmtLine [] else HeaderLine -> FmtLine
hdrFmt forall a b. (a -> b) -> a -> b
$ forall a. [a] -> a
head forall a b. (a -> b) -> a -> b
$ forall a. [a] -> [a]
reverse [HeaderLine]
hrows

hdrstep :: PP.Pretty v => RenderConfig -> KVITable v -> [Key] -> [HeaderLine]
hdrstep :: forall v.
Pretty v =>
RenderConfig -> KVITable v -> [Text] -> [HeaderLine]
hdrstep RenderConfig
_cfg KVITable v
t [] =
  -- colStackAt wasn't recognized, so devolve into a non-colstack table
  let valcoltxt :: Text
valcoltxt = KVITable v
t forall s a. s -> Getting a s a -> a
^. forall v. Lens' (KVITable v) Text
valueColName
      valcoltsz :: Int
valcoltsz = Text -> Int
T.length Text
valcoltxt
      valsizes :: [Int]
valsizes  = forall (t :: * -> *) a. Foldable t => t a -> Int
length forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Show a => a -> [Char]
show forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a ann. Pretty a => a -> Doc ann
PP.pretty forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> b
snd forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall v. KVITable v -> [Item (KVITable v)]
toList KVITable v
t
      valwidth :: Int
valwidth  = forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum forall a b. (a -> b) -> a -> b
$ Int
valcoltsz forall a. a -> [a] -> [a]
: [Int]
valsizes
  in [ FmtLine -> [FmtVal] -> Text -> HeaderLine
HdrLine ([Int] -> FmtLine
fmtLine [Int
valwidth]) [Text -> FmtVal
TxtVal Text
valcoltxt] Text
"" ]
hdrstep RenderConfig
cfg KVITable v
t (Text
key:[Text]
keys) =
  if RenderConfig -> Maybe Text
colStackAt RenderConfig
cfg forall a. Eq a => a -> a -> Bool
== forall a. a -> Maybe a
Just Text
key
  then forall v.
Pretty v =>
RenderConfig -> KVITable v -> KeySpec -> [Text] -> [HeaderLine]
hdrvalstep RenderConfig
cfg KVITable v
t [] (Text
keyforall a. a -> [a] -> [a]
:[Text]
keys)  -- switch to column-stacking mode
  else
    let keyw :: Int
keyw = forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum ( Text -> Int
T.length Text
key forall a. a -> [a] -> [a]
:
                         forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Text -> Int
T.length (forall a. a -> Maybe a -> a
fromMaybe [] forall a b. (a -> b) -> a -> b
$ forall a b. Eq a => a -> [(a, b)] -> Maybe b
L.lookup Text
key forall a b. (a -> b) -> a -> b
$ KVITable v
t forall s a. s -> Getting a s a -> a
^. forall v. Lens' (KVITable v) [(Text, [Text])]
keyVals) )
        mkhdr :: ([HeaderLine], Text) -> HeaderLine -> ([HeaderLine], b)
mkhdr ([HeaderLine]
hs, Text
v) (HdrLine FmtLine
fmt [FmtVal]
hdrvals Text
trailer) =
          ( FmtLine -> [FmtVal] -> Text -> HeaderLine
HdrLine (Int -> FmtLine -> FmtLine
fmtAddColLeft Int
keyw FmtLine
fmt) (Text -> FmtVal
TxtVal Text
v forall a. a -> [a] -> [a]
: [FmtVal]
hdrvals) Text
trailer forall a. a -> [a] -> [a]
: [HeaderLine]
hs , b
"")
    in forall a. [a] -> [a]
reverse forall a b. (a -> b) -> a -> b
$ forall a b. (a, b) -> a
fst forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl forall {b}.
IsString b =>
([HeaderLine], Text) -> HeaderLine -> ([HeaderLine], b)
mkhdr ([], Text
key) forall a b. (a -> b) -> a -> b
$ forall v.
Pretty v =>
RenderConfig -> KVITable v -> [Text] -> [HeaderLine]
hdrstep RenderConfig
cfg KVITable v
t [Text]
keys
         -- first line shows hdrval for non-colstack'd columns, others are blank

hdrvalstep :: PP.Pretty v => RenderConfig -> KVITable v -> KeySpec -> [Key] -> [HeaderLine]
hdrvalstep :: forall v.
Pretty v =>
RenderConfig -> KVITable v -> KeySpec -> [Text] -> [HeaderLine]
hdrvalstep RenderConfig
_ KVITable v
_ KeySpec
_ [] = forall a. HasCallStack => [Char] -> a
error [Char]
"ASCII hdrvalstep with empty keys after matching colStackAt -- impossible"
hdrvalstep RenderConfig
cfg KVITable v
t KeySpec
steppath (Text
key:[]) =
  let titles :: [Text]
titles = [Text] -> [Text]
ordering forall a b. (a -> b) -> a -> b
$ forall a. a -> Maybe a -> a
fromMaybe [] forall a b. (a -> b) -> a -> b
$ forall a b. Eq a => a -> [(a, b)] -> Maybe b
L.lookup Text
key forall a b. (a -> b) -> a -> b
$ KVITable v
t forall s a. s -> Getting a s a -> a
^. forall v. Lens' (KVITable v) [(Text, [Text])]
keyVals
      ordering :: [Text] -> [Text]
ordering = if RenderConfig -> Bool
sortKeyVals RenderConfig
cfg then [Text] -> [Text]
sortWithNums else forall a. a -> a
id
      cvalWidths :: Text -> [Int]
cvalWidths Text
kv = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall (t :: * -> *) a. Foldable t => t a -> Int
length forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Show a => a -> [Char]
show forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a ann. Pretty a => a -> Doc ann
PP.pretty forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> b
snd) forall a b. (a -> b) -> a -> b
$
                      forall a. (a -> Bool) -> [a] -> [a]
L.filter ((forall a. Eq a => [a] -> [a] -> Bool
L.isSuffixOf (KeySpec
steppath forall a. Semigroup a => a -> a -> a
<> [(Text
key, Text
kv)])) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> a
fst) forall a b. (a -> b) -> a -> b
$
                      forall v. KVITable v -> [Item (KVITable v)]
toList KVITable v
t
      colWidth :: Text -> Int
colWidth Text
kv = let cvw :: [Int]
cvw = Text -> [Int]
cvalWidths Text
kv
                    in if forall (t :: * -> *). Foldable t => t Bool -> Bool
and [ RenderConfig -> Bool
hideBlankCols RenderConfig
cfg, forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Int]
cvw forall a. Eq a => a -> a -> Bool
== Int
0 ]
                    then Int
0
                    else forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum forall a b. (a -> b) -> a -> b
$ Text -> Int
T.length Text
kv forall a. a -> [a] -> [a]
: [Int]
cvw
      cwidths :: [Int]
cwidths = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Text -> Int
colWidth [Text]
titles
      fmtcols :: [Int]
fmtcols = if RenderConfig -> Bool
equisizedCols RenderConfig
cfg
                then (forall a. Int -> a -> [a]
replicate (forall (t :: * -> *) a. Foldable t => t a -> Int
length [Int]
cwidths) (forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum [Int]
cwidths))
                else [Int]
cwidths
  in [ FmtLine -> [FmtVal] -> Text -> HeaderLine
HdrLine ([Int] -> FmtLine
fmtLine forall a b. (a -> b) -> a -> b
$ [Int]
fmtcols) (Text -> FmtVal
TxtVal forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Text]
titles) Text
key ]
hdrvalstep RenderConfig
cfg KVITable v
t KeySpec
steppath (Text
key:[Text]
keys) =
  let vals :: [Text]
vals = [Text] -> [Text]
ordering forall a b. (a -> b) -> a -> b
$ forall a. a -> Maybe a -> a
fromMaybe [] forall a b. (a -> b) -> a -> b
$ forall a b. Eq a => a -> [(a, b)] -> Maybe b
L.lookup Text
key forall a b. (a -> b) -> a -> b
$ KVITable v
t forall s a. s -> Getting a s a -> a
^. forall v. Lens' (KVITable v) [(Text, [Text])]
keyVals
      ordering :: [Text] -> [Text]
ordering = if RenderConfig -> Bool
sortKeyVals RenderConfig
cfg then [Text] -> [Text]
sortWithNums else forall a. a -> a
id
      subhdrsV :: Text -> [HeaderLine]
subhdrsV Text
v = forall v.
Pretty v =>
RenderConfig -> KVITable v -> KeySpec -> [Text] -> [HeaderLine]
hdrvalstep RenderConfig
cfg KVITable v
t (KeySpec
steppath forall a. Semigroup a => a -> a -> a
<> [(Text
key,Text
v)]) [Text]
keys
      subTtlHdrs :: [(Int, [HeaderLine])]
subTtlHdrs = let subAtVal :: Text -> (Int, [HeaderLine])
subAtVal Text
v = (Text -> Int
T.length Text
v, Text -> [HeaderLine]
subhdrsV Text
v)
                   in forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Text -> (Int, [HeaderLine])
subAtVal [Text]
vals
      szexts :: [Int]
szexts = let subVW :: [HeaderLine] -> Int
subVW = FmtLine -> Int
fmtWidth forall b c a. (b -> c) -> (a -> b) -> a -> c
. HeaderLine -> FmtLine
hdrFmt forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [a] -> a
head
                   subW :: (a, [HeaderLine]) -> (a, Int)
subW (a
hl,[HeaderLine]
sh) = let sv :: Int
sv = [HeaderLine] -> Int
subVW [HeaderLine]
sh
                                  in if forall (t :: * -> *). Foldable t => t Bool -> Bool
and [ RenderConfig -> Bool
hideBlankCols RenderConfig
cfg,
                                              FmtLine -> Bool
fmtEmptyCols forall a b. (a -> b) -> a -> b
$ HeaderLine -> FmtLine
hdrFmt forall a b. (a -> b) -> a -> b
$ forall a. [a] -> a
head [HeaderLine]
sh
                                            ]
                                     then (a
0, Int
0)
                                     else (a
hl, Int
sv)
               in forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry forall a. Ord a => a -> a -> a
max forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall {a}. Num a => (a, [HeaderLine]) -> (a, Int)
subW) [(Int, [HeaderLine])]
subTtlHdrs
      rsz_extsubhdrs :: [HeaderLine]
rsz_extsubhdrs = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall {t :: * -> *}. Foldable t => t HeaderLine -> HeaderLine
hdrJoin forall a b. (a -> b) -> a -> b
$
                       forall a. [[a]] -> [[a]]
L.transpose forall a b. (a -> b) -> a -> b
$
                       forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry forall {f :: * -> *}.
Functor f =>
Int -> f HeaderLine -> f HeaderLine
rsz_hdrstack) forall a b. (a -> b) -> a -> b
$
                       forall a b. [a] -> [b] -> [(a, b)]
zip [Int]
szhdrs forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a b. (a, b) -> b
snd [(Int, [HeaderLine])]
subTtlHdrs
      largest :: Int
largest = forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum [Int]
szexts
      szhdrs :: [Int]
szhdrs = if RenderConfig -> Bool
equisizedCols RenderConfig
cfg Bool -> Bool -> Bool
&& Bool -> Bool
not (RenderConfig -> Bool
hideBlankCols RenderConfig
cfg)
               then forall a. Int -> a -> [a]
replicate (forall (t :: * -> *) a. Foldable t => t a -> Int
length [Text]
vals) Int
largest
               else [Int]
szexts
      rsz_hdrstack :: Int -> f HeaderLine -> f HeaderLine
rsz_hdrstack Int
s f HeaderLine
vhs = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Int -> HeaderLine -> HeaderLine
rsz_hdrs Int
s) f HeaderLine
vhs
      rsz_hdrs :: Int -> HeaderLine -> HeaderLine
rsz_hdrs Int
hw (HdrLine (FmtLine [Int]
c Sigils
s Sigils
j) [FmtVal]
v Text
r) =
        let nzCols :: [Int]
nzCols = forall a. (a -> Bool) -> [a] -> [a]
L.filter (forall a. Eq a => a -> a -> Bool
/= Int
0) [Int]
c
            pcw :: Int
pcw = forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Int]
nzCols forall a. Num a => a -> a -> a
+ ((Int
perColOvhd forall a. Num a => a -> a -> a
+ Int
1) forall a. Num a => a -> a -> a
* (forall (t :: * -> *) a. Foldable t => t a -> Int
length [Int]
nzCols forall a. Num a => a -> a -> a
- Int
1))
            (Int
ew,Int
w0) = let l :: Int
l = forall (t :: * -> *) a. Foldable t => t a -> Int
length [Int]
nzCols
                      in if Int
l forall a. Eq a => a -> a -> Bool
== Int
0 then (Int
0,Int
0)
                         else forall a. Ord a => a -> a -> a
max Int
0 (Int
hw forall a. Num a => a -> a -> a
- Int
pcw) forall a. Integral a => a -> a -> (a, a)
`divMod` forall (t :: * -> *) a. Foldable t => t a -> Int
length [Int]
nzCols
            c' :: [Int]
c' = forall a b. (a, b) -> a
fst forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl (\([Int]
c'',Int
n) Int
w -> ([Int]
c''forall a. Semigroup a => a -> a -> a
<>[Int
nforall a. Num a => a -> a -> a
+Int
w],Int
ew)) ([],Int
ewforall a. Num a => a -> a -> a
+Int
w0) [Int]
c
        in FmtLine -> [FmtVal] -> Text -> HeaderLine
HdrLine ([Int] -> Sigils -> Sigils -> FmtLine
FmtLine [Int]
c' Sigils
s Sigils
j) [FmtVal]
v Text
r
      hdrJoin :: t HeaderLine -> HeaderLine
hdrJoin t HeaderLine
hl = forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl HeaderLine -> HeaderLine -> HeaderLine
hlJoin (FmtLine -> [FmtVal] -> Text -> HeaderLine
HdrLine ([Int] -> FmtLine
fmtLine []) [] Text
"") t HeaderLine
hl
      hlJoin :: HeaderLine -> HeaderLine -> HeaderLine
hlJoin (HdrLine (FmtLine [Int]
c Sigils
s Sigils
j) [FmtVal]
v Text
_) (HdrLine (FmtLine [Int]
c' Sigils
_ Sigils
_) [FmtVal]
v' Text
r) =
        FmtLine -> [FmtVal] -> Text -> HeaderLine
HdrLine ([Int] -> Sigils -> Sigils -> FmtLine
FmtLine ([Int]
cforall a. Semigroup a => a -> a -> a
<>[Int]
c') Sigils
s Sigils
j) ([FmtVal]
vforall a. Semigroup a => a -> a -> a
<>[FmtVal]
v') Text
r
      tvals :: [FmtVal]
tvals = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Text -> FmtVal
CenterVal [Text]
vals
  in FmtLine -> [FmtVal] -> Text -> HeaderLine
HdrLine ([Int] -> FmtLine
fmtLine [Int]
szhdrs) [FmtVal]
tvals Text
key forall a. a -> [a] -> [a]
: [HeaderLine]
rsz_extsubhdrs

renderSeq :: PP.Pretty v => RenderConfig -> FmtLine -> [Key] -> KVITable v -> [Text]
renderSeq :: forall v.
Pretty v =>
RenderConfig -> FmtLine -> [Text] -> KVITable v -> [Text]
renderSeq RenderConfig
cfg FmtLine
fmt [Text]
keys KVITable v
kvitbl = FmtLine -> [FmtVal] -> Text
fmtRender FmtLine
fmt forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> b
snd forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Text] -> KeySpec -> [(Bool, [FmtVal])]
asciiRows [Text]
keys []
  where
    asciiRows :: [Key] -> KeySpec -> [ (Bool, [FmtVal]) ]
    asciiRows :: [Text] -> KeySpec -> [(Bool, [FmtVal])]
asciiRows [] KeySpec
path =
      let v :: Maybe v
v = forall v. KeySpec -> KVITable v -> Maybe v
lookup KeySpec
path KVITable v
kvitbl
          skip :: Bool
skip = case Maybe v
v of
                   Maybe v
Nothing -> RenderConfig -> Bool
hideBlankRows RenderConfig
cfg
                   Just v
_  -> Bool
False
      in if Bool
skip then []
         else [ (Bool
False, [ forall b a. b -> (a -> b) -> Maybe a -> b
maybe (Text -> FmtVal
TxtVal Text
"") Text -> FmtVal
TxtVal ([Char] -> Text
T.pack forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Show a => a -> [Char]
show forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a ann. Pretty a => a -> Doc ann
PP.pretty forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe v
v) ]) ]
    asciiRows (Text
key:[Text]
kseq) KeySpec
path
      | RenderConfig -> Maybe Text
colStackAt RenderConfig
cfg forall a. Eq a => a -> a -> Bool
== forall a. a -> Maybe a
Just Text
key =
        let filterOrDefaultBlankRows :: [(a, [Maybe Text])] -> [(a, [FmtVal])]
filterOrDefaultBlankRows =
              forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [Maybe Text] -> [FmtVal]
defaultBlanks) forall b c a. (b -> c) -> (a -> b) -> a -> c
.
              if RenderConfig -> Bool
hideBlankRows RenderConfig
cfg
              then forall a. (a -> Bool) -> [a] -> [a]
L.filter (Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all forall a. Maybe a -> Bool
isNothing forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> b
snd)
              else forall a. a -> a
id
            defaultBlanks :: [Maybe Text] -> [FmtVal]
defaultBlanks = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\Maybe Text
v -> forall b a. b -> (a -> b) -> Maybe a -> b
maybe (Text -> FmtVal
TxtVal Text
"") Text -> FmtVal
TxtVal Maybe Text
v)
        in forall {a}. [(a, [Maybe Text])] -> [(a, [FmtVal])]
filterOrDefaultBlankRows forall a b. (a -> b) -> a -> b
$ [ (Bool
False, [Text] -> KeySpec -> [Maybe Text]
multivalRows (Text
keyforall a. a -> [a] -> [a]
:[Text]
kseq) KeySpec
path) ]
      | Bool
otherwise =
        let subrows :: Text -> [(Bool, [FmtVal])]
subrows Text
keyval = [Text] -> KeySpec -> [(Bool, [FmtVal])]
asciiRows [Text]
kseq forall a b. (a -> b) -> a -> b
$ KeySpec
path forall a. Semigroup a => a -> a -> a
<> [ (Text
key, Text
keyval) ]
            grprow :: [(Bool, [FmtVal])] -> [(Bool, [FmtVal])]
grprow [(Bool, [FmtVal])]
subs = if Text
key forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` RenderConfig -> [Text]
rowGroup RenderConfig
cfg Bool -> Bool -> Bool
&& Bool -> Bool
not (forall (t :: * -> *) a. Foldable t => t a -> Bool
null [(Bool, [FmtVal])]
subs)
                          then let subl :: [(Bool, [FmtVal])]
subl = [ (Bool
True, forall a. Int -> a -> [a]
replicate (forall (t :: * -> *) a. Foldable t => t a -> Int
length forall a b. (a -> b) -> a -> b
$ forall a b. (a, b) -> b
snd forall a b. (a -> b) -> a -> b
$ forall a. [a] -> a
head [(Bool, [FmtVal])]
subs) FmtVal
Separator) ]
                               in if forall a b. (a, b) -> a
fst (forall a. [a] -> a
last [(Bool, [FmtVal])]
subs)
                                  then forall a. [a] -> [a]
init [(Bool, [FmtVal])]
subs forall a. Semigroup a => a -> a -> a
<> [(Bool, [FmtVal])]
subl
                                  else [(Bool, [FmtVal])]
subs forall a. Semigroup a => a -> a -> a
<> [(Bool, [FmtVal])]
subl
                          else [(Bool, [FmtVal])]
subs
            addSubrows :: [(Bool, [FmtVal])] -> Text -> [(Bool, [FmtVal])]
addSubrows [(Bool, [FmtVal])]
ret Text
keyval = [(Bool, [FmtVal])]
ret forall a. Semigroup a => a -> a -> a
<> ([(Bool, [FmtVal])] -> [(Bool, [FmtVal])]
grprow forall a b. (a -> b) -> a -> b
$ forall a b. (a, b) -> a
fst forall a b. (a -> b) -> a -> b
$
                                            forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl forall {a}.
([(a, [FmtVal])], Text) -> (a, [FmtVal]) -> ([(a, [FmtVal])], Text)
leftAdd ([],Text
keyval) forall a b. (a -> b) -> a -> b
$ Text -> [(Bool, [FmtVal])]
subrows Text
keyval)
            leftAdd :: ([(a, [FmtVal])], Text) -> (a, [FmtVal]) -> ([(a, [FmtVal])], Text)
leftAdd ([(a, [FmtVal])]
acc,Text
kv) (a
b,[FmtVal]
subrow) = ([(a, [FmtVal])]
acc forall a. Semigroup a => a -> a -> a
<> [ (a
b, Text -> FmtVal
TxtVal Text
kv forall a. a -> [a] -> [a]
: [FmtVal]
subrow) ],
                                           if RenderConfig -> Bool
rowRepeat RenderConfig
cfg then Text
kv else Text
"")
            ordering :: [Text] -> [Text]
ordering = if RenderConfig -> Bool
sortKeyVals RenderConfig
cfg then [Text] -> [Text]
sortWithNums else forall a. a -> a
id
        in forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl [(Bool, [FmtVal])] -> Text -> [(Bool, [FmtVal])]
addSubrows [] forall a b. (a -> b) -> a -> b
$ [Text] -> [Text]
ordering forall a b. (a -> b) -> a -> b
$ forall a. a -> Maybe a -> a
fromMaybe [] forall a b. (a -> b) -> a -> b
$ forall a b. Eq a => a -> [(a, b)] -> Maybe b
L.lookup Text
key forall a b. (a -> b) -> a -> b
$ KVITable v
kvitbl forall s a. s -> Getting a s a -> a
^. forall v. Lens' (KVITable v) [(Text, [Text])]
keyVals
    multivalRows :: [Key] -> KeySpec -> [ Maybe Text ]
    multivalRows :: [Text] -> KeySpec -> [Maybe Text]
multivalRows (Text
key:[]) KeySpec
path =
      let ordering :: [Text] -> [Text]
ordering = if RenderConfig -> Bool
sortKeyVals RenderConfig
cfg then [Text] -> [Text]
sortWithNums else forall a. a -> a
id
          keyvals :: [Text]
keyvals = [Text] -> [Text]
ordering forall a b. (a -> b) -> a -> b
$ forall a. a -> Maybe a -> a
fromMaybe [] forall a b. (a -> b) -> a -> b
$ forall a b. Eq a => a -> [(a, b)] -> Maybe b
L.lookup Text
key forall a b. (a -> b) -> a -> b
$ KVITable v
kvitbl forall s a. s -> Getting a s a -> a
^. forall v. Lens' (KVITable v) [(Text, [Text])]
keyVals
          showEnt :: v -> Text
showEnt = [Char] -> Text
T.pack forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Show a => a -> [Char]
show forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a ann. Pretty a => a -> Doc ann
PP.pretty
      in (\Text
v -> (v -> Text
showEnt forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (forall v. KeySpec -> KVITable v -> Maybe v
lookup (KeySpec
path forall a. Semigroup a => a -> a -> a
<> [(Text
key,Text
v)]) KVITable v
kvitbl))) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Text]
keyvals
    multivalRows (Text
key:[Text]
kseq) KeySpec
path =
      let ordering :: [Text] -> [Text]
ordering = if RenderConfig -> Bool
sortKeyVals RenderConfig
cfg then [Text] -> [Text]
sortWithNums else forall a. a -> a
id
          keyvals :: [Text]
keyvals = [Text] -> [Text]
ordering forall a b. (a -> b) -> a -> b
$ forall a. a -> Maybe a -> a
fromMaybe [] forall a b. (a -> b) -> a -> b
$ forall a b. Eq a => a -> [(a, b)] -> Maybe b
L.lookup Text
key  forall a b. (a -> b) -> a -> b
$ KVITable v
kvitbl forall s a. s -> Getting a s a -> a
^. forall v. Lens' (KVITable v) [(Text, [Text])]
keyVals
      in forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (\Text
v -> [Text] -> KeySpec -> [Maybe Text]
multivalRows [Text]
kseq (KeySpec
path forall a. Semigroup a => a -> a -> a
<> [(Text
key,Text
v)])) [Text]
keyvals
    multivalRows [] KeySpec
_ = forall a. HasCallStack => [Char] -> a
error [Char]
"multivalRows cannot be called with no keys!"