From c47bd8404fda0a782719848ef190b56eb0fdb9dc Mon Sep 17 00:00:00 2001
From: Albert Krewinkel <tarleb@moltkeplatz.de>
Date: Mon, 7 Apr 2014 11:00:30 +0200
Subject: [PATCH] Org reader: Support inline math (like $E=mc^2$)

Closes #1223.
---
 src/Text/Pandoc/Readers/Org.hs | 22 ++++++++++++++++------
 tests/Tests/Readers/Org.hs     |  4 ++++
 2 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/src/Text/Pandoc/Readers/Org.hs b/src/Text/Pandoc/Readers/Org.hs
index 20bca3e28..2bb6ee122 100644
--- a/src/Text/Pandoc/Readers/Org.hs
+++ b/src/Text/Pandoc/Readers/Org.hs
@@ -459,6 +459,7 @@ inline = choice inlineParsers <?> "inline"
                         , strikeout
                         , underline
                         , code
+                        , math
                         , verbatim
                         , subscript
                         , superscript
@@ -530,10 +531,13 @@ underline = B.strong       <$> inlinesEnclosedBy '_'
 code      :: OrgParser Inlines
 code      = B.code         <$> rawEnclosedBy '='
 
-verbatim  ::  OrgParser Inlines
+math      :: OrgParser Inlines
+math      = B.math         <$> rawEnclosedBy '$'
+
+verbatim  :: OrgParser Inlines
 verbatim  = B.rawInline "" <$> rawEnclosedBy '~'
 
-subscript ::  OrgParser Inlines
+subscript :: OrgParser Inlines
 subscript = B.subscript    <$> (try $ char '_' *> maybeGroupedByBraces)
 
 superscript ::  OrgParser Inlines
@@ -580,18 +584,24 @@ rawEnclosedBy c = enclosedRaw (atStart $ char c) (atEnd $ char c)
 -- succeeds only if we're not right after a str (ie. in middle of word)
 atStart :: OrgParser a -> OrgParser a
 atStart p = do
-  pos <- getPosition
-  st <- getState
-  guard $ orgLastStrPos st /= Just pos
+  guard =<< not <$> isRightAfterString
   p
 
 -- | succeeds only if we're at the end of a word
 atEnd :: OrgParser a -> OrgParser a
 atEnd p = try $ do
-  p <* lookingAtEndOfWord
+ p <* lookingAtEndOfWord
  where lookingAtEndOfWord =
            eof <|> const (return ()) =<< lookAhead . oneOf =<< postWordChars
 
+isRightAfterString :: OrgParser Bool
+isRightAfterString = do
+  pos <- getPosition
+  st <- getState
+  -- the position `Nothing` isn't after a String, either, hence the double
+  -- negation
+  return $ not $ orgLastStrPos st /= Just pos
+
 postWordChars :: OrgParser [Char]
 postWordChars = do
   st <- getState
diff --git a/tests/Tests/Readers/Org.hs b/tests/Tests/Readers/Org.hs
index eb9f4d741..77b9d9327 100644
--- a/tests/Tests/Readers/Org.hs
+++ b/tests/Tests/Readers/Org.hs
@@ -54,6 +54,10 @@ tests =
           "=Robot.rock()=" =?>
           para (code "Robot.rock()")
 
+      , "Math" =:
+          "$E=mc^2$" =?>
+           para (math "E=mc^2")
+
       , "Verbatim" =:
           "~word for word~" =?>
           para (rawInline "" "word for word")