@@ -65,7 +65,7 @@ import Text.Pandoc.Parsing hiding (many, optional, withRaw,
65 mathInline, mathDisplay,
65 mathInline, mathDisplay,
66 space, (<|>), spaces, blankline)
66 space, (<|>), spaces, blankline)
67import Text.Pandoc.Shared
67import Text.Pandoc.Shared
68−import Text.Pandoc.Readers.LaTeX.Types (Macro(..), Tok(..),
68+import Text.Pandoc.Readers.LaTeX.Types (Macro(..), ExpansionPoint(..), Tok(..),
69 TokType(..))
69 TokType(..))
70import Text.Pandoc.Walk
70import Text.Pandoc.Walk
71import Text.Pandoc.Error (PandocError(PandocParsecError, PandocMacroLoop))
71import Text.Pandoc.Error (PandocError(PandocParsecError, PandocMacroLoop))
@@ -375,7 +375,7 @@ doMacros n = do
375 macros <- sMacros <$> getState
375 macros <- sMacros <$> getState
376 case M.lookup name macros of
376 case M.lookup name macros of
377 Nothing -> return ()
377 Nothing -> return ()
378− Just (Macro numargs optarg newtoks) -> do
378+ Just (Macro expansionPoint numargs optarg newtoks) -> do
379 setInput ts
379 setInput ts
380 let getarg = spaces >> braced
380 let getarg = spaces >> braced
381 args <- case optarg of
381 args <- case optarg of
@@ -389,9 +389,12 @@ doMacros n = do
389 addTok t acc = setpos spos t : acc
389 addTok t acc = setpos spos t : acc
390 ts' <- getInput
390 ts' <- getInput
391 setInput $ foldr addTok ts' newtoks
391 setInput $ foldr addTok ts' newtoks
392+ case expansionPoint of
392− if n > 20 -- detect macro expansion loops
394+ if n > 20 -- detect macro expansion loops
393− then throwError $ PandocMacroLoop (T.unpack name)
395+ then throwError $ PandocMacroLoop (T.unpack name)
394− else doMacros (n + 1)
396+ else doMacros (n + 1)
397+ ExpandWhenDefined -> return ()
396setpos :: (Line, Column) -> Tok -> Tok
399setpos :: (Line, Column) -> Tok -> Tok
397setpos spos (Tok _ tt txt) = Tok spos tt txt
400setpos spos (Tok _ tt txt) = Tok spos tt txt
@@ -1375,7 +1378,8 @@ isBlockCommand s =
1376treatAsBlock :: Set.Set Text
1379treatAsBlock :: Set.Set Text
1377treatAsBlock = Set.fromList
1380treatAsBlock = Set.fromList
1378− [ "newcommand", "renewcommand"
1382+ , "newcommand", "renewcommand"
1379 , "newenvironment", "renewenvironment"
1383 , "newenvironment", "renewenvironment"
1380 , "providecommand", "provideenvironment"
1384 , "providecommand", "provideenvironment"
1381 -- newcommand, etc. should be parsed by macroDef, but we need this
1385 -- newcommand, etc. should be parsed by macroDef, but we need this
@@ -1517,7 +1521,7 @@ macroDef :: PandocMonad m => LP m Blocks
1517macroDef = do
1521macroDef = do
1518 mempty <$ ((commandDef <|> environmentDef) <* doMacros 0)
1522 mempty <$ ((commandDef <|> environmentDef) <* doMacros 0)
1519 where commandDef = do
1523 where commandDef = do
1520− (name, macro') <- newcommand
1524+ (name, macro') <- newcommand <|> letmacro
1521 guardDisabled Ext_latex_macros <|>
1525 guardDisabled Ext_latex_macros <|>
1522 updateState (\s -> s{ sMacros = M.insert name macro' (sMacros s) })
1526 updateState (\s -> s{ sMacros = M.insert name macro' (sMacros s) })
1523 environmentDef = do
1527 environmentDef = do
@@ -1532,6 +1536,15 @@ macroDef = do
1532 -- @\newcommand{\envname}[n-args][default]{begin}@
1536 -- @\newcommand{\envname}[n-args][default]{begin}@
1533 -- @\newcommand{\endenvname}@
1537 -- @\newcommand{\endenvname}@
1539+letmacro :: PandocMonad m => LP m (Text, Macro)
1543+ Tok _ (CtrlSeq name) _ <- anyControlSeq
1544+ optional $ symbol '='
1545+ contents <- braced <|> ((:[]) <$> anyControlSeq)
1546+ return (name, Macro ExpandWhenDefined 0 Nothing contents)
1535newcommand :: PandocMonad m => LP m (Text, Macro)
1548newcommand :: PandocMonad m => LP m (Text, Macro)
1536newcommand = do
1549newcommand = do
1537 pos <- getPosition
1550 pos <- getPosition
@@ -1546,13 +1559,15 @@ newcommand = do
1547 optarg <- option Nothing $ Just <$> try bracketedToks
1560 optarg <- option Nothing $ Just <$> try bracketedToks
1549− contents <- braced
1562+ contents <- withVerbatimMode braced
1563+ -- we use withVerbatimMode, because macros are to be expanded
1564+ -- at point of use, not point of definition
1550 when (mtype == "newcommand") $ do
1565 when (mtype == "newcommand") $ do
1551 macros <- sMacros <$> getState
1566 macros <- sMacros <$> getState
1552 case M.lookup name macros of
1567 case M.lookup name macros of
1553 Just _ -> report $ MacroAlreadyDefined (T.unpack txt) pos
1568 Just _ -> report $ MacroAlreadyDefined (T.unpack txt) pos
1554 Nothing -> return ()
1569 Nothing -> return ()
1555− return (name, Macro numargs optarg contents)
1570+ return (name, Macro ExpandWhenUsed numargs optarg contents)
1557newenvironment :: PandocMonad m => LP m (Text, Macro, Macro)
1572newenvironment :: PandocMonad m => LP m (Text, Macro, Macro)
1558newenvironment = do
1573newenvironment = do
@@ -1568,16 +1583,16 @@ newenvironment = do
1569 optarg <- option Nothing $ Just <$> try bracketedToks
1584 optarg <- option Nothing $ Just <$> try bracketedToks
1571− startcontents <- braced
1586+ startcontents <- withVerbatimMode braced
1573− endcontents <- braced
1588+ endcontents <- withVerbatimMode braced
1574 when (mtype == "newenvironment") $ do
1589 when (mtype == "newenvironment") $ do
1575 macros <- sMacros <$> getState
1590 macros <- sMacros <$> getState
1576 case M.lookup name macros of
1591 case M.lookup name macros of
1577 Just _ -> report $ MacroAlreadyDefined (T.unpack name) pos
1592 Just _ -> report $ MacroAlreadyDefined (T.unpack name) pos
1578 Nothing -> return ()
1593 Nothing -> return ()
1579− return (name, Macro numargs optarg startcontents,
1594+ return (name, Macro ExpandWhenUsed numargs optarg startcontents,
1580− Macro 0 Nothing endcontents)
1595+ Macro ExpandWhenUsed 0 Nothing endcontents)
1582bracketedToks :: PandocMonad m => LP m [Tok]
1597bracketedToks :: PandocMonad m => LP m [Tok]
1583bracketedToks = do
1598bracketedToks = do