@@ -42,7 +42,8 @@ module Text.Pandoc.Readers.Muse (readMuse) where
42import Control.Monad
42import Control.Monad
43import Control.Monad.Except (throwError)
43import Control.Monad.Except (throwError)
44import Data.Char (isLetter)
44import Data.Char (isLetter)
45−import Data.List (stripPrefix)
45+import Data.List (stripPrefix, intercalate)
46+import Data.List.Split (splitOn)
46import qualified Data.Map as M
47import qualified Data.Map as M
47import Data.Maybe (fromMaybe)
48import Data.Maybe (fromMaybe)
48import Data.Text (Text, unpack)
49import Data.Text (Text, unpack)
@@ -187,17 +188,19 @@ directive = do
187-- block parsers
188-- block parsers
190−block :: PandocMonad m => MuseParser m (F Blocks)
191+parseBlock :: PandocMonad m => MuseParser m (F Blocks)
191−block = do
192+parseBlock = do
192− res <- mempty <$ skipMany1 blankline
193− <|> blockElements
193+ res <- blockElements <|> para
195− skipMany blankline
194+ optionMaybe blankline
196 trace (take 60 $ show $ B.toList $ runF res defaultParserState)
195 trace (take 60 $ show $ B.toList $ runF res defaultParserState)
197 return res
196 return res
198+block :: PandocMonad m => MuseParser m (F Blocks)
199+block = parseBlock <* skipMany blankline
199blockElements :: PandocMonad m => MuseParser m (F Blocks)
201blockElements :: PandocMonad m => MuseParser m (F Blocks)
200−blockElements = choice [ comment
202+blockElements = choice [ mempty <$ blankline
201 , separator
204 , separator
203 , example
206 , example
@@ -257,15 +260,26 @@ example = try $ do
257-- in case opening and/or closing tags are on separate lines.
260-- in case opening and/or closing tags are on separate lines.
258chop :: String -> String
261chop :: String -> String
259chop = lchop . rchop
262chop = lchop . rchop
264+lchop :: String -> String
260− where lchop s = case s of
265+lchop s = case s of
261 '\n':ss -> ss
266 '\n':ss -> ss
269+rchop :: String -> String
263− rchop = reverse . lchop . reverse
270+rchop = reverse . lchop . reverse
272+dropSpacePrefix :: [String] -> [String]
273+dropSpacePrefix lns =
274+ map (drop maxIndent) lns
275+ where flns = filter (not . all (== ' ')) lns
276+ maxIndent = if null flns then maximum (map length lns) else length $ takeWhile (== ' ') $ foldl1 commonPrefix flns
265exampleTag :: PandocMonad m => MuseParser m (F Blocks)
278exampleTag :: PandocMonad m => MuseParser m (F Blocks)
266−exampleTag = do
279+exampleTag = try $ do
267 (attr, contents) <- htmlElement "example"
281 (attr, contents) <- htmlElement "example"
268− return $ return $ B.codeBlockWith attr $ chop contents
282+ return $ return $ B.codeBlockWith attr $ rchop $ intercalate "\n" $ dropSpacePrefix $ splitOn "\n" $ lchop contents
270literal :: PandocMonad m => MuseParser m (F Blocks)
284literal :: PandocMonad m => MuseParser m (F Blocks)
271literal = do
285literal = do
@@ -309,7 +323,7 @@ verseLine = do
310verseLines :: PandocMonad m => MuseParser m (F Blocks)
324verseLines :: PandocMonad m => MuseParser m (F Blocks)
311verseLines = do
325verseLines = do
312− optionMaybe blankline -- Skip blankline after opening tag on separate line
326+ --optionMaybe blankline -- Skip blankline after opening tag on separate line
313 lns <- many verseLine
327 lns <- many verseLine
314 lns' <- mapM (parseFromString' (trimInlinesF . mconcat <$> many inline)) lns
328 lns' <- mapM (parseFromString' (trimInlinesF . mconcat <$> many inline)) lns
315 return $ B.lineBlock <$> sequence lns'
329 return $ B.lineBlock <$> sequence lns'
@@ -317,7 +331,7 @@ verseLines = do
317verseTag :: PandocMonad m => MuseParser m (F Blocks)
331verseTag :: PandocMonad m => MuseParser m (F Blocks)
318verseTag = do
332verseTag = do
319 (_, content) <- htmlElement "verse"
333 (_, content) <- htmlElement "verse"
320− parseFromString verseLines content
334+ parseFromString verseLines (intercalate "\n" $ dropSpacePrefix $ splitOn "\n" $ lchop content)
322commentTag :: PandocMonad m => MuseParser m (F Blocks)
336commentTag :: PandocMonad m => MuseParser m (F Blocks)
323commentTag = parseHtmlContent "comment" anyChar >> return mempty
337commentTag = parseHtmlContent "comment" anyChar >> return mempty
@@ -349,7 +363,7 @@ amuseNoteBlock = try $ do
349 guardEnabled Ext_amuse
363 guardEnabled Ext_amuse
350 pos <- getPosition
364 pos <- getPosition
351 ref <- noteMarker <* spaceChar
365 ref <- noteMarker <* spaceChar
352− content <- listItemContents $ 3 + length ref
366+ content <- listItemContents
353 oldnotes <- stateNotes' <$> getState
367 oldnotes <- stateNotes' <$> getState
354 case M.lookup ref oldnotes of
368 case M.lookup ref oldnotes of
355 Just _ -> logMessage $ DuplicateNoteReference ref pos
369 Just _ -> logMessage $ DuplicateNoteReference ref pos
@@ -399,11 +413,6 @@ lineBlock = try $ do
402−listLine :: PandocMonad m => Int -> MuseParser m String
403−listLine markerLength = try $ do
404− indentWith markerLength
405− manyTill anyChar eol
407withListContext :: PandocMonad m => MuseParser m a -> MuseParser m a
416withListContext :: PandocMonad m => MuseParser m a -> MuseParser m a
408withListContext p = do
417withListContext p = do
409 state <- getState
418 state <- getState
@@ -413,66 +422,47 @@ withListContext p = do
413 updateState (\st -> st {stateParserContext = oldContext})
422 updateState (\st -> st {stateParserContext = oldContext})
414 return parsed
423 return parsed
416−listContinuation :: PandocMonad m => Int -> MuseParser m [String]
425+listItemContents :: PandocMonad m => MuseParser m (F Blocks)
417−listContinuation markerLength = try $ do
426+listItemContents = do
418− result <- many1 $ listLine markerLength
427+ pos <- getPosition
419− blank <- option id ((++ [""]) <$ blankline)
420− return $ blank result
422−listStart :: PandocMonad m => MuseParser m Int -> MuseParser m Int
423−listStart marker = try $ do
424− preWhitespace <- length <$> many spaceChar
425− st <- stateParserContext <$> getState
426− getPosition >>= \pos -> guard (st == ListItemState || sourceColumn pos /= 1)
428+ let col = sourceColumn pos - 1
427− markerLength <- marker
429+ first <- try $ withListContext parseBlock
428− void spaceChar <|> eol
430+ rest <- many $ try (skipMany blankline >> indentWith col >> withListContext parseBlock)
429− return $ preWhitespace + markerLength + 1
431+ return $ mconcat (first : rest)
431−dropSpacePrefix :: [String] -> [String]
432−dropSpacePrefix lns =
433− map (drop maxIndent) lns
434− where flns = filter (not . all (== ' ')) lns
435− maxIndent = if null flns then 0 else length $ takeWhile (== ' ') $ foldl1 commonPrefix flns
437−listItemContents :: PandocMonad m => Int -> MuseParser m (F Blocks)
438−listItemContents markerLength = do
439− firstLine <- manyTill anyChar eol
440− restLines <- many $ listLine markerLength
441− blank <- option id ((++ [""]) <$ blankline)
442− let first = firstLine : blank restLines
443− rest <- many $ listContinuation markerLength
444− let allLines = concat (first : rest)
445− parseFromString (withListContext parseBlocks) $ unlines (dropSpacePrefix allLines)
447−listItem :: PandocMonad m => MuseParser m Int -> MuseParser m (F Blocks)
448−listItem start = try $ do
449− markerLength <- start
450− listItemContents markerLength
452−bulletListItems :: PandocMonad m => MuseParser m (F [Blocks])
453−bulletListItems = sequence <$> many1 (listItem bulletListStart)
455−bulletListStart :: PandocMonad m => MuseParser m Int
433+listItem :: PandocMonad m => Int -> MuseParser m () -> MuseParser m (F Blocks)
456−bulletListStart = listStart (char '-' >> return 1)
434+listItem n p = try $ do
435+ optionMaybe blankline
438+ void spaceChar <|> lookAhead eol
458bulletList :: PandocMonad m => MuseParser m (F Blocks)
441bulletList :: PandocMonad m => MuseParser m (F Blocks)
459−bulletList = do
442+bulletList = try $ do
460− listItems <- bulletListItems
443+ many spaceChar
445+ let col = sourceColumn pos
448+ void spaceChar <|> lookAhead eol
449+ first <- listItemContents
450+ rest <- many $ listItem (col - 1) (void (char '-'))
461− return $ B.bulletList <$> listItems
451+ return $ B.bulletList <$> sequence (first : rest)
463−orderedListStart :: PandocMonad m
467−orderedListStart style delim = listStart (snd <$> withHorizDisplacement (orderedListMarker style delim))
469orderedList :: PandocMonad m => MuseParser m (F Blocks)
453orderedList :: PandocMonad m => MuseParser m (F Blocks)
470orderedList = try $ do
454orderedList = try $ do
457+ let col = sourceColumn pos
471− p@(_, style, delim) <- lookAhead (many spaceChar *> anyOrderedListMarker <* (eol <|> void spaceChar))
459+ p@(_, style, delim) <- anyOrderedListMarker
472 guard $ style `elem` [Decimal, LowerAlpha, UpperAlpha, LowerRoman, UpperRoman]
460 guard $ style `elem` [Decimal, LowerAlpha, UpperAlpha, LowerRoman, UpperRoman]
473 guard $ delim == Period
461 guard $ delim == Period
474− items <- sequence <$> many1 (listItem $ orderedListStart style delim)
462+ void spaceChar <|> lookAhead eol
463+ first <- listItemContents
464+ rest <- many $ listItem (col - 1) (void (orderedListMarker style delim))
475− return $ B.orderedListWith p <$> items
465+ return $ B.orderedListWith p <$> sequence (first : rest)
477definitionListItem :: PandocMonad m => MuseParser m (F (Inlines, [Blocks]))
467definitionListItem :: PandocMonad m => MuseParser m (F (Inlines, [Blocks]))
478definitionListItem = try $ do
468definitionListItem = try $ do
@@ -482,7 +472,7 @@ definitionListItem = try $ do
482 string "::"
472 string "::"
483 firstLine <- manyTill anyChar eol
473 firstLine <- manyTill anyChar eol
484 restLines <- manyTill anyLine endOfListItemElement
474 restLines <- manyTill anyLine endOfListItemElement
485− let lns = dropWhile (== ' ') firstLine : dropSpacePrefix restLines
475+ let lns = dropWhile (== ' ') firstLine : restLines
486 lineContent <- parseFromString (withListContext parseBlocks) $ unlines lns
476 lineContent <- parseFromString (withListContext parseBlocks) $ unlines lns
487 pure $ do lineContent' <- lineContent
477 pure $ do lineContent' <- lineContent
488 term' <- term
478 term' <- term
@@ -501,8 +491,8 @@ definitionListItems = sequence <$> many1 definitionListItem
502definitionList :: PandocMonad m => MuseParser m (F Blocks)
492definitionList :: PandocMonad m => MuseParser m (F Blocks)
503definitionList = do
493definitionList = do
504− listItems <- definitionListItems
494+ items <- definitionListItems
505− return $ B.definitionList <$> listItems
495+ return $ B.definitionList <$> items