{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedLists #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}

module Text.Pandoc.Readers.Typst.Parsing
  ( P,
    pTok,
    pWithContents,
    ignored,
    getField,
    chunks,
  )
where
import Control.Monad (MonadPlus)
import Control.Monad.Reader (lift)
import qualified Data.Foldable as F
import qualified Data.Map as M
import Data.Maybe (fromMaybe)
import Data.Sequence (Seq)
import Data.Text (Text)
import Text.Parsec
    ( ParsecT, getInput, setInput, tokenPrim )
import Typst.Types
    ( Identifier, Content(Elt), FromVal(..), Val(VNone) )
import Text.Pandoc.Class.PandocMonad ( PandocMonad, report )
import Text.Pandoc.Logging (LogMessage(..))

type P m a = ParsecT [Content] () m a

pTok :: PandocMonad m => (Content -> Bool) -> P m Content
pTok :: forall (m :: * -> *).
PandocMonad m =>
(Content -> Bool) -> P m Content
pTok Content -> Bool
f = forall s (m :: * -> *) t a u.
Stream s m t =>
(t -> String)
-> (SourcePos -> t -> s -> SourcePos)
-> (t -> Maybe a)
-> ParsecT s u m a
tokenPrim forall a. Show a => a -> String
show forall {p}. SourcePos -> Content -> p -> SourcePos
showPos Content -> Maybe Content
match
  where
    showPos :: SourcePos -> Content -> p -> SourcePos
showPos SourcePos
_oldpos (Elt Identifier
_ (Just SourcePos
pos) Map Identifier Val
_) p
_ = SourcePos
pos
    showPos SourcePos
oldpos Content
_ p
_ = SourcePos
oldpos
    match :: Content -> Maybe Content
match Content
x | Content -> Bool
f Content
x = forall a. a -> Maybe a
Just Content
x
    match Content
_ = forall a. Maybe a
Nothing

ignored :: PandocMonad m => Text -> P m ()
ignored :: forall (m :: * -> *). PandocMonad m => Text -> P m ()
ignored Text
msg = forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *). PandocMonad m => LogMessage -> m ()
report forall a b. (a -> b) -> a -> b
$ Text -> LogMessage
IgnoredElement Text
msg

pWithContents :: PandocMonad m => P m a -> Seq Content -> P m a
pWithContents :: forall (m :: * -> *) a.
PandocMonad m =>
P m a -> Seq Content -> P m a
pWithContents P m a
pa Seq Content
cs = do
  [Content]
inp <- forall (m :: * -> *) s u. Monad m => ParsecT s u m s
getInput
  forall (m :: * -> *) s u. Monad m => s -> ParsecT s u m ()
setInput forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a. Foldable t => t a -> [a]
F.toList Seq Content
cs
  a
res <- P m a
pa
  forall (m :: * -> *) s u. Monad m => s -> ParsecT s u m ()
setInput [Content]
inp
  forall (f :: * -> *) a. Applicative f => a -> f a
pure a
res

-- | Get field value from element, defaulting to VNone.
getField ::
  (MonadFail m, MonadPlus m, FromVal a) =>
  Identifier ->
  M.Map Identifier Val ->
  m a
getField :: forall (m :: * -> *) a.
(MonadFail m, MonadPlus m, FromVal a) =>
Identifier -> Map Identifier Val -> m a
getField Identifier
name Map Identifier Val
fields = forall a (m :: * -> *).
(FromVal a, MonadPlus m, MonadFail m) =>
Val -> m a
fromVal forall a b. (a -> b) -> a -> b
$ forall a. a -> Maybe a -> a
fromMaybe Val
VNone forall a b. (a -> b) -> a -> b
$ forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup Identifier
name Map Identifier Val
fields

-- | Split a list into chunks of a given size. The last chunk may be smaller.
chunks :: Int -> [a] -> [[a]]
chunks :: forall a. Int -> [a] -> [[a]]
chunks Int
_ [] = []
chunks Int
n [a]
xs = forall a. Int -> [a] -> [a]
take Int
n [a]
xs forall a. a -> [a] -> [a]
: forall a. Int -> [a] -> [[a]]
chunks Int
n (forall a. Int -> [a] -> [a]
drop Int
n [a]
xs)