{-# 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 :: RenderConfig -> KVITable v -> Text
render RenderConfig
cfg KVITable v
t =
  let kseq :: [Text]
kseq = (Text, [Text]) -> Text
forall a b. (a, b) -> a
fst ((Text, [Text]) -> Text) -> [(Text, [Text])] -> [Text]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> KVITable v
t KVITable v
-> Getting [(Text, [Text])] (KVITable v) [(Text, [Text])]
-> [(Text, [Text])]
forall s a. s -> Getting a s a -> a
^. Getting [(Text, [Text])] (KVITable v) [(Text, [Text])]
forall v. Lens' (KVITable v) [(Text, [Text])]
keyVals
      (FmtLine
fmt, [Text]
hdr) = RenderConfig -> KVITable v -> [Text] -> (FmtLine, [Text])
forall v.
Pretty v =>
RenderConfig -> KVITable v -> [Text] -> (FmtLine, [Text])
renderHdrs RenderConfig
cfg KVITable v
t [Text]
kseq
      bdy :: [Text]
bdy = RenderConfig -> FmtLine -> [Text] -> KVITable v -> [Text]
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 ([Text] -> Text) -> [Text] -> Text
forall a b. (a -> b) -> a -> b
$ [Text]
hdr [Text] -> [Text] -> [Text]
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 :: Text -> Text -> Text -> Sigils
Sigils { sep :: Text
sep = Text
"|", pad :: Text
pad = Text
" ", cap :: Text
cap = Text
"_" }
               Sigils :: Text -> Text -> Text -> Sigils
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
_) = [Int] -> Int
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' = (Int -> Bool) -> [Int] -> [Int]
forall a. (a -> Bool) -> [a] -> [a]
L.filter (Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
0) [Int]
cols
  in [Int] -> Int
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Int]
cols' Int -> Int -> Int
forall a. Num a => a -> a -> a
+ ((Int
perColOvhd Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Int -> Int -> Int
forall a. Num a => a -> a -> a
* ([Int] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Int]
cols' Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1))

fmtEmptyCols :: FmtLine -> Bool
fmtEmptyCols :: FmtLine -> Bool
fmtEmptyCols (FmtLine [Int]
cols Sigils
_ Sigils
_) = [Int] -> Int
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Int]
cols Int -> Int -> Bool
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 Int -> [Int] -> [Int]
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 [Int] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Int]
cols Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== [FmtVal] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [FmtVal]
vals
  then let sig :: (Sigils -> p) -> FmtVal -> p
sig Sigils -> p
f FmtVal
o = case FmtVal
o of
                       FmtVal
Separator   -> Sigils -> p
f Sigils
sepsigils
                       TxtVal Text
_    -> Sigils -> p
f Sigils
sigils
                       CenterVal Text
_ -> Sigils -> p
f Sigils
sigils
           l :: Text
l = (Sigils -> Text) -> FmtVal -> Text
forall p. (Sigils -> p) -> FmtVal -> p
sig Sigils -> Text
sep (FmtVal -> Text) -> FmtVal -> Text
forall a b. (a -> b) -> a -> b
$ [FmtVal] -> FmtVal
forall a. [a] -> a
head [FmtVal]
vals
       in Text
l Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>
          [Text] -> Text
T.concat
          [ (Sigils -> Text) -> FmtVal -> Text
forall p. (Sigils -> p) -> FmtVal -> p
sig Sigils -> Text
pad FmtVal
fld Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>
            (case FmtVal
fld of
                FmtVal
Separator   -> String -> Text
T.pack (Int -> Char -> String
forall a. Int -> a -> [a]
replicate Int
sz Char
'-')
                TxtVal Text
v    -> String -> Text
T.pack (Int -> Char -> String
forall a. Int -> a -> [a]
replicate (Int
sz Int -> Int -> Int
forall a. Num a => a -> a -> a
- Text -> Int
T.length Text
v) Char
' ') Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
v
                CenterVal Text
t -> let (Int
w,Int
e) = (Int
sz Int -> Int -> Int
forall a. Num a => a -> a -> a
- Text -> Int
T.length Text
t Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
2) Int -> Int -> (Int, Int)
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 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
0) Text
m
                                   rs :: Text
rs = Int -> Text -> Text
T.replicate (Int
w Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
e) Text
m
                               in if Text -> Int
T.length Text
t Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
2 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
sz
                                  then (Int -> Text -> Text
T.replicate (Int
sz Int -> Int -> Int
forall a. Num a => a -> a -> a
- Text -> Int
T.length Text
t) Text
" ") Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
t
                                  else Text
ls Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
t Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
rs
            ) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>
            (Sigils -> Text) -> FmtVal -> Text
