{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
module Text.Pandoc.Readers.Org.ParserState
( OrgParserState (..)
, defaultOrgParserState
, OrgParserLocal (..)
, OrgNoteRecord
, Tag(..)
, HasReaderOptions (..)
, HasQuoteContext (..)
, HasMacros (..)
, TodoMarker (..)
, TodoSequence
, TodoState (..)
, activeTodoMarkers
, registerTodoSequence
, MacroExpander
, lookupMacro
, registerMacro
, F
, askF
, asksF
, trimInlinesF
, runF
, returnF
, ExportSettings (..)
, ArchivedTreesOption (..)
, optionsToParserState
) where
import Control.Monad.Reader (ReaderT, asks, local)
import Data.Default (Default (..))
import qualified Data.Map as M
import qualified Data.Set as Set
import Data.Text (Text)
import Text.Pandoc.Builder (Blocks)
import Text.Pandoc.Definition (Meta (..), nullMeta)
import Text.Pandoc.Logging
import Text.Pandoc.Options (ReaderOptions (..))
import Text.Pandoc.Parsing (Future, HasIdentifierList (..),
HasIncludeFiles (..), HasLastStrPosition (..),
HasLogMessages (..), HasMacros (..),
HasQuoteContext (..), HasReaderOptions (..),
ParserContext (..), QuoteContext (..), SourcePos,
askF, asksF, returnF, runF, trimInlinesF)
import Text.Pandoc.Readers.LaTeX.Types (Macro)
type F = Future OrgParserState
type OrgNoteRecord = (Text, F Blocks)
type OrgNoteTable = [OrgNoteRecord]
type OrgLinkFormatters = M.Map Text (Text -> Text)
type MacroExpander = [Text] -> Text
newtype Tag = Tag { fromTag :: Text }
deriving (Show, Eq, Ord)
data TodoState = Todo | Done
deriving (Eq, Ord, Show)
data TodoMarker = TodoMarker
{ todoMarkerState :: TodoState
, todoMarkerName :: Text
}
deriving (Show, Eq)
type TodoSequence = [TodoMarker]
data OrgParserState = OrgParserState
{ orgStateAnchorIds :: [Text]
, orgStateEmphasisCharStack :: [Char]
, orgStateEmphasisPreChars :: [Char]
, orgStateEmphasisPostChars :: [Char]
, orgStateEmphasisNewlines :: Maybe Int
, orgStateExcludeTags :: Set.Set Tag
, orgStateExcludeTagsChanged :: Bool
, orgStateExportSettings :: ExportSettings
, orgStateIdentifiers :: Set.Set Text
, orgStateIncludeFiles :: [Text]
, orgStateLastForbiddenCharPos :: Maybe SourcePos
, orgStateLastPreCharPos :: Maybe SourcePos
, orgStateLastStrPos :: Maybe SourcePos
, orgStateLinkFormatters :: OrgLinkFormatters
, orgStateMacros :: M.Map Text MacroExpander
, orgStateMacroDepth :: Int
, orgStateMeta :: F Meta
, orgStateNotes' :: OrgNoteTable
, orgStateOptions :: ReaderOptions
, orgStateParserContext :: ParserContext
, orgStateSelectTags :: Set.Set Tag
, orgStateSelectTagsChanged :: Bool
, orgStateTodoSequences :: [TodoSequence]
, orgStateTrimLeadBlkIndent :: Bool
, orgLogMessages :: [LogMessage]
, orgMacros :: M.Map Text Macro
}
data OrgParserLocal = OrgParserLocal
{ orgLocalQuoteContext :: QuoteContext
}
instance Default OrgParserLocal where
def = OrgParserLocal NoQuote
instance HasReaderOptions OrgParserState where
extractReaderOptions = orgStateOptions
instance HasLastStrPosition OrgParserState where
getLastStrPos = orgStateLastStrPos
setLastStrPos pos st = st{ orgStateLastStrPos = pos }
instance Monad m => HasQuoteContext st (ReaderT OrgParserLocal m) where
getQuoteContext = asks orgLocalQuoteContext
withQuoteContext q = local (\s -> s{orgLocalQuoteContext = q})
instance HasIdentifierList OrgParserState where
extractIdentifierList = orgStateIdentifiers
updateIdentifierList f s = s{ orgStateIdentifiers = f (orgStateIdentifiers s) }
instance HasLogMessages OrgParserState where
addLogMessage msg st = st{ orgLogMessages = msg : orgLogMessages st }
getLogMessages st = reverse $ orgLogMessages st
instance HasMacros OrgParserState where
extractMacros st = orgMacros st
updateMacros f st = st{ orgMacros = f (orgMacros st) }
instance HasIncludeFiles OrgParserState where
getIncludeFiles = orgStateIncludeFiles
addIncludeFile f st = st { orgStateIncludeFiles = f : orgStateIncludeFiles st }
dropLatestIncludeFile st =
st { orgStateIncludeFiles = drop 1 $ orgStateIncludeFiles st }
instance Default OrgParserState where
def = defaultOrgParserState
defaultOrgParserState :: OrgParserState
defaultOrgParserState = OrgParserState
{ orgStateAnchorIds = []
, orgStateEmphasisPreChars = "-\t ('\"{"
, orgStateEmphasisPostChars = "-\t\n .,:!?;'\")}["
, orgStateEmphasisCharStack = []
, orgStateEmphasisNewlines = Nothing
, orgStateExportSettings = def
, orgStateExcludeTags = Set.singleton $ Tag "noexport"
, orgStateExcludeTagsChanged = False
, orgStateIdentifiers = Set.empty
, orgStateIncludeFiles = []
, orgStateLastForbiddenCharPos = Nothing
, orgStateLastPreCharPos = Nothing
, orgStateLastStrPos = Nothing
, orgStateLinkFormatters = M.empty
, orgStateMacros = M.empty
, orgStateMacroDepth = 0
, orgStateMeta = return nullMeta
, orgStateNotes' = []
, orgStateOptions = def
, orgStateParserContext = NullState
, orgStateSelectTags = Set.singleton $ Tag "export"
, orgStateSelectTagsChanged = False
, orgStateTrimLeadBlkIndent = True
, orgStateTodoSequences = []
, orgLogMessages = []
, orgMacros = M.empty
}
optionsToParserState :: ReaderOptions -> OrgParserState
optionsToParserState opts =
def { orgStateOptions = opts }
registerTodoSequence :: TodoSequence -> OrgParserState -> OrgParserState
registerTodoSequence todoSeq st =
let curSeqs = orgStateTodoSequences st
in st{ orgStateTodoSequences = todoSeq : curSeqs }
activeTodoSequences :: OrgParserState -> [TodoSequence]
activeTodoSequences st =
let curSeqs = orgStateTodoSequences st
in if null curSeqs
then [[ TodoMarker Todo "TODO" , TodoMarker Done "DONE" ]]
else curSeqs
activeTodoMarkers :: OrgParserState -> TodoSequence
activeTodoMarkers = concat . activeTodoSequences
lookupMacro :: Text -> OrgParserState -> Maybe MacroExpander
lookupMacro macroName = M.lookup macroName . orgStateMacros
registerMacro :: (Text, MacroExpander) -> OrgParserState -> OrgParserState
registerMacro (name, expander) st =
let curMacros = orgStateMacros st
in st{ orgStateMacros = M.insert name expander curMacros }
data ArchivedTreesOption =
ArchivedTreesExport
| ArchivedTreesNoExport
| ArchivedTreesHeadlineOnly
data ExportSettings = ExportSettings
{ exportArchivedTrees :: ArchivedTreesOption
, exportDrawers :: Either [Text] [Text]
, exportEmphasizedText :: Bool
, exportHeadlineLevels :: Int
, exportPreserveBreaks :: Bool
, exportSmartQuotes :: Bool
, exportSpecialStrings :: Bool
, exportSubSuperscripts :: Bool
, exportWithAuthor :: Bool
, exportWithCreator :: Bool
, exportWithEmail :: Bool
, exportWithPlanning :: Bool
, exportWithTags :: Bool
, exportWithTodoKeywords :: Bool
}
instance Default ExportSettings where
def = defaultExportSettings
defaultExportSettings :: ExportSettings
defaultExportSettings = ExportSettings
{ exportArchivedTrees = ArchivedTreesHeadlineOnly
, exportDrawers = Left ["LOGBOOK"]
, exportEmphasizedText = True
, exportHeadlineLevels = 3
, exportPreserveBreaks = False
, exportSmartQuotes = False
, exportSpecialStrings = True
, exportSubSuperscripts = True
, exportWithAuthor = True
, exportWithCreator = True
, exportWithEmail = True
, exportWithPlanning = False
, exportWithTags = True
, exportWithTodoKeywords = True
}