{- Copyright (C) 2014-2016 Albert Krewinkel This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {- | Module : Text.Pandoc.Readers.Org.Options Copyright : Copyright (C) 2014-2016 Albert Krewinkel License : GNU GPL, version 2 or above Maintainer : Albert Krewinkel Org-mode parsing utilities. Most functions are simply re-exports from @Text.Pandoc.Parsing@, some functions are adapted to Org-mode specific functionality. -} module Text.Pandoc.Readers.Org.Parsing ( OrgParser , anyLine , blanklines , newline , parseFromString , skipSpaces1 , inList , withContext , getExportSetting , updateLastForbiddenCharPos , updateLastPreCharPos , orgArgKey , orgArgWord , orgArgWordChar -- * Re-exports from Text.Pandoc.Parser , ParserContext (..) , many1Till , notFollowedBy' , spaceChar , nonspaceChar , skipSpaces , blankline , enclosed , stringAnyCase , charsInBalanced , uri , withRaw , readWithM , guardEnabled , updateLastStrPos , notAfterString , ParserState (..) , registerHeader , QuoteContext (..) , singleQuoteStart , singleQuoteEnd , doubleQuoteStart , doubleQuoteEnd , dash , ellipses , citeKey -- * Re-exports from Text.Pandoc.Parsec , runParser , getInput , char , letter , digit , alphaNum , skipMany1 , spaces , anyChar , satisfy , string , count , eof , noneOf , oneOf , lookAhead , notFollowedBy , many , many1 , manyTill , (<|>) , () , choice , try , sepBy , sepBy1 , option , optional , optionMaybe , getState , updateState , SourcePos , getPosition ) where import Text.Pandoc.Readers.Org.ParserState import qualified Text.Pandoc.Parsing as P import Text.Pandoc.Parsing hiding ( anyLine, blanklines, newline , parseFromString ) import Control.Monad ( guard ) import Control.Monad.Reader ( Reader ) -- | The parser used to read org files. type OrgParser = ParserT [Char] OrgParserState (Reader OrgParserLocal) -- -- Adaptions and specializations of parsing utilities -- -- | Parse any line of text anyLine :: OrgParser String anyLine = P.anyLine <* updateLastPreCharPos <* updateLastForbiddenCharPos -- The version Text.Pandoc.Parsing cannot be used, as we need additional parts -- of the state saved and restored. parseFromString :: OrgParser a -> String -> OrgParser a parseFromString parser str' = do oldLastPreCharPos <- orgStateLastPreCharPos <$> getState updateState $ \s -> s{ orgStateLastPreCharPos = Nothing } result <- P.parseFromString parser str' updateState $ \s -> s{ orgStateLastPreCharPos = oldLastPreCharPos } return result -- | Skip one or more tab or space characters. skipSpaces1 :: OrgParser () skipSpaces1 = skipMany1 spaceChar -- | Like @Text.Parsec.Char.newline@, but causes additional state changes. newline :: OrgParser Char newline = P.newline <* updateLastPreCharPos <* updateLastForbiddenCharPos -- | Like @Text.Parsec.Char.blanklines@, but causes additional state changes. blanklines :: OrgParser [Char] blanklines = P.blanklines <* updateLastPreCharPos <* updateLastForbiddenCharPos -- | Succeeds when we're in list context. inList :: OrgParser () inList = do ctx <- orgStateParserContext <$> getState guard (ctx == ListItemState) -- | Parse in different context withContext :: ParserContext -- ^ New parser context -> OrgParser a -- ^ Parser to run in that context -> OrgParser a withContext context parser = do oldContext <- orgStateParserContext <$> getState updateState $ \s -> s{ orgStateParserContext = context } result <- parser updateState $ \s -> s{ orgStateParserContext = oldContext } return result -- -- Parser state functions -- -- | Get an export setting. getExportSetting :: (ExportSettings -> a) -> OrgParser a getExportSetting s = s . orgStateExportSettings <$> getState -- | Set the current position as the last position at which a forbidden char -- was found (i.e. a character which is not allowed at the inner border of -- markup). updateLastForbiddenCharPos :: OrgParser () updateLastForbiddenCharPos = getPosition >>= \p -> updateState $ \s -> s{ orgStateLastForbiddenCharPos = Just p} -- | Set the current parser position as the position at which a character was -- seen which allows inline markup to follow. updateLastPreCharPos :: OrgParser () updateLastPreCharPos = getPosition >>= \p -> updateState $ \s -> s{ orgStateLastPreCharPos = Just p} -- -- Org key-value parsing -- -- | Read the key of a plist style key-value list. orgArgKey :: OrgParser String orgArgKey = try $ skipSpaces *> char ':' *> many1 orgArgWordChar -- | Read the value of a plist style key-value list. orgArgWord :: OrgParser String orgArgWord = many1 orgArgWordChar -- | Chars treated as part of a word in plists. orgArgWordChar :: OrgParser Char orgArgWordChar = alphaNum <|> oneOf "-_"