forall p. (Sigils -> p) -> FmtVal -> p
sig Sigils -> Text
pad FmtVal
fld Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>
            (Sigils -> Text) -> FmtVal -> Text
forall p. (Sigils -> p) -> FmtVal -> p
sig Sigils -> Text
sep FmtVal
fld  -- KWQ or if next fld is Nothing
          | (Int
sz,FmtVal
fld) <- [Int] -> [FmtVal] -> [(Int, FmtVal)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Int]
cols [FmtVal]
vals, Int
sz Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
0
          ]
  else String -> Text
forall a. HasCallStack => String -> a
error (String
"Insufficient arguments (" String -> String -> String
forall a. Semigroup a => a -> a -> a
<>
              Int -> String
forall a. Show a => a -> String
show ([FmtVal] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [FmtVal]
vals) String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
")" String -> String -> String
forall a. Semigroup a => a -> a -> a
<>
              String
" for FmtLine " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Int -> String
forall a. Show a => a -> String
show ([Int] -> Int
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 :: RenderConfig -> KVITable v -> [Text] -> (FmtLine, [Text])
renderHdrs RenderConfig
cfg KVITable v
t [Text]
keys =
  ( FmtLine
lastFmt
  , [ FmtLine -> [FmtVal] -> Text
fmtRender FmtLine
fmt [FmtVal]
hdrvals
      Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> (if Text -> Bool
T.null Text
trailer then Text
"" else (Text
" <- " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
trailer))
    | (HdrLine FmtLine
fmt [FmtVal]
hdrvals Text
trailer) <- [HeaderLine]
hrows
    ] [Text] -> [Text] -> [Text]
forall a. Semigroup a => a -> a -> a
<>
    [ FmtLine -> [FmtVal] -> Text
fmtRender FmtLine
lastFmt (Int -> FmtVal -> [FmtVal]
forall a. Int -> a -> [a]
replicate (FmtLine -> Int
fmtColCnt FmtLine
lastFmt) FmtVal
Separator) ])
  where
    hrows :: [HeaderLine]
hrows = RenderConfig -> KVITable v -> [Text] -> [HeaderLine]
forall v.
Pretty v =>
RenderConfig -> KVITable v -> [Text] -> [HeaderLine]
hdrstep RenderConfig
cfg KVITable v
t [Text]
keys
    lastFmt :: FmtLine
lastFmt = if [HeaderLine] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [HeaderLine]
hrows then [Int] -> FmtLine
fmtLine [] else HeaderLine -> FmtLine
hdrFmt (HeaderLine -> FmtLine) -> HeaderLine -> FmtLine
forall a b. (a -> b) -> a -> b
$ [HeaderLine] -> HeaderLine
forall a. [a] -> a
head ([HeaderLine] -> HeaderLine) -> [HeaderLine] -> HeaderLine
forall a b. (a -> b) -> a -> b
$ [HeaderLine] -> [HeaderLine]
forall a. [a] -> [a]
reverse [HeaderLine]
hrows

hdrstep :: PP.Pretty v => RenderConfig -> KVITable v -> [Key] -> [HeaderLine]
hdrstep :: 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 KVITable v -> Getting Text (KVITable v) Text -> Text
forall s a. s -> Getting a s a -> a
^. Getting Text (KVITable v) Text
forall v. Lens' (KVITable v) Text
valueColName
      valcoltsz :: Int
valcoltsz = Text -> Int
T.length Text
valcoltxt
      valsizes :: [Int]
valsizes  = String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length (String -> Int) -> ((KeySpec, v) -> String) -> (KeySpec, v) -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Doc Any -> String
forall a. Show a => a -> String
show (Doc Any -> String)
-> ((KeySpec, v) -> Doc Any) -> (KeySpec, v) -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. v -> Doc Any
forall a ann. Pretty a => a -> Doc ann
PP.pretty (v -> Doc Any) -> ((KeySpec, v) -> v) -> (KeySpec, v) -> Doc Any
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (KeySpec, v) -> v
forall a b. (a, b) -> b
snd ((KeySpec, v) -> Int) -> [(KeySpec, v)] -> [Int]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> KVITable v -> [Item (KVITable v)]
forall v. KVITable v -> [Item (KVITable v)]
toList KVITable v
t
      valwidth :: Int
valwidth  = [Int] -> Int
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum ([Int] -> Int) -> [Int] -> Int
forall a b. (a -> b) -> a -> b
$ Int
valcoltsz Int -> [Int] -> [Int]
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 Maybe Text -> Maybe Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text -> Maybe Text
forall a. a -> Maybe a
Just Text
key
  then RenderConfig -> KVITable v -> KeySpec -> [Text] -> [HeaderLine]
forall v.
Pretty v =>
RenderConfig -> KVITable v -> KeySpec -> [Text] -> [HeaderLine]
hdrvalstep RenderConfig
cfg KVITable v
t [] (Text
keyText -> [Text] -> [Text]
forall a. a -> [a] -> [a]
:[Text]
keys)  -- switch to column-stacking mode
  else
    let keyw :: Int
keyw = [Int] -> Int
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum ( Text -> Int
T.length Text
key Int -> [Int] -> [Int]
forall a. a -> [a] -> [a]
:
                         (Text -> Int) -> [Text] -> [Int]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Text -> Int
T.length ([Text] -> Maybe [Text] -> [Text]
forall a. a -> Maybe a -> a
fromMaybe [] (Maybe [Text] -> [Text]) -> Maybe [Text] -> [Text]
forall a b. (a -> b) -> a -> b
$ Text -> [(Text, [Text])] -> Maybe [Text]
forall a b. Eq a => a -> [(a, b)] -> Maybe b
L.lookup Text
key ([(Text, [Text])] -> Maybe [Text])
-> [(Text, [Text])] -> Maybe [Text]
forall a b. (a -> b) -> a -> b
$ KVITable v
t KVITable v
-> Getting [(Text, [Text])] (KVITable v) [(Text, [Text])]
-> [(Text, [Text])]
forall s a. s -> Getting a s a -> a
^. Getting [(Text, [Text])] (KVITable v) [(Text, [Text])]
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 FmtVal -> [FmtVal] -> [FmtVal]
forall a. a -> [a] -> [a]
: [FmtVal]
hdrvals) Text
trailer HeaderLine -> [HeaderLine] -> [HeaderLine]
forall a. a -> [a] -> [a]
: [HeaderLine]
hs , b
"")
    in [HeaderLine] -> [HeaderLine]
forall a. [a] -> [a]
reverse ([HeaderLine] -> [HeaderLine]) -> [HeaderLine] -> [HeaderLine]
forall a b. (a -> b) -> a -> b
$ ([HeaderLine], Text) -> [HeaderLine]
forall a b. (a, b) -> a
fst (([HeaderLine], Text) -> [HeaderLine])
-> ([HeaderLine], Text) -> [HeaderLine]
forall a b. (a -> b) -> a -> b
$ (([HeaderLine], Text) -> HeaderLine -> ([HeaderLine], Text))
-> ([HeaderLine], Text) -> [HeaderLine] -> ([HeaderLine], Text)
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl ([HeaderLine], Text) -> HeaderLine -> ([HeaderLine], Text)
forall b.
IsString b =>
([HeaderLine], Text) -> HeaderLine -> ([HeaderLine], b)
mkhdr ([], Text
key) ([HeaderLine] -> ([HeaderLine], Text))
-> [HeaderLine] -> ([HeaderLine], Text)
forall a b. (a -> b) -> a -> b
$ RenderConfig -> KVITable v -> [Text] -> [HeaderLine]
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 :: RenderConfig -> KVITable v -> KeySpec -> [Text] -> [HeaderLine]
hdrvalstep RenderConfig
_ KVITable v
_ KeySpec
_ [] = String -> [HeaderLine]
forall a. HasCallStack => String -> a
error String
"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 ([Text] -> [Text]) -> [Text] -> [Text]
forall a b. (a -> b) -> a -> b
$ [Text] -> Maybe [Text] -> [Text]
forall a. a -> Maybe a -> a
fromMaybe [] (Maybe [Text] -> [Text]) -> Maybe [Text] -> [Text]
forall a b. (a -> b) -> a -> b
$ Text -> [(Text, [Text])] -> Maybe [Text]
forall a b. Eq a => a -> [(a, b)] -> Maybe b
L.lookup Text
key ([(Text, [Text])] -> Maybe [Text])
-> [(Text, [Text])] -> Maybe [Text]
forall a b. (a -> b) -> a -> b
$ KVITable v
t KVITable v
-> Getting [(Text, [Text])] (KVITable v) [(Text, [Text])]
-> [(Text, [Text])]
forall s a. s -> Getting a s a -> a
^. Getting [(Text, [Text])] (KVITable v) [(Text, [Text])]
forall v. Lens' (KVITable v) [(Text, [Text])]
keyVals
      ordering :: [Text] -> [Text]
ordering = if RenderConfig -> Bool
sortKeyVals RenderConfig
cfg then [Text] -> [Text]
sortWithNums else [Text] -> [Text]
forall a. a -> a
id
      cvalWidths :: Text -> [Int]
cvalWidths Text
kv = ((KeySpec, v) -> Int) -> [(KeySpec, v)] -> [Int]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length (String -> Int) -> ((KeySpec, v) -> String) -> (KeySpec, v) -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Doc Any -> String
forall a. Show a => a -> String
show (Doc Any -> String)
-> ((KeySpec, v) -> Doc Any) -> (KeySpec, v) -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. v -> Doc Any
forall a ann. Pretty a => a -> Doc ann
PP.pretty (v -> Doc Any) -> ((KeySpec, v) -> v) -> (KeySpec, v) -> Doc Any
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (KeySpec, v) -> v
forall a b. (a, b) -> b
snd) ([(KeySpec, v)] -> [Int]) -> [(KeySpec, v)] -> [Int]
forall a b. (a -> b) -> a -> b
$
                      ((KeySpec, v) -> Bool) -> [(KeySpec, v)] -> [(KeySpec, v)]
forall a. (a -> Bool) -> [a] -> [a]
L.filter ((KeySpec -> KeySpec -> Bool
forall a. Eq a => [a] -> [a] -> Bool
L.isSuffixOf (KeySpec
steppath KeySpec -> KeySpec -> KeySpec
forall a. Semigroup a => a -> a -> a
<> [(Text
key, Text
kv)])) (KeySpec -> Bool)
-> ((KeySpec, v) -> KeySpec) -> (KeySpec, v) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (KeySpec, v) -> KeySpec
forall a b. (a, b) -> a
fst) ([(KeySpec, v)] -> [(KeySpec, v)])
-> [(KeySpec, v)] -> [(KeySpec, v)]
forall a b. (a -> b) -> a -> b
$
                      KVITable v -> [Item (KVITable v)]
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 [Bool] -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
and [ RenderConfig -> Bool
hideBlankCols RenderConfig
cfg, [Int] -> Int
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Int]
cvw Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 ]
                    then Int
