@@ -284,6 +284,11 @@ block = choice [ mempty <$ blanklines
284284 ] <?> "block"
285285
286286
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+
287292--
288293-- Block Attributes
289294--
@@ -522,28 +527,70 @@ trailingResultsBlock = optionMaybe . try $ do
522527 block
523528
524529-- | Parse code block arguments
525−-- TODO: We currently don't handle switches.
526530codeHeaderArgs :: Monad m => OrgParser m ([String], [(String, String)])
527531codeHeaderArgs = try $ do
528532 language <- skipSpaces *> orgArgWord
529− _ <- skipSpaces *> (try $ switch `sepBy` (many1 spaceChar))
533+ (switchClasses, switchKv) <- switchesAsAttributes
530534 parameters <- manyTill blockOption newline
531535 let pandocLang = translateLang language
536+ let classes = pandocLang : switchClasses
532537 return $
533538 if hasRundocParameters parameters
534− then ( [ pandocLang, rundocBlockClass ]
535− , map toRundocAttrib (("language", language) : parameters)
539+ then ( classes <> [ rundocBlockClass ]
540+ , switchKv <> map toRundocAttrib (("language", language) : parameters)
536541 )
537− else ([ pandocLang ], parameters)
542+ else (classes, switchKv <> parameters)
538543 where
539544 hasRundocParameters = not . null
540545
541−switch :: Monad m => OrgParser m (Char, Maybe String)
542−switch = try $ simpleSwitch <|> lineNumbersSwitch
546+switchesAsAttributes :: Monad m => OrgParser m ([String], [(String, String)])
547+switchesAsAttributes = try $ do
548+ switches <- skipSpaces *> (try $ switch `sepBy` (many1 spaceChar))
549+ return $ foldr addToAttr ([], []) switches
543550 where
544− simpleSwitch = (\c -> (c, Nothing)) <$> (oneOf "-+" *> letter)
545− lineNumbersSwitch = (\ls -> ('l', Just ls)) <$>
546− (string "-l \"" *> many1Till nonspaceChar (char '"'))
551+ addToAttr :: (Char, Maybe String, SwitchPolarity)
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' $
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)
547594
548595blockOption :: Monad m => OrgParser m (String, String)
549596blockOption = try $ do
@@ -558,9 +605,6 @@ orgParamValue = try $
558605 *> many1 nonspaceChar
559606 <* skipSpaces
560607
561−horizontalRule :: Monad m => OrgParser m (F Blocks)
562−horizontalRule = return B.horizontalRule <$ try hline
563−
564608
565609--
566610-- Drawers