{-# LANGUAGE DerivingStrategies         #-}
{-# LANGUAGE FlexibleContexts           #-}
{-# LANGUAGE LambdaCase                 #-}
{-# LANGUAGE RankNTypes                 #-}
{- |
Module      : Text.GridTable
Copyright   : © 2022 Albert Krewinkel
License     : MIT
Maintainer  : Albert Krewinkel <albert@zeitkraut.de>

Parse reStructuredText-style grid tables.
-}

module Text.GridTable
  ( module Text.GridTable.ArrayTable
    -- * Parse from character stream
  , gridTable
    -- * List-based representation
  , Cell (..)
  , rows
  ) where

import Prelude hiding (lines)
import Data.Array (Array, elems, bounds)
import Data.Bifunctor (bimap)
import Data.Maybe (mapMaybe)
import Text.GridTable.ArrayTable
import Text.GridTable.Parse (gridTable)

colBounds :: Array CellIndex a -> (ColIndex, ColIndex)
colBounds :: forall a. Array CellIndex a -> (ColIndex, ColIndex)
colBounds = forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap forall a b. (a, b) -> b
snd forall a b. (a, b) -> b
snd forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall i e. Array i e -> (i, i)
bounds

-- | Returns the rows of a grid table as lists of simple cells.
rows :: ArrayTable a -> [[Cell a]]
rows :: forall a. ArrayTable a -> [[Cell a]]
rows ArrayTable a
gt =
  let tarr :: Array CellIndex (GridCell a)
tarr = forall a. ArrayTable a -> Array CellIndex (GridCell a)
arrayTableCells ArrayTable a
gt
      ncols :: Int
ncols = ColIndex -> Int
fromColIndex forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry (forall a b c. (a -> b -> c) -> b -> a -> c
flip (-)) forall a b. (a -> b) -> a -> b
$ forall a. Array CellIndex a -> (ColIndex, ColIndex)
colBounds Array CellIndex (GridCell a)
tarr
      toSimpleCell :: GridCell a -> Maybe (Cell a)
toSimpleCell = \case
        ContentCell RowSpan
rs ColSpan
cs a
c -> forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall a. a -> RowSpan -> ColSpan -> Cell a
Cell a
c RowSpan
rs ColSpan
cs
        ContinuationCell {} -> forall a. Maybe a
Nothing
      mkRows :: [[Cell a]] -> [GridCell a] -> [[Cell a]]
      mkRows :: forall a. [[Cell a]] -> [GridCell a] -> [[Cell a]]
mkRows [[Cell a]]
rs = \case
        [] -> forall a. [a] -> [a]
reverse [[Cell a]]
rs
        [GridCell a]
xs -> let ([GridCell a]
r, [GridCell a]
xs') = forall a. Int -> [a] -> ([a], [a])
splitAt (Int
ncols forall a. Num a => a -> a -> a
+ Int
1) [GridCell a]
xs
              in forall a. [[Cell a]] -> [GridCell a] -> [[Cell a]]
mkRows (forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe forall {a}. GridCell a -> Maybe (Cell a)
toSimpleCell [GridCell a]
rforall a. a -> [a] -> [a]
:[[Cell a]]
rs) [GridCell a]
xs'
  in forall a. [[Cell a]] -> [GridCell a] -> [[Cell a]]
mkRows [] forall a b. (a -> b) -> a -> b
$ forall i e. Array i e -> [e]
elems Array CellIndex (GridCell a)
tarr

-- | Raw grid table cell
data Cell a = Cell
  { forall a. Cell a -> a
cellContent :: a
  , forall a. Cell a -> RowSpan
cellRowSpan :: RowSpan
  , forall a. Cell a -> ColSpan
cellColSpan :: ColSpan
  }
  deriving stock (Cell a -> Cell a -> Bool
forall a. Eq a => Cell a -> Cell a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Cell a -> Cell a -> Bool
$c/= :: forall a. Eq a => Cell a -> Cell a -> Bool
== :: Cell a -> Cell a -> Bool
$c== :: forall a. Eq a => Cell a -> Cell a -> Bool
Eq, Cell a -> Cell a -> Bool
Cell a -> Cell a -> Ordering
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall {a}. Ord a => Eq (Cell a)
forall a. Ord a => Cell a -> Cell a -> Bool
forall a. Ord a => Cell a -> Cell a -> Ordering
forall a. Ord a => Cell a -> Cell a -> Cell a
min :: Cell a -> Cell a -> Cell a
$cmin :: forall a. Ord a => Cell a -> Cell a -> Cell a
max :: Cell a -> Cell a -> Cell a
$cmax :: forall a. Ord a => Cell a -> Cell a -> Cell a
>= :: Cell a -> Cell a -> Bool
$c>= :: forall a. Ord a => Cell a -> Cell a -> Bool
> :: Cell a -> Cell a -> Bool
$c> :: forall a. Ord a => Cell a -> Cell a -> Bool
<= :: Cell a -> Cell a -> Bool
$c<= :: forall a. Ord a => Cell a -> Cell a -> Bool
< :: Cell a -> Cell a -> Bool
$c< :: forall a. Ord a => Cell a -> Cell a -> Bool
compare :: Cell a -> Cell a -> Ordering
$ccompare :: forall a. Ord a => Cell a -> Cell a -> Ordering
Ord, Int -> Cell a -> ShowS
forall a. Show a => Int -> Cell a -> ShowS
forall a. Show a => [Cell a] -> ShowS
forall a. Show a => Cell a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Cell a] -> ShowS
$cshowList :: forall a. Show a => [Cell a] -> ShowS
show :: Cell a -> String
$cshow :: forall a. Show a => Cell a -> String
showsPrec :: Int -> Cell a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> Cell a -> ShowS
Show)