0
                    else [Int] -> Int
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum ([Int] -> Int) -> [Int] -> Int
forall a b. (a -> b) -> a -> b
$ Text -> Int
T.length Text
kv Int -> [Int] -> [Int]
forall a. a -> [a] -> [a]
: [Int]
cvw
      cwidths :: [Int]
cwidths = (Text -> Int) -> [Text] -> [Int]
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 (Int -> Int -> [Int]
forall a. Int -> a -> [a]
replicate ([Int] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Int]
cwidths) ([Int] -> Int
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 ([Int] -> FmtLine) -> [Int] -> FmtLine
forall a b. (a -> b) -> a -> b
$ [Int]
fmtcols) (Text -> FmtVal
TxtVal (Text -> FmtVal) -> [Text] -> [FmtVal]
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 ([Text] -> [Text]) -> [Text] -> [Text]
forall a b. (a -> b) -> a -> b
$ [Text] -> Maybe [Text] -> [Text]
forall a. a -> Maybe a -> a
fromMaybe [] (Maybe [Text] -> [Text]) -> Maybe [Text] -> [Text]
forall a b. (a -> b) -> a -> b
$ Text -> [(Text, [Text])] -> Maybe [Text]
forall a b. Eq a => a -> [(a, b)] -> Maybe b
L.lookup Text
key ([(Text, [Text])] -> Maybe [Text])
-> [(Text, [Text])] -> Maybe [Text]
forall a b. (a -> b) -> a -> b
$ KVITable v
t KVITable v
-> Getting [(Text, [Text])] (KVITable v) [(Text, [Text])]
-> [(Text, [Text])]
forall s a. s -> Getting a s a -> a
^. Getting [(Text, [Text])] (KVITable v) [(Text, [Text])]
forall v. Lens' (KVITable v) [(Text, [Text])]
keyVals
      ordering :: [Text] -> [Text]
ordering = if RenderConfig -> Bool
sortKeyVals RenderConfig
cfg then [Text] -> [Text]
sortWithNums else [Text] -> [Text]
forall a. a -> a
id
      subhdrsV :: Text -> [HeaderLine]
subhdrsV Text
v = RenderConfig -> KVITable v -> KeySpec -> [Text] -> [HeaderLine]
forall v.
Pretty v =>
RenderConfig -> KVITable v -> KeySpec -> [Text] -> [HeaderLine]
hdrvalstep RenderConfig
cfg KVITable v
t (KeySpec
steppath KeySpec -> KeySpec -> KeySpec
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 (Text -> (Int, [HeaderLine])) -> [Text] -> [(Int, [HeaderLine])]
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 (FmtLine -> Int)
-> ([HeaderLine] -> FmtLine) -> [HeaderLine] -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HeaderLine -> FmtLine
hdrFmt (HeaderLine -> FmtLine)
-> ([HeaderLine] -> HeaderLine) -> [HeaderLine] -> FmtLine
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [HeaderLine] -> HeaderLine
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 [Bool] -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
and [ RenderConfig -> Bool
hideBlankCols RenderConfig
cfg,
                                              FmtLine -> Bool
fmtEmptyCols (FmtLine -> Bool) -> FmtLine -> Bool
forall a b. (a -> b) -> a -> b
$ HeaderLine -> FmtLine
hdrFmt (HeaderLine -> FmtLine) -> HeaderLine -> FmtLine
forall a b. (a -> b) -> a -> b
$ [HeaderLine] -> HeaderLine
forall a. [a] -> a
head [HeaderLine]
sh
                                            ]
                                     then (a
0, Int
0)
                                     else (a
hl, Int
sv)
               in ((Int, [HeaderLine]) -> Int) -> [(Int, [HeaderLine])] -> [Int]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Int -> Int -> Int) -> (Int, Int) -> Int
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry Int -> Int -> Int
forall a. Ord a => a -> a -> a
max ((Int, Int) -> Int)
-> ((Int, [HeaderLine]) -> (Int, Int))
-> (Int, [HeaderLine])
-> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int, [HeaderLine]) -> (Int, Int)
forall a. Num a => (a, [HeaderLine]) -> (a, Int)
subW) [(Int, [HeaderLine])]
subTtlHdrs
      rsz_extsubhdrs :: [HeaderLine]
