@@ -120,6 +120,7 @@ braced = char '{' *> (concat <$> manyTill
120120 ( many1 (satisfy (\c -> c /= '\\' && c /= '}' && c /= '{'))
121121 <|> try (string "\\}")
122122 <|> try (string "\\{")
123+ <|> try (string "\\\\")
123124 <|> ((\x -> "{" ++ x ++ "}") <$> braced)
124125 <|> count 1 anyChar
125126 ) (char '}'))
@@ -172,6 +173,7 @@ inline = (mempty <$ comment)
172173 <|> (str <$> count 1 tildeEscape)
173174 <|> (str <$> string "]")
174175 <|> (str <$> string "#") -- TODO print warning?
176+ <|> (str <$> string "&") -- TODO print warning?
175177 -- <|> (str <$> count 1 (satisfy (\c -> c /= '\\' && c /='\n' && c /='}' && c /='{'))) -- eat random leftover characters
176178
177179inlines :: LP Inlines
@@ -208,28 +210,28 @@ inBrackets x = (str "[") <> x <> (str "]")
208210-- eat an optional argument and one or more arguments in braces
209211ignoreInlines :: String -> (String, LP Inlines)
210212ignoreInlines name = (name, doraw <|> (mempty <$ optargs))
211− where optargs = optional opt *> skipMany (optional sp *> braced)
213+ where optargs = skipopts *> skipMany (try $ optional sp *> braced)
212214 contseq = '\\':name
213215 doraw = (rawInline "latex" . (contseq ++) . snd) <$>
214216 (getState >>= guard . stateParseRaw >> (withRaw optargs))
215217
216218ignoreBlocks :: String -> (String, LP Blocks)
217219ignoreBlocks name = (name, doraw <|> (mempty <$ optargs))
218− where optargs = optional opt *> skipMany (optional sp *> braced)
220+ where optargs = skipopts *> skipMany (try $ optional sp *> braced)
219221 contseq = '\\':name
220222 doraw = (rawBlock "latex" . (contseq ++) . snd) <$>
221223 (getState >>= guard . stateParseRaw >> (withRaw optargs))
222224
223225blockCommands :: M.Map String (LP Blocks)
224226blockCommands = M.fromList $
225− [ ("par", pure mempty)
226− , ("title", mempty <$ (tok >>= addTitle))
227− , ("subtitle", mempty <$ (tok >>= addSubtitle))
228− , ("author", mempty <$ authors)
229− -- in letter class, temp. store address & sig as title, author
230− , ("address", mempty <$ (tok >>= addTitle))
231− , ("signature", mempty <$ authors)
232− , ("date", mempty <$ (tok >>= addDate))
227+ [ ("par", mempty <$ skipopts)
228+ , ("title", mempty <$ (skipopts *> tok >>= addTitle))
229+ , ("subtitle", mempty <$ (skipopts *> tok >>= addSubtitle))
230+ , ("author", mempty <$ (skipopts *> authors))
231+ -- -- in letter class, temp. store address & sig as title, author
232+ , ("address", mempty <$ (skipopts *> tok >>= addTitle))
233+ , ("signature", mempty <$ (skipopts *> authors))
234+ , ("date", mempty <$ (skipopts *> tok >>= addDate))
233235 -- sectioning
234236 , ("chapter", updateState (\s -> s{ stateHasChapters = True }) *> section 0)
235237 , ("section", section 1)
@@ -241,14 +243,14 @@ blockCommands = M.fromList $
241243 , ("frametitle", section 3)
242244 , ("framesubtitle", section 4)
243245 -- letters
244− , ("opening", (para . trimInlines) <$> tok)
245− , ("closing", closing)
246+ , ("opening", (para . trimInlines) <$> (skipopts *> tok))
247+ , ("closing", skipopts *> closing)
246248 --
247− , ("rule", optional opt *> tok *> tok *> pure horizontalRule)
249+ , ("rule", skipopts *> tok *> tok *> pure horizontalRule)
248250 , ("begin", mzero) -- these are here so they won't be interpreted as inline
249251 , ("end", mzero)
250− , ("item", loose_item)
251− , ("documentclass", optional opt *> braced *> preamble)
252+ , ("item", skipopts *> loose_item)
253+ , ("documentclass", skipopts *> braced *> preamble)
252254 ] ++ map ignoreBlocks
253255 -- these commands will be ignored unless --parse-raw is specified,
254256 -- in which case they will appear as raw latex blocks
@@ -291,8 +293,7 @@ section :: Int -> LP Blocks
291293section lvl = do
292294 hasChapters <- stateHasChapters `fmap` getState
293295 let lvl' = if hasChapters then lvl + 1 else lvl
294− optional sp
295− optional opt
296+ skipopts
296297 contents <- grouped inline
297298 return $ header lvl' contents
298299
@@ -310,7 +311,7 @@ inlineCommand = try $ do
310311 Nothing
311312 | parseRaw ->
312313 (rawInline "latex" . (('\\':name') ++)) <$>
313− (withRaw (optional opt *> many braced)
314+ (withRaw (skipopts *> many braced)
314315 >>= applyMacros' . snd)
315316 | otherwise -> return mempty
316317
@@ -399,7 +400,7 @@ inlineCommands = M.fromList $
399400 , ("href", (unescapeURL <$> braced <* optional sp) >>= \url ->
400401 tok >>= \lab ->
401402 pure (link url "" lab))
402− , ("includegraphics", optional opt *> (unescapeURL <$> braced) >>=
403+ , ("includegraphics", skipopts *> (unescapeURL <$> braced) >>=
403404 (\src -> pure (image src "" (str "image"))))
404405 , ("cite", citation "cite" NormalCitation False)
405406 , ("citep", citation "citep" NormalCitation False)
@@ -573,6 +574,9 @@ tok = try $ grouped inline <|> inlineCommand <|> str <$> (count 1 $ inlineChar)
573574opt :: LP Inlines
574575opt = bracketed inline <* optional sp
575576
577+skipopts :: LP ()
578+skipopts = skipMany opt
579+
576580inlineText :: LP Inlines
577581inlineText = str <$> many1 inlineChar
578582
@@ -619,7 +623,7 @@ handleIncludes (x:xs) = (x:) `fmap` handleIncludes xs
619623include :: LP ([FilePath], String)
620624include = do
621625 name <- controlSeq "include" <|> controlSeq "usepackage"
622− optional opt
626+ skipopts
623627 fs <- (splitBy (==',')) <$> braced
624628 rest <- getInput
625629 let fs' = if name == "include"
@@ -712,7 +716,7 @@ closing = do
712716 return $ para (trimInlines contents) <> sigs
713717
714718item :: LP Blocks
715−item = blocks *> controlSeq "item" *> optional opt *> blocks
719+item = blocks *> controlSeq "item" *> skipopts *> blocks
716720
717721loose_item :: LP Blocks
718722loose_item = do
@@ -750,7 +754,7 @@ mathEnv innerEnv name = para <$> mathDisplay (inner <$> verbEnv name)
750754
751755verbEnv :: String -> LP String
752756verbEnv name = do
753− optional opt
757+ skipopts
754758 optional blankline
755759 let endEnv = try $ controlSeq "end" *> braced >>= guard . (== name)
756760 res <- manyTill anyChar endEnv