git.iko.soy/typeable/pandoc
on master help sign in
Merge pull request #1231 from tarleb/org-fix-subexpr
2304e9cJohn MacFarlane
src/Text/Pandoc/Readers/Org.hs+37−10
@@ -622,17 +622,11 @@ displayMath = B.displayMath <$> choice [ rawMathBetween "\\[" "\\]"
622 , rawMathBetween "$$" "$$"
622 , rawMathBetween "$$" "$$"
623 ]
623 ]
624
624
625−subscript :: OrgParser Inlines
625+subscript :: OrgParser Inlines
626−subscript = B.subscript <$> try (char '_' *> maybeGroupedByBraces)
626+subscript = B.subscript <$> try (char '_' *> subOrSuperExpr)
627
627
628−superscript :: OrgParser Inlines
628+superscript :: OrgParser Inlines
629−superscript = B.superscript <$> try (char '^' *> maybeGroupedByBraces)
629+superscript = B.superscript <$> try (char '^' *> subOrSuperExpr)
630−
631−maybeGroupedByBraces :: OrgParser Inlines
632−maybeGroupedByBraces = try $
633− choice [ try $ enclosedInlines (char '{') (char '}')
634− , B.str . (:"") <$> anyChar
635− ]
636
630
637symbol :: OrgParser Inlines
631symbol :: OrgParser Inlines
638symbol = B.str . (: "") <$> (oneOf specialChars >>= updatePositions)
632symbol = B.str . (: "") <$> (oneOf specialChars >>= updatePositions)
@@ -805,3 +799,36 @@ notAfterForbiddenBorderChar = do
805 pos <- getPosition
799 pos <- getPosition
806 lastFBCPos <- orgStateLastForbiddenCharPos <$> getState
800 lastFBCPos <- orgStateLastForbiddenCharPos <$> getState
807 return $ lastFBCPos /= Just pos
801 return $ lastFBCPos /= Just pos
802+
803+-- | Read a sub- or superscript expression
804+subOrSuperExpr :: OrgParser Inlines
805+subOrSuperExpr = try $ do
806+ choice [ balancedSexp '{' '}'
807+ , balancedSexp '(' ')' >>= return . enclosing ('(', ')')
808+ , simpleSubOrSuperString
809+ ] >>= parseFromString (mconcat <$> many inline)
810+
811+-- | Read a balanced sexp
812+balancedSexp :: Char
813+ -> Char
814+ -> OrgParser String
815+balancedSexp l r = try $ do
816+ char l
817+ res <- concat <$> many ( many1 (noneOf ([l, r] ++ "\n\r"))
818+ <|> try (string [l, r])
819+ <|> enclosing (l, r) <$> balancedSexp l r
820+ )
821+ char r
822+ return res
823+
824+simpleSubOrSuperString :: OrgParser String
825+simpleSubOrSuperString = try $
826+ choice [ string "*"
827+ , mappend <$> option [] ((:[]) <$> oneOf "+-")
828+ <*> many1 alphaNum
829+ ]
830+
831+enclosing :: (a, a)
832+ -> [a]
833+ -> [a]
834+enclosing (left, right) s = left : s ++ [right]
tests/Tests/Readers/Org.hs+30−9
@@ -78,15 +78,15 @@ tests =
78 "A * symbol" =?>
78 "A * symbol" =?>
79 para (str "A" <> space <> str "*" <> space <> "symbol")
79 para (str "A" <> space <> str "*" <> space <> "symbol")
80
80
81− , "Superscript single char" =:
81+ , "Superscript simple expression" =:
82− "2^n" =?>
82+ "2^-λ" =?>
83− para (str "2" <> superscript "n")
83+ para (str "2" <> superscript "-λ")
84
84
85 , "Superscript multi char" =:
85 , "Superscript multi char" =:
86 "2^{n-1}" =?>
86 "2^{n-1}" =?>
87 para (str "2" <> superscript "n-1")
87 para (str "2" <> superscript "n-1")
88
88
89− , "Subscript single char" =:
89+ , "Subscript simple expression" =:
90 "a_n" =?>
90 "a_n" =?>
91 para (str "a" <> subscript "n")
91 para (str "a" <> subscript "n")
92
92
@@ -105,11 +105,8 @@ tests =
105 ])
105 ])
106
106
107 , "No empty markup" =:
107 , "No empty markup" =:
108− -- FIXME: __ is erroneously parsed as subscript "_"
109− -- "// ** __ ++ == ~~ $$" =?>
108+ "// ** __ ++ == ~~ $$" =?>
110− -- para (spcSep [ "//", "**", "__", "++", "==", "~~", "$$" ])
109+ para (spcSep [ "//", "**", "__", "++", "==", "~~", "$$" ])
111− "// ** ++ == ~~ $$" =?>
112− para (spcSep [ "//", "**", "++", "==", "~~", "$$" ])
113
110
114 , "Adherence to Org's rules for markup borders" =:
111 , "Adherence to Org's rules for markup borders" =:
115 "/t/& a/ / ./r/ (*l*) /e/! /b/." =?>
112 "/t/& a/ / ./r/ (*l*) /e/! /b/." =?>
@@ -143,6 +140,30 @@ tests =
143 ]))
140 ]))
144 , "emph/" ])
141 , "emph/" ])
145
142
143+ , "Sub- and superscript expressions" =:
144+ unlines [ "a_(a(b)(c)d)"
145+ , "e^(f(g)h)"
146+ , "i_(jk)l)"
147+ , "m^()n"
148+ , "o_{p{q{}r}}"
149+ , "s^{t{u}v}"
150+ , "w_{xy}z}"
151+ , "1^{}2"
152+ , "3_{{}}"
153+ , "4^(a(*b(c*)d))"
154+ ] =?>
155+ para (spcSep [ "a" <> subscript "(a(b)(c)d)"
156+ , "e" <> superscript "(f(g)h)"
157+ , "i" <> (subscript "(jk)") <> "l)"
158+ , "m" <> (superscript "()") <> "n"
159+ , "o" <> subscript "p{q{}r}"
160+ , "s" <> superscript "t{u}v"
161+ , "w" <> (subscript "xy") <> "z}"
162+ , "1" <> (superscript "") <> "2"
163+ , "3" <> subscript "{}"
164+ , "4" <> superscript ("(a(" <> strong "b(c" <> ")d))")
165+ ])
166+
146 , "Image" =:
167 , "Image" =:
147 "[[./sunset.jpg]]" =?>
168 "[[./sunset.jpg]]" =?>
148 (para $ image "./sunset.jpg" "" "")
169 (para $ image "./sunset.jpg" "" "")