rsz_extsubhdrs = ([HeaderLine] -> HeaderLine) -> [[HeaderLine]] -> [HeaderLine]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [HeaderLine] -> HeaderLine
forall (t :: * -> *). Foldable t => t HeaderLine -> HeaderLine
hdrJoin ([[HeaderLine]] -> [HeaderLine]) -> [[HeaderLine]] -> [HeaderLine]
forall a b. (a -> b) -> a -> b
$
                       [[HeaderLine]] -> [[HeaderLine]]
forall a. [[a]] -> [[a]]
L.transpose ([[HeaderLine]] -> [[HeaderLine]])
-> [[HeaderLine]] -> [[HeaderLine]]
forall a b. (a -> b) -> a -> b
$
                       ((Int, [HeaderLine]) -> [HeaderLine])
-> [(Int, [HeaderLine])] -> [[HeaderLine]]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Int -> [HeaderLine] -> [HeaderLine])
-> (Int, [HeaderLine]) -> [HeaderLine]
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry Int -> [HeaderLine] -> [HeaderLine]
forall (f :: * -> *).
Functor f =>
Int -> f HeaderLine -> f HeaderLine
rsz_hdrstack) ([(Int, [HeaderLine])] -> [[HeaderLine]])
-> [(Int, [HeaderLine])] -> [[HeaderLine]]
forall a b. (a -> b) -> a -> b
$
                       [Int] -> [[HeaderLine]] -> [(Int, [HeaderLine])]
