git.iko.soy/typeable/pandoc
on master help sign in
Org reader: Add partial support for `#+EXCLUDE_TAGS` option. (#4950)
a26b3a2Brian Leung
src/Text/Pandoc/Readers/Org/DocumentTree.hs+7−7
@@ -43,6 +43,7 @@ import Text.Pandoc.Readers.Org.BlockStarts
43import Text.Pandoc.Readers.Org.ParserState
43import Text.Pandoc.Readers.Org.ParserState
44import Text.Pandoc.Readers.Org.Parsing
44import Text.Pandoc.Readers.Org.Parsing
45
45
46+import qualified Data.Set as Set
46import qualified Text.Pandoc.Builder as B
47import qualified Text.Pandoc.Builder as B
47
48
48--
49--
@@ -73,9 +74,6 @@ documentTree blocks inline = do
73 , headlineChildren = headlines'
74 , headlineChildren = headlines'
74 }
75 }
75
76
76−newtype Tag = Tag { fromTag :: String }
77− deriving (Show, Eq)
78−
79-- | Create a tag containing the given string.
77-- | Create a tag containing the given string.
80toTag :: String -> Tag
78toTag :: String -> Tag
81toTag = Tag
79toTag = Tag
@@ -153,7 +151,7 @@ headline blocks inline lvl = try $ do
153
151
154 headerTags :: Monad m => OrgParser m [Tag]
152 headerTags :: Monad m => OrgParser m [Tag]
155 headerTags = try $
153 headerTags = try $
156− let tag = many1 (alphaNum <|> oneOf "@%#_") <* char ':'
154+ let tag = orgTagWord <* char ':'
157 in map toTag <$> (skipSpaces *> char ':' *> many1 tag <* skipSpaces)
155 in map toTag <$> (skipSpaces *> char ':' *> many1 tag <* skipSpaces)
158
156
159-- | Convert an Org mode headline (i.e. a document tree) into pandoc's Blocks
157-- | Convert an Org mode headline (i.e. a document tree) into pandoc's Blocks
@@ -163,15 +161,17 @@ headlineToBlocks hdln = do
163 let tags = headlineTags hdln
161 let tags = headlineTags hdln
164 let text = headlineText hdln
162 let text = headlineText hdln
165 let level = headlineLevel hdln
163 let level = headlineLevel hdln
164+ shouldNotExport <- hasDoNotExportTag tags
166 case () of
165 case () of
167− _ | any isNoExportTag tags -> return mempty
166+ _ | shouldNotExport -> return mempty
168 _ | any isArchiveTag tags -> archivedHeadlineToBlocks hdln
167 _ | any isArchiveTag tags -> archivedHeadlineToBlocks hdln
169 _ | isCommentTitle text -> return mempty
168 _ | isCommentTitle text -> return mempty
170 _ | maxLevel <= level -> headlineToHeaderWithList hdln
169 _ | maxLevel <= level -> headlineToHeaderWithList hdln
171 _ | otherwise -> headlineToHeaderWithContents hdln
170 _ | otherwise -> headlineToHeaderWithContents hdln
172
171
173−isNoExportTag :: Tag -> Bool
172+hasDoNotExportTag :: Monad m => [Tag] -> OrgParser m Bool
174−isNoExportTag = (== toTag "noexport")
173+hasDoNotExportTag tags = containsExcludedTag . orgStateExcludedTags <$> getState
174+ where containsExcludedTag s = any (`Set.member` s) tags
175
175
176isArchiveTag :: Tag -> Bool
176isArchiveTag :: Tag -> Bool
177isArchiveTag = (== toTag "ARCHIVE")
177isArchiveTag = (== toTag "ARCHIVE")
src/Text/Pandoc/Readers/Org/Meta.hs+11
@@ -52,6 +52,7 @@ import Data.Char (toLower)
52import Data.List (intersperse)
52import Data.List (intersperse)
53import Data.Maybe (fromMaybe)
53import Data.Maybe (fromMaybe)
54import qualified Data.Map as M
54import qualified Data.Map as M
55+import qualified Data.Set as Set
55import Network.HTTP (urlEncode)
56import Network.HTTP (urlEncode)
56
57
57-- | Returns the current meta, respecting export options.
58-- | Returns the current meta, respecting export options.
@@ -158,6 +159,7 @@ optionLine = try $ do
158 "seq_todo" -> todoSequence >>= updateState . registerTodoSequence
159 "seq_todo" -> todoSequence >>= updateState . registerTodoSequence
159 "typ_todo" -> todoSequence >>= updateState . registerTodoSequence
160 "typ_todo" -> todoSequence >>= updateState . registerTodoSequence
160 "macro" -> macroDefinition >>= updateState . registerMacro
161 "macro" -> macroDefinition >>= updateState . registerMacro
162+ "exclude_tags" -> excludedTagSet >>= updateState . setExcludedTags
161 "pandoc-emphasis-pre" -> emphChars >>= updateState . setEmphasisPreChar
163 "pandoc-emphasis-pre" -> emphChars >>= updateState . setEmphasisPreChar
162 "pandoc-emphasis-post" -> emphChars >>= updateState . setEmphasisPostChar
164 "pandoc-emphasis-post" -> emphChars >>= updateState . setEmphasisPostChar
163 _ -> mzero
165 _ -> mzero
@@ -190,6 +192,15 @@ parseFormat = try $ replacePlain <|> replaceUrl <|> justAppend
190 rest = manyTill anyChar (eof <|> () <$ oneOf "\n\r")
192 rest = manyTill anyChar (eof <|> () <$ oneOf "\n\r")
191 tillSpecifier c = manyTill (noneOf "\n\r") (try $ string ('%':c:""))
193 tillSpecifier c = manyTill (noneOf "\n\r") (try $ string ('%':c:""))
192
194
195+excludedTagSet :: Monad m => OrgParser m (Set.Set Tag)
196+excludedTagSet = do
197+ skipSpaces
198+ Set.fromList . map Tag <$>
199+ many (orgTagWord <* skipSpaces) <* newline
200+
201+setExcludedTags :: Set.Set Tag -> OrgParserState -> OrgParserState
202+setExcludedTags tagSet st = st { orgStateExcludedTags = tagSet }
203+
193setEmphasisPreChar :: Maybe [Char] -> OrgParserState -> OrgParserState
204setEmphasisPreChar :: Maybe [Char] -> OrgParserState -> OrgParserState
194setEmphasisPreChar csMb st =
205setEmphasisPreChar csMb st =
195 let preChars = fromMaybe (orgStateEmphasisPostChars defaultOrgParserState) csMb
206 let preChars = fromMaybe (orgStateEmphasisPostChars defaultOrgParserState) csMb
src/Text/Pandoc/Readers/Org/ParserState.hs+6
@@ -33,6 +33,7 @@ module Text.Pandoc.Readers.Org.ParserState
33 , defaultOrgParserState
33 , defaultOrgParserState
34 , OrgParserLocal (..)
34 , OrgParserLocal (..)
35 , OrgNoteRecord
35 , OrgNoteRecord
36+ , Tag(..)
36 , HasReaderOptions (..)
37 , HasReaderOptions (..)
37 , HasQuoteContext (..)
38 , HasQuoteContext (..)
38 , HasMacros (..)
39 , HasMacros (..)
@@ -88,6 +89,9 @@ type OrgNoteTable = [OrgNoteRecord]
88type OrgLinkFormatters = M.Map String (String -> String)
89type OrgLinkFormatters = M.Map String (String -> String)
89-- | Macro expander function
90-- | Macro expander function
90type MacroExpander = [String] -> String
91type MacroExpander = [String] -> String
92+-- | Tag
93+newtype Tag = Tag { fromTag :: String }
94+ deriving (Show, Eq, Ord)
91
95
92-- | The states in which a todo item can be
96-- | The states in which a todo item can be
93data TodoState = Todo | Done
97data TodoState = Todo | Done
@@ -113,6 +117,7 @@ data OrgParserState = OrgParserState
113 -- specified here.
117 -- specified here.
114 , orgStateEmphasisPostChars :: [Char] -- ^ Chars allowed at after emphasis
118 , orgStateEmphasisPostChars :: [Char] -- ^ Chars allowed at after emphasis
115 , orgStateEmphasisNewlines :: Maybe Int
119 , orgStateEmphasisNewlines :: Maybe Int
120+ , orgStateExcludedTags :: Set.Set Tag
116 , orgStateExportSettings :: ExportSettings
121 , orgStateExportSettings :: ExportSettings
117 , orgStateHeaderMap :: M.Map Inlines String
122 , orgStateHeaderMap :: M.Map Inlines String
118 , orgStateIdentifiers :: Set.Set String
123 , orgStateIdentifiers :: Set.Set String
@@ -183,6 +188,7 @@ defaultOrgParserState = OrgParserState
183 , orgStateEmphasisCharStack = []
188 , orgStateEmphasisCharStack = []
184 , orgStateEmphasisNewlines = Nothing
189 , orgStateEmphasisNewlines = Nothing
185 , orgStateExportSettings = def
190 , orgStateExportSettings = def
191+ , orgStateExcludedTags = Set.singleton $ Tag "noexport"
186 , orgStateHeaderMap = M.empty
192 , orgStateHeaderMap = M.empty
187 , orgStateIdentifiers = Set.empty
193 , orgStateIdentifiers = Set.empty
188 , orgStateIncludeFiles = []
194 , orgStateIncludeFiles = []
src/Text/Pandoc/Readers/Org/Parsing.hs+8
@@ -46,6 +46,8 @@ module Text.Pandoc.Readers.Org.Parsing
46 , orgArgKey
46 , orgArgKey
47 , orgArgWord
47 , orgArgWord
48 , orgArgWordChar
48 , orgArgWordChar
49+ , orgTagWord
50+ , orgTagWordChar
49 -- * Re-exports from Text.Pandoc.Parser
51 -- * Re-exports from Text.Pandoc.Parser
50 , ParserContext (..)
52 , ParserContext (..)
51 , many1Till
53 , many1Till
@@ -220,3 +222,9 @@ orgArgWord = many1 orgArgWordChar
220-- | Chars treated as part of a word in plists.
222-- | Chars treated as part of a word in plists.
221orgArgWordChar :: Monad m => OrgParser m Char
223orgArgWordChar :: Monad m => OrgParser m Char
222orgArgWordChar = alphaNum <|> oneOf "-_"
224orgArgWordChar = alphaNum <|> oneOf "-_"
225+
226+orgTagWord :: Monad m => OrgParser m String
227+orgTagWord = many1 orgTagWordChar
228+
229+orgTagWordChar :: Monad m => OrgParser m Char
230+orgTagWordChar = alphaNum <|> oneOf "@%#_"
test/command/4284.mdnew file+29
@@ -0,0 +1,29 @@
1+```
2+% pandoc -f org -t native
3+#+EXCLUDE_TAGS:apple cat bye dog %
4+
5+* This should not appear :apple:
6+* NOEXPORT should appear if not specified in EXCLUDE_TAGS :noexport:
7+* This should not appear :cat:hi:laptop:
8+** Children of headers with excluded tags should not appear :xylophone:
9+* This should not appear :%:
10+^D
11+[Header 1 ("noexport-should-appear-if-not-specified-in-excludetags",[],[]) [Str "NOEXPORT",Space,Str "should",Space,Str "appear",Space,Str "if",Space,Str "not",Space,Str "specified",Space,Str "in",Space,Str "EXCLUDE",Subscript [Str "TAGS"],Space,Span ("",["tag"],[("tag-name","noexport")]) [SmallCaps [Str "noexport"]]]]
12+```
13+
14+```
15+% pandoc -f org -t native
16+#+EXCLUDE_TAGS:elephant
17+* This should not appear :elephant:
18+* This should appear :fawn:
19+^D
20+[Header 1 ("this-should-appear",[],[]) [Str "This",Space,Str "should",Space,Str "appear",Space,Span ("",["tag"],[("tag-name","fawn")]) [SmallCaps [Str "fawn"]]]]
21+```
22+
23+```
24+% pandoc -f org -t native
25+#+EXCLUDE_TAGS:
26+* NOEXPORT should appear if not specified in EXCLUDE_TAGS :noexport:
27+^D
28+[Header 1 ("noexport-should-appear-if-not-specified-in-excludetags",[],[]) [Str "NOEXPORT",Space,Str "should",Space,Str "appear",Space,Str "if",Space,Str "not",Space,Str "specified",Space,Str "in",Space,Str "EXCLUDE",Subscript [Str "TAGS"],Space,Span ("",["tag"],[("tag-name","noexport")]) [SmallCaps [Str "noexport"]]]]
29+```