git.iko.soy/typeable/pandoc
on master help sign in
Org reader: modify handling of example blocks. (#5717)
0558ea9Brian Leung
src/Text/Pandoc/Readers/Org/Blocks.hs+41−14
@@ -186,7 +186,7 @@ orgBlock = try $ do
186 "html" -> rawBlockLines (return . B.rawBlock (lowercase blkType))
186 "html" -> rawBlockLines (return . B.rawBlock (lowercase blkType))
187 "latex" -> rawBlockLines (return . B.rawBlock (lowercase blkType))
187 "latex" -> rawBlockLines (return . B.rawBlock (lowercase blkType))
188 "ascii" -> rawBlockLines (return . B.rawBlock (lowercase blkType))
188 "ascii" -> rawBlockLines (return . B.rawBlock (lowercase blkType))
189− "example" -> rawBlockLines (return . exampleCode)
189+ "example" -> exampleBlock blockAttrs
190 "quote" -> parseBlockLines (fmap B.blockQuote)
190 "quote" -> parseBlockLines (fmap B.blockQuote)
191 "verse" -> verseBlock
191 "verse" -> verseBlock
192 "src" -> codeBlock blockAttrs
192 "src" -> codeBlock blockAttrs
@@ -200,6 +200,16 @@ orgBlock = try $ do
200 lowercase :: String -> String
200 lowercase :: String -> String
201 lowercase = map toLower
201 lowercase = map toLower
202
202
203+exampleBlock :: PandocMonad m => BlockAttributes -> String -> OrgParser m (F Blocks)
204+exampleBlock blockAttrs _label = do
205+ skipSpaces
206+ (classes, kv) <- switchesAsAttributes
207+ newline
208+ content <- rawBlockContent "example"
209+ let id' = fromMaybe mempty $ blockAttrName blockAttrs
210+ let codeBlck = B.codeBlockWith (id', "example":classes, kv) content
211+ return . return $ codeBlck
212+
203rawBlockLines :: Monad m => (String -> F Blocks) -> String -> OrgParser m (F Blocks)
213rawBlockLines :: Monad m => (String -> F Blocks) -> String -> OrgParser m (F Blocks)
204rawBlockLines f blockType = ignHeaders *> (f <$> rawBlockContent blockType)
214rawBlockLines f blockType = ignHeaders *> (f <$> rawBlockContent blockType)
205
215
@@ -216,11 +226,13 @@ rawBlockContent :: Monad m => String -> OrgParser m String
216rawBlockContent blockType = try $ do
226rawBlockContent blockType = try $ do
217 blkLines <- manyTill rawLine blockEnder
227 blkLines <- manyTill rawLine blockEnder
218 tabLen <- getOption readerTabStop
228 tabLen <- getOption readerTabStop
219− return
229+ trimP <- orgStateTrimLeadBlkIndent <$> getState
230+ let stripIndent strs = if trimP then map (drop (shortestIndent strs)) strs else strs
220− . unlines
231+ (unlines
221− . stripIndent
232+ . stripIndent
222− . map (tabsToSpaces tabLen . commaEscaped)
233+ . map (tabsToSpaces tabLen . commaEscaped)
223− $ blkLines
234+ $ blkLines)
235+ <$ updateState (\s -> s { orgStateTrimLeadBlkIndent = True })
224 where
236 where
225 rawLine :: Monad m => OrgParser m String
237 rawLine :: Monad m => OrgParser m String
226 rawLine = try $ ("" <$ blankline) <|> anyLine
238 rawLine = try $ ("" <$ blankline) <|> anyLine
@@ -228,9 +240,6 @@ rawBlockContent blockType = try $ do
228 blockEnder :: Monad m => OrgParser m ()
240 blockEnder :: Monad m => OrgParser m ()
229 blockEnder = try $ skipSpaces <* stringAnyCase ("#+end_" <> blockType)
241 blockEnder = try $ skipSpaces <* stringAnyCase ("#+end_" <> blockType)
230
242
231− stripIndent :: [String] -> [String]
232− stripIndent strs = map (drop (shortestIndent strs)) strs
233−
234 shortestIndent :: [String] -> Int
243 shortestIndent :: [String] -> Int
235 shortestIndent = foldr (min . length . takeWhile isSpace) maxBound
244 shortestIndent = foldr (min . length . takeWhile isSpace) maxBound
236 . filter (not . null)
245 . filter (not . null)
@@ -357,12 +366,19 @@ switchPolarity = (SwitchMinus <$ char '-') <|> (SwitchPlus <$ char '+')
357
366
358-- | Parses a source block switch option.
367-- | Parses a source block switch option.
359switch :: Monad m => OrgParser m (Char, Maybe String, SwitchPolarity)
368switch :: Monad m => OrgParser m (Char, Maybe String, SwitchPolarity)
360−switch = try $ lineNumberSwitch <|> labelSwitch <|> simpleSwitch
369+switch = try $ lineNumberSwitch <|> labelSwitch
370+ <|> whitespaceSwitch <|> simpleSwitch
361 where
371 where
362 simpleSwitch = (\pol c -> (c, Nothing, pol)) <$> switchPolarity <*> letter
372 simpleSwitch = (\pol c -> (c, Nothing, pol)) <$> switchPolarity <*> letter
363 labelSwitch = genericSwitch 'l' $
373 labelSwitch = genericSwitch 'l' $
364 char '"' *> many1Till nonspaceChar (char '"')
374 char '"' *> many1Till nonspaceChar (char '"')
365
375
376+whitespaceSwitch :: Monad m => OrgParser m (Char, Maybe String, SwitchPolarity)
377+whitespaceSwitch = do
378+ string "-i"
379+ updateState $ \s -> s { orgStateTrimLeadBlkIndent = False }
380+ return ('i', Nothing, SwitchMinus)
381+
366-- | Generic source block switch-option parser.
382-- | Generic source block switch-option parser.
367genericSwitch :: Monad m
383genericSwitch :: Monad m
368 => Char
384 => Char
@@ -821,11 +837,22 @@ listItem parseIndentedMarker = try . withContext ListItemState $ do
821
837
822-- continuation of a list item - indented and separated by blankline or endline.
838-- continuation of a list item - indented and separated by blankline or endline.
823-- Note: nested lists are parsed as continuations.
839-- Note: nested lists are parsed as continuations.
824−listContinuation :: Monad m => Int
840+listContinuation :: PandocMonad m => Int -> OrgParser m String
825− -> OrgParser m String
826listContinuation markerLength = try $ do
841listContinuation markerLength = try $ do
827 notFollowedBy' blankline
842 notFollowedBy' blankline
828− mappend <$> (concat <$> many1 listLine)
843+ mappend <$> (concat <$> many1 (listContinuation' markerLength))
829 <*> many blankline
844 <*> many blankline
830 where
845 where
846+ listContinuation' indentation =
847+ blockLines indentation <|> listLine indentation
831− listLine = try $ indentWith markerLength *> anyLineNewline
848+ listLine indentation = try $ indentWith indentation *> anyLineNewline
849+ -- The block attributes and start must be appropriately indented,
850+ -- but the contents, and end do not.
851+ blockLines indentation =
852+ try $ lookAhead (indentWith indentation
853+ >> blockAttributes
854+ >>= (\blockAttrs ->
855+ case attrFromBlockAttributes blockAttrs of
856+ ("", [], []) -> count 1 anyChar
857+ _ -> indentWith indentation))
858+ >> (snd <$> withRaw orgBlock)
src/Text/Pandoc/Readers/Org/ParserState.hs+2
@@ -117,6 +117,7 @@ data OrgParserState = OrgParserState
117 , orgStateSelectTags :: Set.Set Tag
117 , orgStateSelectTags :: Set.Set Tag
118 , orgStateSelectTagsChanged :: Bool
118 , orgStateSelectTagsChanged :: Bool
119 , orgStateTodoSequences :: [TodoSequence]
119 , orgStateTodoSequences :: [TodoSequence]
120+ , orgStateTrimLeadBlkIndent :: Bool
120 , orgLogMessages :: [LogMessage]
121 , orgLogMessages :: [LogMessage]
121 , orgMacros :: M.Map Text Macro
122 , orgMacros :: M.Map Text Macro
122 }
123 }
@@ -184,6 +185,7 @@ defaultOrgParserState = OrgParserState
184 , orgStateParserContext = NullState
185 , orgStateParserContext = NullState
185 , orgStateSelectTags = Set.singleton $ Tag "export"
186 , orgStateSelectTags = Set.singleton $ Tag "export"
186 , orgStateSelectTagsChanged = False
187 , orgStateSelectTagsChanged = False
188+ , orgStateTrimLeadBlkIndent = True
187 , orgStateTodoSequences = []
189 , orgStateTodoSequences = []
188 , orgLogMessages = []
190 , orgLogMessages = []
189 , orgMacros = M.empty
191 , orgMacros = M.empty
test/command/4186.mdnew file+60
@@ -0,0 +1,60 @@
1+```
2+% pandoc -f org -t native
3+#+BEGIN_EXAMPLE -i
4+ This should retain the four leading spaces
5+#+END_EXAMPLE
6+^D
7+[CodeBlock ("",["example"],[]) " This should retain the four leading spaces\n"]
8+```
9+
10+```
11+% pandoc -f org -t html
12+- depth 1
13+ #+NAME: bob
14+ #+BEGIN_EXAMPLE -i
15+ Vertical alignment is four spaces beyond the appearance of the word "depth".
16+ #+END_EXAMPLE
17+ - depth 2
18+ #+begin_example
19+ Vertically aligned with the second appearance of the word "depth".
20+ #+end_example
21+ #+begin_example -i
22+ Vertical alignment is four spaces beyond the second
23+ appearance of the word "depth".
24+ The "begin" portion is a component of
25+ this deeper list element, so that guarantees
26+ that the entire block must be a component of the
27+ inner list element.
28+ #+end_example
29+ Still inside the inner list element
30+ #+NAME: carrie
31+ #+BEGIN_EXAMPLE
32+ This belongs to the outer list element, and is aligned accordingly, since the NAME attribute is not indented deeply enough. It is not enough for the BEGIN alone to be aligned deeply if the block is meant to have a NAME.
33+ #+END_EXAMPLE
34+ Still in the shallower list element since the preceding example
35+ block forced the deeper list element to terminate.
36+Outside all lists.
37+^D
38+<ul>
39+<li><p>depth 1</p>
40+<pre id="bob" class="example"><code> Vertical alignment is four spaces beyond the appearance of the word &quot;depth&quot;.
41+</code></pre>
42+<ul>
43+<li><p>depth 2</p>
44+<pre class="example"><code>Vertically aligned with the second appearance of the word &quot;depth&quot;.
45+</code></pre>
46+<pre class="example"><code> Vertical alignment is four spaces beyond the second
47+ appearance of the word &quot;depth&quot;.
48+ The &quot;begin&quot; portion is a component of
49+ this deeper list element, so that guarantees
50+ that the entire block must be a component of the
51+ inner list element.
52+</code></pre>
53+<p>Still inside the inner list element</p></li>
54+</ul>
55+<pre id="carrie" class="example"><code>This belongs to the outer list element, and is aligned accordingly, since the NAME attribute is not indented deeply enough. It is not enough for the BEGIN alone to be aligned deeply if the block is meant to have a NAME.
56+</code></pre>
57+<p>Still in the shallower list element since the preceding example block forced the deeper list element to terminate.</p></li>
58+</ul>
59+<p>Outside all lists.</p>
60+```