{-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedLists #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} module Text.Pandoc.Readers.Typst.Parsing ( P, PState(..), defaultPState, 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(..)) newtype PState = PState { sLabels :: [Text]} deriving (Show) defaultPState :: PState defaultPState = PState { sLabels = [] } type P m a = ParsecT [Content] PState m a -- state tracks a list of labels in the document pTok :: PandocMonad m => (Content -> Bool) -> P m Content pTok f = tokenPrim show showPos match where showPos _oldpos (Elt _ (Just pos) _) _ = pos showPos oldpos _ _ = oldpos match x | f x = Just x match _ = Nothing ignored :: PandocMonad m => Text -> P m () ignored msg = lift $ report $ IgnoredElement msg pWithContents :: PandocMonad m => P m a -> Seq Content -> P m a pWithContents pa cs = do inp <- getInput setInput $ F.toList cs res <- pa setInput inp pure res -- | Get field value from element, defaulting to VNone. getField :: (MonadFail m, MonadPlus m, FromVal a) => Identifier -> M.Map Identifier Val -> m a getField name fields = fromVal $ fromMaybe VNone $ M.lookup name fields -- | Split a list into chunks of a given size. The last chunk may be smaller. chunks :: Int -> [a] -> [[a]] chunks _ [] = [] chunks n xs = take n xs : chunks n (drop n xs)