forall a b. [a] -> [b] -> [(a, b)]
zip [Int]
szhdrs ([[HeaderLine]] -> [(Int, [HeaderLine])])
-> [[HeaderLine]] -> [(Int, [HeaderLine])]
forall a b. (a -> b) -> a -> b
$ ((Int, [HeaderLine]) -> [HeaderLine])
-> [(Int, [HeaderLine])] -> [[HeaderLine]]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Int, [HeaderLine]) -> [HeaderLine]
forall a b. (a, b) -> b
snd [(Int, [HeaderLine])]
subTtlHdrs
      largest :: Int
largest = [Int] -> Int
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 Int -> Int -> [Int]
forall a. Int -> a -> [a]
replicate ([Text] -> Int
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 = (HeaderLine -> HeaderLine) -> f HeaderLine -> f HeaderLine
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 = (Int -> Bool) -> [Int] -> [Int]
forall a. (a -> Bool) -> [a] -> [a]
L.filter (Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
0) [Int]
c
            pcw :: Int
pcw = [Int] -> Int
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Int]
nzCols Int -> Int -> Int
forall a. Num a => a -> a -> a
+ ((Int
perColOvhd Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Int -> Int -> Int
forall a. Num a => a -> a -> a
* ([Int] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Int]
nzCols Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1))
            (Int
ew,Int
w0) = let l :: Int
l = [Int] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Int]
nzCols
                      in if Int
l Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 then (Int
0,Int
0)
                         else Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
0 (Int
hw Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
pcw) Int -> Int -> (Int, Int)
forall a. Integral a => a -> a -> (a, a)
`divMod` [Int] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Int]
nzCols
            c' :: [Int]
c' = ([Int], Int) -> [Int]
forall a b. (a, b) -> a
fst (([Int], Int) -> [Int]) -> ([Int], Int) -> [Int]
forall a b. (a -> b) -> a -> b
$ (([Int], Int) -> Int -> ([Int], Int))
-> ([Int], Int) -> [Int] -> ([Int], Int)
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl (\([Int]
c'',Int
n) Int
w -> ([Int]
c''[Int] -> [Int] -> [Int]
forall a. Semigroup a => a -> a -> a
<>[Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
w],Int
ew)) ([],Int
ewInt -> Int -> Int
forall 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 = (HeaderLine -> HeaderLine -> HeaderLine)
-> HeaderLine -> t HeaderLine -> HeaderLine
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]
c[Int] -> [Int] -> [Int]
forall a. Semigroup a => a -> a -> a
<>[Int]
c') Sigils
s Sigils
j) ([FmtVal]
v[FmtVal] -> [FmtVal] -> [FmtVal]
forall a. Semigroup a => a -> a -> a
<>[FmtVal]
v') Text
r
      tvals :: [FmtVal]
tvals = (Text -> FmtVal) -> [Text] -> [FmtVal]
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 HeaderLine -> [HeaderLine] -> [HeaderLine]
forall a. a -> [a] -> [a]
: [HeaderLine]
rsz_extsubhdrs

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