git.iko.soy/typeable/pandoc
on master help sign in
Org reader: handle line numbering switch for src blocks
04658c4Albert Krewinkel
src/Text/Pandoc/Readers/Org/Blocks.hs+57−13
@@ -284,6 +284,11 @@ block = choice [ mempty <$ blanklines
284 ] <?> "block"
284 ] <?> "block"
285
285
286
286
287+-- | Parse a horizontal rule into a block element
288+horizontalRule :: Monad m => OrgParser m (F Blocks)
289+horizontalRule = return B.horizontalRule <$ try hline
290+
291+
287--
292--
288-- Block Attributes
293-- Block Attributes
289--
294--
@@ -522,28 +527,70 @@ trailingResultsBlock = optionMaybe . try $ do
522 block
527 block
523
528
524-- | Parse code block arguments
529-- | Parse code block arguments
525−-- TODO: We currently don't handle switches.
526codeHeaderArgs :: Monad m => OrgParser m ([String], [(String, String)])
530codeHeaderArgs :: Monad m => OrgParser m ([String], [(String, String)])
527codeHeaderArgs = try $ do
531codeHeaderArgs = try $ do
528 language <- skipSpaces *> orgArgWord
532 language <- skipSpaces *> orgArgWord
529− _ <- skipSpaces *> (try $ switch `sepBy` (many1 spaceChar))
533+ (switchClasses, switchKv) <- switchesAsAttributes
530 parameters <- manyTill blockOption newline
534 parameters <- manyTill blockOption newline
531 let pandocLang = translateLang language
535 let pandocLang = translateLang language
536+ let classes = pandocLang : switchClasses
532 return $
537 return $
533 if hasRundocParameters parameters
538 if hasRundocParameters parameters
534− then ( [ pandocLang, rundocBlockClass ]
539+ then ( classes <> [ rundocBlockClass ]
535− , map toRundocAttrib (("language", language) : parameters)
540+ , switchKv <> map toRundocAttrib (("language", language) : parameters)
536 )
541 )
537− else ([ pandocLang ], parameters)
542+ else (classes, switchKv <> parameters)
538 where
543 where
539 hasRundocParameters = not . null
544 hasRundocParameters = not . null
540
545
541−switch :: Monad m => OrgParser m (Char, Maybe String)
546+switchesAsAttributes :: Monad m => OrgParser m ([String], [(String, String)])
542−switch = try $ simpleSwitch <|> lineNumbersSwitch
547+switchesAsAttributes = try $ do
548+ switches <- skipSpaces *> (try $ switch `sepBy` (many1 spaceChar))
549+ return $ foldr addToAttr ([], []) switches
543 where
550 where
544− simpleSwitch = (\c -> (c, Nothing)) <$> (oneOf "-+" *> letter)
551+ addToAttr :: (Char, Maybe String, SwitchPolarity)
545− lineNumbersSwitch = (\ls -> ('l', Just ls)) <$>
552+ -> ([String], [(String, String)])
553+ -> ([String], [(String, String)])
554+ addToAttr ('n', lineNum, pol) (cls, kv) =
555+ let kv' = case lineNum of
556+ Just num -> (("startFrom", num):kv)
557+ Nothing -> kv
558+ cls' = case pol of
559+ SwitchPlus -> "continuedSourceBlock":cls
560+ SwitchMinus -> cls
561+ in ("numberLines":cls', kv')
562+ addToAttr _ x = x
563+
564+-- | Whether a switch flag is specified with @+@ or @-@.
565+data SwitchPolarity = SwitchPlus | SwitchMinus
566+ deriving (Show, Eq)
567+
568+-- | Parses a switch's polarity.
569+switchPolarity :: Monad m => OrgParser m SwitchPolarity
570+switchPolarity = (SwitchMinus <$ char '-') <|> (SwitchPlus <$ char '+')
571+
572+-- | Parses a source block switch option.
573+switch :: Monad m => OrgParser m (Char, Maybe String, SwitchPolarity)
574+switch = try $ lineNumberSwitch <|> labelSwitch <|> simpleSwitch
575+ where
576+ simpleSwitch = (\pol c -> (c, Nothing, pol)) <$> switchPolarity <*> letter
577+ labelSwitch = genericSwitch 'l' $
546− (string "-l \"" *> many1Till nonspaceChar (char '"'))
578+ char '"' *> many1Till nonspaceChar (char '"')
579+
580+-- | Generic source block switch-option parser.
581+genericSwitch :: Monad m
582+ => Char
583+ -> OrgParser m String
584+ -> OrgParser m (Char, Maybe String, SwitchPolarity)
585+genericSwitch c p = try $ do
586+ polarity <- switchPolarity <* char c <* skipSpaces
587+ arg <- optionMaybe p
588+ return $ (c, arg, polarity)
589+
590+-- | Reads a line number switch option. The line number switch can be used with
591+-- example and source blocks.
592+lineNumberSwitch :: Monad m => OrgParser m (Char, Maybe String, SwitchPolarity)
593+lineNumberSwitch = genericSwitch 'n' (many digit)
547
594
548blockOption :: Monad m => OrgParser m (String, String)
595blockOption :: Monad m => OrgParser m (String, String)
549blockOption = try $ do
596blockOption = try $ do
@@ -558,9 +605,6 @@ orgParamValue = try $
558 *> many1 nonspaceChar
605 *> many1 nonspaceChar
559 <* skipSpaces
606 <* skipSpaces
560
607
561−horizontalRule :: Monad m => OrgParser m (F Blocks)
562−horizontalRule = return B.horizontalRule <$ try hline
563−
564
608
565--
609--
566-- Drawers
610-- Drawers
test/Tests/Readers/Org.hs+9
@@ -1556,6 +1556,15 @@ tests =
1556 params = [ ("rundoc-language", "sh"), ("rundoc-noeval", "yes") ]
1556 params = [ ("rundoc-language", "sh"), ("rundoc-noeval", "yes") ]
1557 in codeBlockWith ("", classes, params) "echo $HOME\n"
1557 in codeBlockWith ("", classes, params) "echo $HOME\n"
1558
1558
1559+ , "Source block with line number switch" =:
1560+ unlines [ "#+BEGIN_SRC sh -n 10"
1561+ , ":() { :|:& };:"
1562+ , "#+END_SRC"
1563+ ] =?>
1564+ let classes = [ "bash", "numberLines" ]
1565+ params = [ ("startFrom", "10") ]
1566+ in codeBlockWith ("", classes, params) ":() { :|:& };:\n"
1567+
1559 , "Example block" =:
1568 , "Example block" =:
1560 unlines [ "#+begin_example"
1569 unlines [ "#+begin_example"
1561 , "A chosen representation of"
1570 , "A chosen representation of"