git.iko.soy/typeable/pandoc
on master help sign in
Org reader: introduce Reader environment around Blocks/Inlines

This introduces a Reader environment in the style of Text.Pandoc.Parsing.F, but adapted to the Org reader parser.

commit92582c6272a3a171c406699e46e88afc4835d85c authorAlbert Krewinkel <tarleb@moltkeplatz.de> dateWed 16 Apr 2014, 11:58 (13 years ago) parent5fc2522
1 file changed+176−130
src/Text/Pandoc/Readers/Org.hs+176−130
src/Text/Pandoc/Readers/Org.hs+176−130
@@ -1,4 +1,5 @@
11{-# LANGUAGE OverloadedStrings #-}
2+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
23{-
34Copyright (C) 2014 Albert Krewinkel <tarleb@moltkeplatz.de>
45
@@ -29,21 +30,26 @@ Conversion of org-mode formatted plain text to 'Pandoc' document.
2930module Text.Pandoc.Readers.Org ( readOrg ) where
3031
3132import qualified Text.Pandoc.Builder as B
32−import Text.Pandoc.Builder (Inlines, Blocks, trimInlines, (<>), HasMeta(..))
33+import Text.Pandoc.Builder ( Inlines, Blocks, HasMeta(..), (<>)
34+ , trimInlines )
3335import Text.Pandoc.Definition
3436import Text.Pandoc.Options
3537import qualified Text.Pandoc.Parsing as P
36−import Text.Pandoc.Parsing hiding (newline, orderedListMarker, updateLastStrPos)
38+import Text.Pandoc.Parsing hiding ( F, unF, askF, asksF, runF
39+ , newline, orderedListMarker
40+ , updateLastStrPos )
3741import Text.Pandoc.Shared (compactify')
3842
39−import Control.Applicative (pure, (<$>), (<$), (<*>), (<*), (*>), (<**>))
43+import Control.Applicative ( Applicative, pure
44+ , (<$>), (<$), (<*>), (<*), (*>), (<**>) )
4045import Control.Arrow ((***))
41−import Control.Monad (guard, when)
46+import Control.Monad (foldM, guard, liftM, liftM2, when)
47+import Control.Monad.Reader (Reader, runReader)
4248import Data.Char (toLower)
4349import Data.Default
44−import Data.List (foldl', isPrefixOf, isSuffixOf)
50+import Data.List (isPrefixOf, isSuffixOf)
4551import Data.Maybe (listToMaybe, fromMaybe)
46−import Data.Monoid (mconcat, mempty, mappend)
52+import Data.Monoid (Monoid, mconcat, mempty, mappend)
4753
4854-- | Parse org-mode string and return a Pandoc document.
4955readOrg :: ReaderOptions -- ^ Reader options
@@ -55,10 +61,10 @@ type OrgParser = Parser [Char] OrgParserState
5561
5662parseOrg:: OrgParser Pandoc
5763parseOrg = do
58− blocks' <- B.toList <$> parseBlocks
64+ blocks' <- parseBlocks
5965 st <- getState
60− let meta = orgStateMeta st
61− return $ Pandoc meta $ filter (/= Null) blocks'
66+ let meta = runF (orgStateMeta' st) st
67+ return $ Pandoc meta $ filter (/= Null) (B.toList $ runF blocks' st)
6268
6369--
6470-- Parser State for Org
@@ -73,7 +79,8 @@ data OrgParserState = OrgParserState
7379 , orgStateLastPreCharPos :: Maybe SourcePos
7480 , orgStateLastStrPos :: Maybe SourcePos
7581 , orgStateMeta :: Meta
76− } deriving (Show)
82+ , orgStateMeta' :: F Meta
83+ }
7784
7885instance HasReaderOptions OrgParserState where
7986 extractReaderOptions = orgStateOptions
@@ -96,6 +103,7 @@ defaultOrgParserState = OrgParserState
96103 , orgStateLastPreCharPos = Nothing
97104 , orgStateLastStrPos = Nothing
98105 , orgStateMeta = nullMeta
106+ , orgStateMeta' = return nullMeta
99107 }
100108
101109updateLastStrPos :: OrgParser ()
@@ -138,6 +146,27 @@ resetEmphasisNewlines :: OrgParser ()
138146resetEmphasisNewlines = updateState $ \s ->
139147 s{ orgStateEmphasisNewlines = Nothing }
140148
149+
150+--
151+-- Adaptions and specializations of parsing utilities
152+--
153+
154+newtype F a = F { unF :: Reader OrgParserState a
155+ } deriving (Monad, Applicative, Functor)
156+
157+runF :: F a -> OrgParserState -> a
158+runF = runReader . unF
159+
160+instance Monoid a => Monoid (F a) where
161+ mempty = return mempty
162+ mappend = liftM2 mappend
163+ mconcat = fmap mconcat . sequence
164+
165+trimInlinesF :: F Inlines -> F Inlines
166+trimInlinesF = liftM trimInlines
167+
168+
169+-- | Like @Text.Parsec.Char.newline@, but causes additional state changes.
141170newline :: OrgParser Char
142171newline =
143172 P.newline
@@ -148,10 +177,10 @@ newline =
148177-- parsing blocks
149178--
150179
151−parseBlocks :: OrgParser Blocks
180+parseBlocks :: OrgParser (F Blocks)
152181parseBlocks = mconcat <$> manyTill block eof
153182
154−block :: OrgParser Blocks
183+block :: OrgParser (F Blocks)
155184block = choice [ mempty <$ blanklines
156185 , orgBlock
157186 , example
@@ -159,7 +188,7 @@ block = choice [ mempty <$ blanklines
159188 , figure
160189 , specialLine
161190 , header
162− , hline
191+ , return <$> hline
163192 , list
164193 , table
165194 , paraOrPlain
@@ -169,15 +198,15 @@ block = choice [ mempty <$ blanklines
169198-- Org Blocks (#+BEGIN_... / #+END_...)
170199--
171200
172−orgBlock :: OrgParser Blocks
201+orgBlock :: OrgParser (F Blocks)
173202orgBlock = try $ do
174203 (indent, blockType, args) <- blockHeader
175204 blockStr <- rawBlockContent indent blockType
176205 let classArgs = [ translateLang . fromMaybe [] $ listToMaybe args ]
177206 case blockType of
178207 "comment" -> return mempty
179− "src" -> return $ B.codeBlockWith ("", classArgs, []) blockStr
180− _ -> B.divWith ("", [blockType], [])
208+ "src" -> return . return $ B.codeBlockWith ("", classArgs, []) blockStr
209+ _ -> fmap (B.divWith ("", [blockType], []))
181210 <$> parseFromString parseBlocks blockStr
182211
183212blockHeader :: OrgParser (Int, String, [String])
@@ -222,15 +251,16 @@ commaEscaped (',':cs@('*':_)) = cs
222251commaEscaped (',':cs@('#':'+':_)) = cs
223252commaEscaped cs = cs
224253
225−example :: OrgParser Blocks
226−example = try $
227− B.codeBlockWith ("", ["example"], []) . unlines <$> many1 exampleLine
254+example :: OrgParser (F Blocks)
255+example = try $ do
256+ body <- unlines <$> many1 exampleLine
257+ return . return $ B.codeBlockWith ("", ["example"], []) body
228258
229259exampleLine :: OrgParser String
230260exampleLine = try $ string ": " *> anyLine
231261
232262-- Drawers for properties or a logbook
233−drawer :: OrgParser Blocks
263+drawer :: OrgParser (F Blocks)
234264drawer = try $ do
235265 drawerStart
236266 manyTill drawerLine (try drawerEnd)
@@ -256,18 +286,20 @@ drawerEnd = try $
256286--
257287
258288-- Figures (Image on a line by itself, preceded by name and/or caption)
259−figure :: OrgParser Blocks
289+figure :: OrgParser (F Blocks)
260290figure = try $ do
261291 (tit, cap) <- (maybe mempty withFigPrefix *** fromMaybe mempty)
262292 <$> nameAndOrCaption
263293 src <- skipSpaces *> selfTarget <* skipSpaces <* newline
264294 guard (isImageFilename src)
265− return . B.para $ B.image src tit cap
295+ return $ do
296+ cap' <- cap
297+ return $ B.para $ B.image src tit cap'
266298 where withFigPrefix cs = if "fig:" `isPrefixOf` cs
267299 then cs
268300 else "fig:" ++ cs
269301
270−nameAndOrCaption :: OrgParser (Maybe String, Maybe Inlines)
302+nameAndOrCaption :: OrgParser (Maybe String, Maybe (F Inlines))
271303nameAndOrCaption = try $ nameFirst <|> captionFirst
272304 where
273305 nameFirst = try $ do
@@ -279,7 +311,7 @@ nameAndOrCaption = try $ nameFirst <|> captionFirst
279311 n <- optionMaybe name
280312 return (n, Just c)
281313
282−caption :: OrgParser Inlines
314+caption :: OrgParser (F Inlines)
283315caption = try $ annotation "CAPTION" *> inlinesTillNewline
284316
285317name :: OrgParser String
@@ -289,8 +321,8 @@ annotation :: String -> OrgParser String
289321annotation ann = try $ metaLineStart *> stringAnyCase ann <* char ':'
290322
291323-- Comments, Options and Metadata
292−specialLine :: OrgParser Blocks
293−specialLine = try $ metaLine <|> commentLine
324+specialLine :: OrgParser (F Blocks)
325+specialLine = fmap return . try $ metaLine <|> commentLine
294326
295327metaLine :: OrgParser Blocks
296328metaLine = try $ metaLineStart *> declarationLine
@@ -308,12 +340,15 @@ commentLineStart = try $ mappend <$> many spaceChar <*> string "# "
308340
309341declarationLine :: OrgParser Blocks
310342declarationLine = try $ do
311− meta' <- B.setMeta <$> metaKey <*> metaValue <*> pure nullMeta
312− updateState $ \st -> st { orgStateMeta = orgStateMeta st <> meta' }
343+ key <- metaKey
344+ inlinesF <- metaInlines
345+ updateState $ \st ->
346+ let meta' = B.setMeta <$> pure key <*> inlinesF <*> pure nullMeta
347+ in st { orgStateMeta' = orgStateMeta' st <> meta' }
313348 return mempty
314349
315−metaValue :: OrgParser MetaValue
316−metaValue = MetaInlines . B.toList <$> inlinesTillNewline
350+metaInlines :: OrgParser (F MetaValue)
351+metaInlines = fmap (MetaInlines . B.toList) <$> inlinesTillNewline
317352
318353metaKey :: OrgParser String
319354metaKey = map toLower <$> many1 (noneOf ": \n\r")
@@ -321,16 +356,20 @@ metaKey = map toLower <$> many1 (noneOf ": \n\r")
321356 <* skipSpaces
322357
323358-- | Headers
324−header :: OrgParser Blocks
325−header = try $
326− B.header <$> headerStart
327− <*> inlinesTillNewline
359+header :: OrgParser (F Blocks)
360+header = try $ do
361+ level <- headerStart
362+ title <- inlinesTillNewline
363+ return $ B.header level <$> title
328364
329365headerStart :: OrgParser Int
330366headerStart = try $
331367 (length <$> many1 (char '*')) <* many1 (char ' ')
332368
333−-- Horizontal Line (five dashes or more)
369+-- Don't use (or need) the reader wrapper here, we want hline to be
370+-- @show@able. Otherwise we can't use it with @notFollowedBy'@.
371+
372+-- | Horizontal Line (five -- dashes or more)
334373hline :: OrgParser Blocks
335374hline = try $ do
336375 skipSpaces
@@ -344,22 +383,23 @@ hline = try $ do
344383-- Tables
345384--
346385
347−data OrgTableRow = OrgContentRow [Blocks]
386+data OrgTableRow = OrgContentRow (F [Blocks])
348387 | OrgAlignRow [Alignment]
349388 | OrgHlineRow
350− deriving (Eq, Show)
351389
352390data OrgTable = OrgTable
353391 { orgTableColumns :: Int
354392 , orgTableAlignments :: [Alignment]
355393 , orgTableHeader :: [Blocks]
356394 , orgTableRows :: [[Blocks]]
357− } deriving (Eq, Show)
395+ }
358396
359−table :: OrgParser Blocks
397+table :: OrgParser (F Blocks)
360398table = try $ do
361399 lookAhead tableStart
362− orgToPandocTable . normalizeTable . rowsToTable <$> tableRows
400+ do
401+ rows <- tableRows
402+ return $ return . orgToPandocTable . normalizeTable =<< rowsToTable rows
363403
364404orgToPandocTable :: OrgTable
365405 -> Blocks
@@ -374,11 +414,11 @@ tableRows = try $ many (tableAlignRow <|> tableHline <|> tableContentRow)
374414
375415tableContentRow :: OrgParser OrgTableRow
376416tableContentRow = try $
377− OrgContentRow <$> (tableStart *> manyTill tableContentCell newline)
417+ OrgContentRow . sequence <$> (tableStart *> manyTill tableContentCell newline)
378418
379−tableContentCell :: OrgParser Blocks
419+tableContentCell :: OrgParser (F Blocks)
380420tableContentCell = try $
381− B.plain . trimInlines . mconcat <$> many1Till inline endOfCell
421+ fmap B.plain . trimInlinesF . mconcat <$> many1Till inline endOfCell
382422
383423endOfCell :: OrgParser Char
384424endOfCell = try $ char '|' <|> lookAhead newline
@@ -410,8 +450,8 @@ tableHline = try $
410450 OrgHlineRow <$ (tableStart *> char '-' *> anyLine)
411451
412452rowsToTable :: [OrgTableRow]
413− -> OrgTable
414−rowsToTable = foldl' (flip rowToContent) zeroTable
453+ -> F OrgTable
454+rowsToTable = foldM (flip rowToContent) zeroTable
415455 where zeroTable = OrgTable 0 mempty mempty mempty
416456
417457normalizeTable :: OrgTable
@@ -430,57 +470,64 @@ normalizeTable (OrgTable cols aligns heads lns) =
430470-- line as a header. All other horizontal lines are discarded.
431471rowToContent :: OrgTableRow
432472 -> OrgTable
433− -> OrgTable
434−rowToContent OrgHlineRow = maybeBodyToHeader
435−rowToContent (OrgContentRow rs) = setLongestRow rs . appendToBody rs
436−rowToContent (OrgAlignRow as) = setLongestRow as . setAligns as
473+ -> F OrgTable
474+rowToContent OrgHlineRow t = maybeBodyToHeader t
475+rowToContent (OrgAlignRow as) t = setLongestRow as =<< setAligns as t
476+rowToContent (OrgContentRow rf) t = do
477+ rs <- rf
478+ setLongestRow rs =<< appendToBody rs t
437479
438480setLongestRow :: [a]
439481 -> OrgTable
440− -> OrgTable
441−setLongestRow rs t = t{ orgTableColumns = max (length rs) (orgTableColumns t) }
482+ -> F OrgTable
483+setLongestRow rs t =
484+ return t{ orgTableColumns = max (length rs) (orgTableColumns t) }
442485
443486maybeBodyToHeader :: OrgTable
444− -> OrgTable
487+ -> F OrgTable
445488maybeBodyToHeader t = case t of
446489 OrgTable{ orgTableHeader = [], orgTableRows = b:[] } ->
447− t{ orgTableHeader = b , orgTableRows = [] }
448− _ -> t
490+ return t{ orgTableHeader = b , orgTableRows = [] }
491+ _ -> return t
449492
450493appendToBody :: [Blocks]
451494 -> OrgTable
452− -> OrgTable
453−appendToBody r t = t{ orgTableRows = orgTableRows t ++ [r] }
495+ -> F OrgTable
496+appendToBody r t = return t{ orgTableRows = orgTableRows t ++ [r] }
454497
455498setAligns :: [Alignment]
456499 -> OrgTable
457− -> OrgTable
458−setAligns aligns t = t{ orgTableAlignments = aligns }
500+ -> F OrgTable
501+setAligns aligns t = return $ t{ orgTableAlignments = aligns }
459502
460503-- Paragraphs or Plain text
461−paraOrPlain :: OrgParser Blocks
504+paraOrPlain :: OrgParser (F Blocks)
462505paraOrPlain = try $
463− parseInlines <**> option B.plain (try $ newline *> pure B.para)
506+ parseInlines <**> (fmap <$> option B.plain (try $ newline *> pure B.para))
464507
465−inlinesTillNewline :: OrgParser Inlines
466−inlinesTillNewline = trimInlines . mconcat <$> manyTill inline newline
508+inlinesTillNewline :: OrgParser (F Inlines)
509+inlinesTillNewline = trimInlinesF . mconcat <$> manyTill inline newline
467510
468511
469512--
470513-- list blocks
471514--
472515
473−list :: OrgParser Blocks
516+list :: OrgParser (F Blocks)
474517list = choice [ definitionList, bulletList, orderedList ] <?> "list"
475518
476−definitionList :: OrgParser Blocks
477−definitionList = B.definitionList <$> many1 (definitionListItem bulletListStart)
519+definitionList :: OrgParser (F Blocks)
520+definitionList = fmap B.definitionList . sequence
521+ <$> many1 (definitionListItem bulletListStart)
478522
479−bulletList :: OrgParser Blocks
480−bulletList = B.bulletList . compactify' <$> many1 (listItem bulletListStart)
523+bulletList :: OrgParser (F Blocks)
524+bulletList = fmap B.bulletList . fmap compactify' . sequence
525+ <$> many1 (listItem bulletListStart)
481526
482−orderedList :: OrgParser Blocks
483−orderedList = B.orderedList . compactify' <$> many1 (listItem orderedListStart)
527+orderedList :: OrgParser (F Blocks)
528+-- orderedList = B.orderedList . compactify' <$> many1 (listItem orderedListStart)
529+orderedList = fmap B.orderedList . fmap compactify' . sequence
530+ <$> many1 (listItem orderedListStart)
484531
485532genericListStart :: OrgParser String
486533 -> OrgParser Int
@@ -499,7 +546,7 @@ orderedListStart = genericListStart orderedListMarker
499546 where orderedListMarker = mappend <$> many1 digit <*> (pure <$> oneOf ".)")
500547
501548definitionListItem :: OrgParser Int
502− -> OrgParser (Inlines, [Blocks])
549+ -> OrgParser (F (Inlines, [Blocks]))
503550definitionListItem parseMarkerGetLength = try $ do
504551 markerLength <- parseMarkerGetLength
505552 term <- manyTill (noneOf "\n\r") (try $ string "::")
@@ -507,12 +554,12 @@ definitionListItem parseMarkerGetLength = try $ do
507554 cont <- concat <$> many (listContinuation markerLength)
508555 term' <- parseFromString inline term
509556 contents' <- parseFromString parseBlocks $ first ++ cont
510− return (term', [contents'])
557+ return $ (,) <$> term' <*> fmap (:[]) contents'
511558
512559
513560-- parse raw text for one list item, excluding start marker and continuations
514561listItem :: OrgParser Int
515− -> OrgParser Blocks
562+ -> OrgParser (F Blocks)
516563listItem start = try $ do
517564 markerLength <- try start
518565 firstLine <- anyLineNewline
@@ -536,11 +583,11 @@ anyLineNewline = (++ "\n") <$> anyLine
536583-- inline
537584--
538585
539−inline :: OrgParser Inlines
586+inline :: OrgParser (F Inlines)
540587inline =
541588 choice [ whitespace
542589 , linebreak
543− , link
590+ , linkOrImage
544591 , str
545592 , endline
546593 , emph
@@ -557,29 +604,29 @@ inline =
557604 ] <* (guard =<< newlinesCountWithinLimits)
558605 <?> "inline"
559606
560−parseInlines :: OrgParser Inlines
561−parseInlines = trimInlines . mconcat <$> many1 inline
607+parseInlines :: OrgParser (F Inlines)
608+parseInlines = trimInlinesF . mconcat <$> many1 inline
562609
563610-- treat these as potentially non-text when parsing inline:
564611specialChars :: [Char]
565612specialChars = "\"$'()*+-./:<=>[\\]^_{|}~"
566613
567614
568−whitespace :: OrgParser Inlines
569−whitespace = B.space <$ skipMany1 spaceChar
570− <* updateLastPreCharPos
571− <* updateLastForbiddenCharPos
615+whitespace :: OrgParser (F Inlines)
616+whitespace = pure B.space <$ skipMany1 spaceChar
617+ <* updateLastPreCharPos
618+ <* updateLastForbiddenCharPos
572619 <?> "whitespace"
573620
574−linebreak :: OrgParser Inlines
575−linebreak = try $ B.linebreak <$ string "\\\\" <* skipSpaces <* newline
621+linebreak :: OrgParser (F Inlines)
622+linebreak = try $ pure B.linebreak <$ string "\\\\" <* skipSpaces <* newline
576623
577−str :: OrgParser Inlines
578−str = B.str <$> many1 (noneOf $ specialChars ++ "\n\r ")
579− <* updateLastStrPos
624+str :: OrgParser (F Inlines)
625+str = return . B.str <$> many1 (noneOf $ specialChars ++ "\n\r ")
626+ <* updateLastStrPos
580627
581628-- an endline character that can be treated as a space, not a structural break
582−endline :: OrgParser Inlines
629+endline :: OrgParser (F Inlines)
583630endline = try $ do
584631 newline
585632 notFollowedBy blankline
@@ -595,29 +642,29 @@ endline = try $ do
595642 decEmphasisNewlinesCount
596643 guard =<< newlinesCountWithinLimits
597644 updateLastPreCharPos
598− return B.space
645+ return . return $ B.space
599646
600−link :: OrgParser Inlines
601−link = explicitOrImageLink <|> selflinkOrImage <?> "link"
647+linkOrImage :: OrgParser (F Inlines)
648+linkOrImage = explicitOrImageLink <|> selflinkOrImage <?> "link or image"
602649
603−explicitOrImageLink :: OrgParser Inlines
650+explicitOrImageLink :: OrgParser (F Inlines)
604651explicitOrImageLink = try $ do
605652 char '['
606653 src <- linkTarget
607654 title <- enclosedRaw (char '[') (char ']')
608655 title' <- parseFromString (mconcat <$> many inline) title
609656 char ']'
610− return . B.link src ""
611− $ if isImageFilename src && isImageFilename title
612− then B.image title "" ""
613− else title'
657+ return $ B.link src "" <$>
658+ if isImageFilename src && isImageFilename title
659+ then return $ B.image title mempty mempty
660+ else title'
614661
615−selflinkOrImage :: OrgParser Inlines
662+selflinkOrImage :: OrgParser (F Inlines)
616663selflinkOrImage = try $ do
617664 src <- char '[' *> linkTarget <* char ']'
618− return $ if isImageFilename src
619− then B.image src "" ""
620− else B.link src "" (B.str src)
665+ return . return $ if isImageFilename src
666+ then B.image src "" ""
667+ else B.link src "" (B.str src)
621668
622669selfTarget :: OrgParser String
623670selfTarget = try $ char '[' *> linkTarget <* char ']'
@@ -634,51 +681,50 @@ isImageFilename filename =
634681 imageExtensions = [ "jpeg" , "jpg" , "png" , "gif" , "svg" ]
635682 protocols = [ "file", "http", "https" ]
636683
637−emph :: OrgParser Inlines
638−emph = B.emph <$> emphasisBetween '/'
684+emph :: OrgParser (F Inlines)
685+emph = fmap B.emph <$> emphasisBetween '/'
639686
640−strong :: OrgParser Inlines
641−strong = B.strong <$> emphasisBetween '*'
687+strong :: OrgParser (F Inlines)
688+strong = fmap B.strong <$> emphasisBetween '*'
642689
643−strikeout :: OrgParser Inlines
644−strikeout = B.strikeout <$> emphasisBetween '+'
690+strikeout :: OrgParser (F Inlines)
691+strikeout = fmap B.strikeout <$> emphasisBetween '+'
645692
646693-- There is no underline, so we use strong instead.
647−underline :: OrgParser Inlines
648−underline = B.strong <$> emphasisBetween '_'
649−
650−code :: OrgParser Inlines
651−code = B.code <$> verbatimBetween '='
694+underline :: OrgParser (F Inlines)
695+underline = fmap B.strong <$> emphasisBetween '_'
652696
653−verbatim :: OrgParser Inlines
654−verbatim = B.rawInline "" <$> verbatimBetween '~'
697+code :: OrgParser (F Inlines)
698+code = return . B.code <$> verbatimBetween '='
655699
656−math :: OrgParser Inlines
657−math = B.math <$> choice [ math1CharBetween '$'
658− , mathStringBetween '$'
659− , rawMathBetween "\\(" "\\)"
660− ]
700+verbatim :: OrgParser (F Inlines)
701+verbatim = return . B.rawInline "" <$> verbatimBetween '~'
661702
662−displayMath :: OrgParser Inlines
663−displayMath = B.displayMath <$> choice [ rawMathBetween "\\[" "\\]"
664− , rawMathBetween "$$" "$$"
665− ]
703+subscript :: OrgParser (F Inlines)
704+subscript = fmap B.subscript <$> try (char '_' *> subOrSuperExpr)
666705
667−subscript :: OrgParser Inlines
668−subscript = B.subscript <$> try (char '_' *> subOrSuperExpr)
706+superscript :: OrgParser (F Inlines)
707+superscript = fmap B.superscript <$> try (char '^' *> subOrSuperExpr)
669708
670−superscript :: OrgParser Inlines
671−superscript = B.superscript <$> try (char '^' *> subOrSuperExpr)
709+math :: OrgParser (F Inlines)
710+math = return . B.math <$> choice [ math1CharBetween '$'
711+ , mathStringBetween '$'
712+ , rawMathBetween "\\(" "\\)"
713+ ]
672714
673−symbol :: OrgParser Inlines
674−symbol = B.str . (: "") <$> (oneOf specialChars >>= updatePositions)
715+displayMath :: OrgParser (F Inlines)
716+displayMath = return . B.displayMath <$> choice [ rawMathBetween "\\[" "\\]"
717+ , rawMathBetween "$$" "$$"
718+ ]
719+symbol :: OrgParser (F Inlines)
720+symbol = return . B.str . (: "") <$> (oneOf specialChars >>= updatePositions)
675721 where updatePositions c
676722 | c `elem` emphasisPreChars = c <$ updateLastPreCharPos
677723 | c `elem` emphasisForbiddenBorderChars = c <$ updateLastForbiddenCharPos
678724 | otherwise = return c
679725
680726emphasisBetween :: Char
681− -> OrgParser Inlines
727+ -> OrgParser (F Inlines)
682728emphasisBetween c = try $ do
683729 startEmphasisNewlinesCounting emphasisAllowedNewlines
684730 res <- enclosedInlines (emphasisStart c) (emphasisEnd c)
@@ -755,9 +801,9 @@ mathEnd c = try $ do
755801
756802enclosedInlines :: OrgParser a
757803 -> OrgParser b
758− -> OrgParser Inlines
804+ -> OrgParser (F Inlines)
759805enclosedInlines start end = try $
760− trimInlines . mconcat <$> enclosed start end inline
806+ trimInlinesF . mconcat <$> enclosed start end inline
761807
762808enclosedRaw :: OrgParser a
763809 -> OrgParser b
@@ -843,7 +889,7 @@ notAfterForbiddenBorderChar = do
843889 return $ lastFBCPos /= Just pos
844890
845891-- | Read a sub- or superscript expression
846−subOrSuperExpr :: OrgParser Inlines
892+subOrSuperExpr :: OrgParser (F Inlines)
847893subOrSuperExpr = try $
848894 choice [ id <$> charsInBalanced '{' '}' (noneOf "\n\r")
849895 , enclosing ('(', ')') <$> charsInBalanced '(' ')' (noneOf "\n\r")