From be14e2b5013a442989a338c13baa4d16881f849e Mon Sep 17 00:00:00 2001 From: John MacFarlane Date: Sun, 23 Jul 2017 20:46:37 +0200 Subject: [PATCH] LaTeX reader: some improvements in macro parsing. Fixed applyMacros so that it operates on the whole string, not just the first token! Don't remove macro definitions from the output, even if Ext_latex_macros is set, so that macros will be applied. Since they're only applied to math in Markdown, removing the macros can have bad effects. Even for math macros, keeping them should be harmless. --- src/Text/Pandoc/Readers/LaTeX.hs | 38 ++++++++++++++++---------------- test/command/macros.md | 8 +++++++ test/markdown-reader-more.native | 1 + 3 files changed, 28 insertions(+), 19 deletions(-) create mode 100644 test/command/macros.md diff --git a/src/Text/Pandoc/Readers/LaTeX.hs b/src/Text/Pandoc/Readers/LaTeX.hs index 183eb89a6..cc567d5bd 100644 --- a/src/Text/Pandoc/Readers/LaTeX.hs +++ b/src/Text/Pandoc/Readers/LaTeX.hs @@ -200,12 +200,6 @@ withVerbatimMode parser = do updateState $ \st -> st{ sVerbatimMode = False } return result -rawLaTeXBlock :: (PandocMonad m, HasMacros s, HasReaderOptions s) - => ParserT String s m String -rawLaTeXBlock = do - lookAhead (try (char '\\' >> letter)) - rawLaTeXParser (environment <|> macroDef <|> blockCommand) - rawLaTeXParser :: (PandocMonad m, HasMacros s, HasReaderOptions s) => LP m a -> ParserT String s m String rawLaTeXParser parser = do @@ -218,7 +212,7 @@ rawLaTeXParser parser = do case res of Left _ -> mzero Right (raw, st) -> do - updateState (updateMacros (const $ sMacros st)) + updateState (updateMacros ((sMacros st) <>)) takeP (T.length (untokenize raw)) macro :: (PandocMonad m, HasMacros s, HasReaderOptions s) @@ -227,21 +221,26 @@ macro = do guardEnabled Ext_latex_macros lookAhead (char '\\' *> oneOfStrings ["new", "renew", "provide"] *> oneOfStrings ["command", "environment"]) - mempty <$ rawLaTeXParser macroDef - -- since we're applying macros, we remove the defns + rawBlock "latex" <$> rawLaTeXParser macroDef applyMacros :: (PandocMonad m, HasMacros s, HasReaderOptions s) => String -> ParserT String s m String -applyMacros s = do - (guardEnabled Ext_latex_macros >> - do let retokenize = doMacros 0 *> (toksToString <$> getInput) +applyMacros s = (guardDisabled Ext_latex_macros >> return s) <|> + do let retokenize = doMacros 0 *> + (toksToString <$> many (satisfyTok (const True))) pstate <- getState let lstate = def{ sOptions = extractReaderOptions pstate , sMacros = extractMacros pstate } res <- runParserT retokenize lstate "math" (tokenize (T.pack s)) case res of Left e -> fail (show e) - Right s' -> return s') <|> return s + Right s' -> return s' + +rawLaTeXBlock :: (PandocMonad m, HasMacros s, HasReaderOptions s) + => ParserT String s m String +rawLaTeXBlock = do + lookAhead (try (char '\\' >> letter)) + rawLaTeXParser (environment <|> macroDef <|> blockCommand) rawLaTeXInline :: (PandocMonad m, HasMacros s, HasReaderOptions s) => ParserT String s m String @@ -1503,17 +1502,18 @@ authors = try $ do macroDef :: PandocMonad m => LP m Blocks macroDef = do - guardEnabled Ext_latex_macros mempty <$ ((commandDef <|> environmentDef) <* doMacros 0) where commandDef = do (name, macro') <- newcommand - updateState $ \s -> s{ sMacros = M.insert name macro' (sMacros s) } + guardDisabled Ext_latex_macros <|> + updateState (\s -> s{ sMacros = M.insert name macro' (sMacros s) }) environmentDef = do (name, macro1, macro2) <- newenvironment - updateState $ \s -> s{ sMacros = - M.insert name macro1 (sMacros s) } - updateState $ \s -> s{ sMacros = - M.insert ("end" <> name) macro2 (sMacros s) } + guardDisabled Ext_latex_macros <|> + do updateState $ \s -> s{ sMacros = + M.insert name macro1 (sMacros s) } + updateState $ \s -> s{ sMacros = + M.insert ("end" <> name) macro2 (sMacros s) } -- @\newenvironment{envname}[n-args][default]{begin}{end}@ -- is equivalent to -- @\newcommand{\envname}[n-args][default]{begin}@ diff --git a/test/command/macros.md b/test/command/macros.md new file mode 100644 index 000000000..74d63ef08 --- /dev/null +++ b/test/command/macros.md @@ -0,0 +1,8 @@ +``` +% pandoc -t markdown +\newcommand{\my}{\phi} +$\my+\my$ +^D +\newcommand{\my}{\phi} +$\phi+\phi$ +``` diff --git a/test/markdown-reader-more.native b/test/markdown-reader-more.native index 5d63a21de..a24417ffe 100644 --- a/test/markdown-reader-more.native +++ b/test/markdown-reader-more.native @@ -56,6 +56,7 @@ Pandoc (Meta {unMeta = fromList [("author",MetaList [MetaInlines [Str "Author",S ,OrderedList (3,Example,TwoParens) [[Plain [Str "Third",Space,Str "example."]]] ,Header 2 ("macros",[],[]) [Str "Macros"] +,RawBlock (Format "latex") "\\newcommand{\\tuple}[1]{\\langle #1 \\rangle}" ,Para [Math InlineMath "\\langle x,y \\rangle"] ,Header 2 ("case-insensitive-references",[],[]) [Str "Case-insensitive",Space,Str "references"] ,Para [Link ("",[],[]) [Str "Fum"] ("/fum","")]