From f6dfb632ff38cc9dd5156297959ce8028fd766ea Mon Sep 17 00:00:00 2001 From: Alexander Krotov Date: Mon, 2 Jul 2018 18:30:37 +0300 Subject: Spellcheck comments --- src/Text/Pandoc/Readers/Org/Blocks.hs | 2 +- src/Text/Pandoc/Readers/Org/Inlines.hs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/Text/Pandoc/Readers/Org') diff --git a/src/Text/Pandoc/Readers/Org/Blocks.hs b/src/Text/Pandoc/Readers/Org/Blocks.hs index 888cd9307..d2a749efb 100644 --- a/src/Text/Pandoc/Readers/Org/Blocks.hs +++ b/src/Text/Pandoc/Readers/Org/Blocks.hs @@ -743,7 +743,7 @@ latexEnd envName = try $ -- --- Footnote defintions +-- Footnote definitions -- noteBlock :: PandocMonad m => OrgParser m (F Blocks) noteBlock = try $ do diff --git a/src/Text/Pandoc/Readers/Org/Inlines.hs b/src/Text/Pandoc/Readers/Org/Inlines.hs index 7d1568b80..b7378e3e4 100644 --- a/src/Text/Pandoc/Readers/Org/Inlines.hs +++ b/src/Text/Pandoc/Readers/Org/Inlines.hs @@ -510,7 +510,7 @@ anchor = try $ do <* string ">>" <* skipSpaces --- | Replace every char but [a-zA-Z0-9_.-:] with a hypen '-'. This mirrors +-- | Replace every char but [a-zA-Z0-9_.-:] with a hyphen '-'. This mirrors -- the org function @org-export-solidify-link-text@. solidify :: String -> String -- cgit v1.2.3 From 4e899eb9c886df2200551f69a3f593ab5258f2e2 Mon Sep 17 00:00:00 2001 From: Albert Krewinkel Date: Mon, 23 Jul 2018 22:05:41 +0200 Subject: Org reader: fix parsers relying on parseFromString Emphasis was not parsed when it followed directly after some block types (e.g., lists). The org reader uses a wrapper for the `parseFromString` function to handle org-specific state. The last position of a character allowed before emphasis was reset incorrectly in this wrapper. Emphasized text was not recognized when placed directly behind a block which the reader parses using `parseFromString`. Fixes: #4784 --- src/Text/Pandoc/Readers/Org/Parsing.hs | 7 +++---- test/Tests/Readers/Org/Block/List.hs | 11 +++++++++++ 2 files changed, 14 insertions(+), 4 deletions(-) (limited to 'src/Text/Pandoc/Readers/Org') diff --git a/src/Text/Pandoc/Readers/Org/Parsing.hs b/src/Text/Pandoc/Readers/Org/Parsing.hs index e014de65e..b37b36624 100644 --- a/src/Text/Pandoc/Readers/Org/Parsing.hs +++ b/src/Text/Pandoc/Readers/Org/Parsing.hs @@ -137,14 +137,13 @@ anyLine = <* updateLastPreCharPos <* updateLastForbiddenCharPos --- The version Text.Pandoc.Parsing cannot be used, as we need additional parts --- of the state saved and restored. +-- | Like @'Text.Pandoc.Parsing'@, but resets the position of the last character +-- allowed before emphasised text. parseFromString :: Monad m => OrgParser m a -> String -> OrgParser m a parseFromString parser str' = do - oldLastPreCharPos <- orgStateLastPreCharPos <$> getState updateState $ \s -> s{ orgStateLastPreCharPos = Nothing } result <- P.parseFromString parser str' - updateState $ \s -> s{ orgStateLastPreCharPos = oldLastPreCharPos } + updateState $ \s -> s { orgStateLastPreCharPos = Nothing } return result -- | Skip one or more tab or space characters. diff --git a/test/Tests/Readers/Org/Block/List.hs b/test/Tests/Readers/Org/Block/List.hs index f273b684d..bdab01404 100644 --- a/test/Tests/Readers/Org/Block/List.hs +++ b/test/Tests/Readers/Org/Block/List.hs @@ -243,4 +243,15 @@ tests = mconcat [ para "CLOSED: [2015-10-19 Mon 15:03]" , bulletList [ plain "Note taken on [2015-10-19 Mon 13:24]" ] ] + + , "Markup after header and list" =: + T.unlines [ "* headline" + , "- list" + , "" + , "~variable name~" + ] =?> + mconcat [ headerWith ("headline", [], []) 1 "headline" + , bulletList [ plain "list" ] + , para (code "variable name") + ] ] -- cgit v1.2.3 From ceec26f6471d3c1cbd971cf7701144ccd5bbfdca Mon Sep 17 00:00:00 2001 From: Albert Krewinkel Date: Wed, 5 Sep 2018 14:26:06 +0200 Subject: Org reader: strip planning info from output Planning info is parsed, but not included in the output (as is the default with Emacs Org-mode). Fixes: #4867 --- src/Text/Pandoc/Readers/Org/DocumentTree.hs | 36 ++++++++++++++++++++++++++++- test/Tests/Readers/Org/Block/Header.hs | 25 ++++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) (limited to 'src/Text/Pandoc/Readers/Org') diff --git a/src/Text/Pandoc/Readers/Org/DocumentTree.hs b/src/Text/Pandoc/Readers/Org/DocumentTree.hs index c9465581a..8e2f080f2 100644 --- a/src/Text/Pandoc/Readers/Org/DocumentTree.hs +++ b/src/Text/Pandoc/Readers/Org/DocumentTree.hs @@ -70,6 +70,7 @@ documentTree blocks inline = do , headlineTodoMarker = Nothing , headlineText = B.fromList title' , headlineTags = mempty + , headlinePlanning = emptyPlanning , headlineProperties = mempty , headlineContents = initialBlocks' , headlineChildren = headlines' @@ -117,6 +118,7 @@ data Headline = Headline , headlineTodoMarker :: Maybe TodoMarker , headlineText :: Inlines , headlineTags :: [Tag] + , headlinePlanning :: PlanningInfo -- ^ subtree planning information , headlineProperties :: Properties , headlineContents :: Blocks , headlineChildren :: [Headline] @@ -136,6 +138,7 @@ headline blocks inline lvl = try $ do title <- trimInlinesF . mconcat <$> manyTill inline endOfTitle tags <- option [] headerTags newline + planning <- option emptyPlanning planningInfo properties <- option mempty propertiesDrawer contents <- blocks children <- many (headline blocks inline (level + 1)) @@ -148,6 +151,7 @@ headline blocks inline lvl = try $ do , headlineTodoMarker = todoKw , headlineText = title' , headlineTags = tags + , headlinePlanning = planning , headlineProperties = properties , headlineContents = contents' , headlineChildren = children' @@ -277,9 +281,39 @@ tagsToInlines tags = tagSpan :: Tag -> Inlines -> Inlines tagSpan t = B.spanWith ("", ["tag"], [("tag-name", fromTag t)]) +-- | An Org timestamp, including repetition marks. TODO: improve +type Timestamp = String + +timestamp :: Monad m => OrgParser m Timestamp +timestamp = try $ do + openChar <- oneOf "<[" + let isActive = openChar == '<' + let closeChar = if isActive then '>' else ']' + content <- many1Till anyChar (char closeChar) + return (openChar : content ++ [closeChar]) + +-- | Planning information for a subtree/headline. +data PlanningInfo = PlanningInfo + { planningClosed :: Maybe Timestamp + , planningDeadline :: Maybe Timestamp + , planningScheduled :: Maybe Timestamp + } +emptyPlanning :: PlanningInfo +emptyPlanning = PlanningInfo Nothing Nothing Nothing - +-- | Read a single planning-related and timestamped line. +planningInfo :: Monad m => OrgParser m PlanningInfo +planningInfo = try $ do + updaters <- many1 planningDatum <* skipSpaces <* newline + return $ foldr ($) emptyPlanning updaters + where + planningDatum = skipSpaces *> choice + [ updateWith (\s p -> p { planningScheduled = Just s}) "SCHEDULED" + , updateWith (\d p -> p { planningDeadline = Just d}) "DEADLINE" + , updateWith (\c p -> p { planningClosed = Just c}) "CLOSED" + ] + updateWith fn cs = fn <$> (string cs *> char ':' *> skipSpaces *> timestamp) -- | Read a :PROPERTIES: drawer and return the key/value pairs contained -- within. diff --git a/test/Tests/Readers/Org/Block/Header.hs b/test/Tests/Readers/Org/Block/Header.hs index 3b0d7dda9..6f38714cd 100644 --- a/test/Tests/Readers/Org/Block/Header.hs +++ b/test/Tests/Readers/Org/Block/Header.hs @@ -181,4 +181,29 @@ tests = , " :END:" ] =?> headerWith ("not-numbered", ["unnumbered"], []) 1 "Not numbered" + + , testGroup "planning information" + [ "Planning info is not included in output" =: + T.unlines [ "* important" + , T.unwords + [ "CLOSED: [2018-09-05 Wed 13:58]" + , "DEADLINE: <2018-09-17 Mon>" + , "SCHEDULED: <2018-09-10 Mon>" + ] + ] =?> + headerWith ("important", [], []) 1 "important" + + , "Properties after planning info are recognized" =: + T.unlines [ "* important " + , " " <> T.unwords + [ "CLOSED: [2018-09-05 Wed 13:58]" + , "DEADLINE: <2018-09-17 Mon>" + , "SCHEDULED: <2018-09-10 Mon>" + ] + , " :PROPERTIES:" + , " :custom_id: look" + , " :END:" + ] =?> + headerWith ("look", [], []) 1 "important" + ] ] -- cgit v1.2.3 From aac3d752e1f059d2727863a4705feef4e5a05f3e Mon Sep 17 00:00:00 2001 From: Albert Krewinkel Date: Thu, 6 Sep 2018 20:53:57 +0200 Subject: Org reader internals: disable some GHC extensions The RecordWildCards and ViewPatterns language extensions can be used to shorten code, but usually also makes it harder to read. The DocumentTree module was hence refactored and no longer relies on these extensions. --- src/Text/Pandoc/Readers/Org/DocumentTree.hs | 58 ++++++++++++++++------------- 1 file changed, 32 insertions(+), 26 deletions(-) (limited to 'src/Text/Pandoc/Readers/Org') diff --git a/src/Text/Pandoc/Readers/Org/DocumentTree.hs b/src/Text/Pandoc/Readers/Org/DocumentTree.hs index 8e2f080f2..6dd78560f 100644 --- a/src/Text/Pandoc/Readers/Org/DocumentTree.hs +++ b/src/Text/Pandoc/Readers/Org/DocumentTree.hs @@ -1,4 +1,3 @@ -{-# LANGUAGE NoImplicitPrelude #-} {- Copyright (C) 2014-2018 Albert Krewinkel @@ -17,8 +16,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} {-# LANGUAGE FlexibleContexts #-} -{-# LANGUAGE RecordWildCards #-} -{-# LANGUAGE ViewPatterns #-} +{-# LANGUAGE NoImplicitPrelude #-} {- | Module : Text.Pandoc.Readers.Org.DocumentTree Copyright : Copyright (C) 2014-2018 Albert Krewinkel @@ -167,14 +165,17 @@ headline blocks inline lvl = try $ do -- | Convert an Org mode headline (i.e. a document tree) into pandoc's Blocks headlineToBlocks :: Monad m => Headline -> OrgParser m Blocks -headlineToBlocks hdln@Headline {..} = do - maxHeadlineLevels <- getExportSetting exportHeadlineLevels +headlineToBlocks hdln = do + maxLevel <- getExportSetting exportHeadlineLevels + let tags = headlineTags hdln + let text = headlineText hdln + let level = headlineLevel hdln case () of - _ | any isNoExportTag headlineTags -> return mempty - _ | any isArchiveTag headlineTags -> archivedHeadlineToBlocks hdln - _ | isCommentTitle headlineText -> return mempty - _ | headlineLevel >= maxHeadlineLevels -> headlineToHeaderWithList hdln - _ | otherwise -> headlineToHeaderWithContents hdln + _ | any isNoExportTag tags -> return mempty + _ | any isArchiveTag tags -> archivedHeadlineToBlocks hdln + _ | isCommentTitle text -> return mempty + _ | maxLevel <= level -> headlineToHeaderWithList hdln + _ | otherwise -> headlineToHeaderWithContents hdln isNoExportTag :: Tag -> Bool isNoExportTag = (== toTag "noexport") @@ -186,8 +187,9 @@ isArchiveTag = (== toTag "ARCHIVE") -- FIXME: This accesses builder internals not intended for use in situations -- like these. Replace once keyword parsing is supported. isCommentTitle :: Inlines -> Bool -isCommentTitle (B.toList -> (Str "COMMENT":_)) = True -isCommentTitle _ = False +isCommentTitle inlns = case B.toList inlns of + (Str "COMMENT":_) -> True + _ -> False archivedHeadlineToBlocks :: Monad m => Headline -> OrgParser m Blocks archivedHeadlineToBlocks hdln = do @@ -198,17 +200,21 @@ archivedHeadlineToBlocks hdln = do ArchivedTreesHeadlineOnly -> headlineToHeader hdln headlineToHeaderWithList :: Monad m => Headline -> OrgParser m Blocks -headlineToHeaderWithList hdln@Headline {..} = do +headlineToHeaderWithList hdln = do maxHeadlineLevels <- getExportSetting exportHeadlineLevels header <- headlineToHeader hdln - listElements <- mapM headlineToBlocks headlineChildren + listElements <- mapM headlineToBlocks (headlineChildren hdln) let listBlock = if null listElements then mempty else B.orderedList listElements - let headerText = if maxHeadlineLevels == headlineLevel + let headerText = if maxHeadlineLevels == headlineLevel hdln then header else flattenHeader header - return $ headerText <> headlineContents <> listBlock + return . mconcat $ + [ headerText + , headlineContents hdln + , listBlock + ] where flattenHeader :: Blocks -> Blocks flattenHeader blks = @@ -217,27 +223,27 @@ headlineToHeaderWithList hdln@Headline {..} = do _ -> mempty headlineToHeaderWithContents :: Monad m => Headline -> OrgParser m Blocks -headlineToHeaderWithContents hdln@Headline {..} = do +headlineToHeaderWithContents hdln = do header <- headlineToHeader hdln - childrenBlocks <- mconcat <$> mapM headlineToBlocks headlineChildren - return $ header <> headlineContents <> childrenBlocks + childrenBlocks <- mconcat <$> mapM headlineToBlocks (headlineChildren hdln) + return $ header <> headlineContents hdln <> childrenBlocks headlineToHeader :: Monad m => Headline -> OrgParser m Blocks -headlineToHeader Headline {..} = do +headlineToHeader hdln = do exportTodoKeyword <- getExportSetting exportWithTodoKeywords exportTags <- getExportSetting exportWithTags let todoText = if exportTodoKeyword - then case headlineTodoMarker of + then case headlineTodoMarker hdln of Just kw -> todoKeywordToInlines kw <> B.space Nothing -> mempty else mempty - let text = todoText <> headlineText <> + let text = todoText <> headlineText hdln <> if exportTags - then tagsToInlines headlineTags + then tagsToInlines (headlineTags hdln) else mempty - let propAttr = propertiesToAttr headlineProperties - attr <- registerHeader propAttr headlineText - return $ B.headerWith attr headlineLevel text + let propAttr = propertiesToAttr (headlineProperties hdln) + attr <- registerHeader propAttr (headlineText hdln) + return $ B.headerWith attr (headlineLevel hdln) text todoKeyword :: Monad m => OrgParser m TodoMarker todoKeyword = try $ do -- cgit v1.2.3 From 275afec38a9feb1143344af19d5ebfbf4ef4fb32 Mon Sep 17 00:00:00 2001 From: Albert Krewinkel Date: Thu, 6 Sep 2018 20:57:21 +0200 Subject: Org reader: respect export option `p` for planning info Inclusion of planning info (*DEADLINE*, *SCHEDULED*, and *CLOSED*) can be controlled via the `p` export option: setting the option to `t` will add all planning information in a *Plain* block below the respective headline. --- src/Text/Pandoc/Readers/Org/DocumentTree.hs | 26 +++++++++++++++++++++++++- src/Text/Pandoc/Readers/Org/ExportSettings.hs | 2 +- src/Text/Pandoc/Readers/Org/ParserState.hs | 2 ++ test/Tests/Readers/Org/Block/Header.hs | 13 +++++++++++++ test/Tests/Readers/Org/Directive.hs | 23 +++++++++++++++++++++++ 5 files changed, 64 insertions(+), 2 deletions(-) (limited to 'src/Text/Pandoc/Readers/Org') diff --git a/src/Text/Pandoc/Readers/Org/DocumentTree.hs b/src/Text/Pandoc/Readers/Org/DocumentTree.hs index 6dd78560f..c7a5f22c4 100644 --- a/src/Text/Pandoc/Readers/Org/DocumentTree.hs +++ b/src/Text/Pandoc/Readers/Org/DocumentTree.hs @@ -204,6 +204,7 @@ headlineToHeaderWithList hdln = do maxHeadlineLevels <- getExportSetting exportHeadlineLevels header <- headlineToHeader hdln listElements <- mapM headlineToBlocks (headlineChildren hdln) + planningBlock <- planningToBlock (headlinePlanning hdln) let listBlock = if null listElements then mempty else B.orderedList listElements @@ -213,6 +214,7 @@ headlineToHeaderWithList hdln = do return . mconcat $ [ headerText , headlineContents hdln + , planningBlock , listBlock ] where @@ -225,8 +227,9 @@ headlineToHeaderWithList hdln = do headlineToHeaderWithContents :: Monad m => Headline -> OrgParser m Blocks headlineToHeaderWithContents hdln = do header <- headlineToHeader hdln + planningBlock <- planningToBlock (headlinePlanning hdln) childrenBlocks <- mconcat <$> mapM headlineToBlocks (headlineChildren hdln) - return $ header <> headlineContents hdln <> childrenBlocks + return $ header <> planningBlock <> headlineContents hdln <> childrenBlocks headlineToHeader :: Monad m => Headline -> OrgParser m Blocks headlineToHeader hdln = do @@ -287,6 +290,27 @@ tagsToInlines tags = tagSpan :: Tag -> Inlines -> Inlines tagSpan t = B.spanWith ("", ["tag"], [("tag-name", fromTag t)]) +-- | Render planning info as a block iff the respective export setting is +-- enabled. +planningToBlock :: Monad m => PlanningInfo -> OrgParser m Blocks +planningToBlock planning = do + includePlanning <- getExportSetting exportWithPlanning + return $ + if includePlanning + then B.plain . mconcat . intersperse B.space . filter (/= mempty) $ + [ datumInlines planningClosed "CLOSED" + , datumInlines planningDeadline "DEADLINE" + , datumInlines planningScheduled "SCHEDULED" + ] + else mempty + where + datumInlines field name = + case field planning of + Nothing -> mempty + Just time -> B.strong (B.str name <> B.str ":") + <> B.space + <> B.emph (B.str time) + -- | An Org timestamp, including repetition marks. TODO: improve type Timestamp = String diff --git a/src/Text/Pandoc/Readers/Org/ExportSettings.hs b/src/Text/Pandoc/Readers/Org/ExportSettings.hs index d02eb37c5..f79ee0d64 100644 --- a/src/Text/Pandoc/Readers/Org/ExportSettings.hs +++ b/src/Text/Pandoc/Readers/Org/ExportSettings.hs @@ -69,7 +69,7 @@ exportSetting = choice , integerSetting "H" (\val es -> es { exportHeadlineLevels = val }) , ignoredSetting "inline" , ignoredSetting "num" - , ignoredSetting "p" + , booleanSetting "p" (\val es -> es { exportWithPlanning = val }) , ignoredSetting "pri" , ignoredSetting "prop" , ignoredSetting "stat" diff --git a/src/Text/Pandoc/Readers/Org/ParserState.hs b/src/Text/Pandoc/Readers/Org/ParserState.hs index 4cb5bb626..d33602575 100644 --- a/src/Text/Pandoc/Readers/Org/ParserState.hs +++ b/src/Text/Pandoc/Readers/Org/ParserState.hs @@ -260,6 +260,7 @@ data ExportSettings = ExportSettings , exportWithAuthor :: Bool -- ^ Include author in final meta-data , exportWithCreator :: Bool -- ^ Include creator in final meta-data , exportWithEmail :: Bool -- ^ Include email in final meta-data + , exportWithPlanning :: Bool -- ^ Keep planning info after headlines , exportWithTags :: Bool -- ^ Keep tags as part of headlines , exportWithTodoKeywords :: Bool -- ^ Keep TODO keywords in headers } @@ -280,6 +281,7 @@ defaultExportSettings = ExportSettings , exportWithAuthor = True , exportWithCreator = True , exportWithEmail = True + , exportWithPlanning = False , exportWithTags = True , exportWithTodoKeywords = True } diff --git a/test/Tests/Readers/Org/Block/Header.hs b/test/Tests/Readers/Org/Block/Header.hs index 6f38714cd..913c830d6 100644 --- a/test/Tests/Readers/Org/Block/Header.hs +++ b/test/Tests/Readers/Org/Block/Header.hs @@ -205,5 +205,18 @@ tests = , " :END:" ] =?> headerWith ("look", [], []) 1 "important" + + , "Planning info followed by test" =: + T.unlines [ "* important " + , " " <> T.unwords + [ "CLOSED: [2018-09-05 Wed 13:58]" + , "DEADLINE: <2018-09-17 Mon>" + , "SCHEDULED: <2018-09-10 Mon>" + ] + , " :PROPERTIES:" + , " :custom_id: look" + , " :END:" + ] =?> + headerWith ("look", [], []) 1 "important" ] ] diff --git a/test/Tests/Readers/Org/Directive.hs b/test/Tests/Readers/Org/Directive.hs index bb9c52e69..87abb714d 100644 --- a/test/Tests/Readers/Org/Directive.hs +++ b/test/Tests/Readers/Org/Directive.hs @@ -150,6 +150,29 @@ tests = , "* Headline :hello:world:" ] =?> headerWith ("headline", [], mempty) 1 "Headline" + + , testGroup "planning information" + [ "include planning info after headlines" =: + T.unlines [ "#+OPTIONS: p:t" + , "* important" + , " DEADLINE: <2018-10-01 Mon> SCHEDULED: <2018-09-15 Sat>" + ] =?> + mconcat [ headerWith ("important", mempty, mempty) 1 "important" + , plain $ strong "DEADLINE:" + <> space + <> emph (str "<2018-10-01 Mon>") + <> space + <> strong "SCHEDULED:" + <> space + <> emph (str "<2018-09-15 Sat>") + ] + + , "empty planning info is not included" =: + T.unlines [ "#+OPTIONS: p:t" + , "* Wichtig" + ] =?> + headerWith ("wichtig", mempty, mempty) 1 "Wichtig" + ] ] , testGroup "Include" -- cgit v1.2.3 From 6e8f31dab16472cb7cf14aac88cf2e383bdbc5ec Mon Sep 17 00:00:00 2001 From: leungbk Date: Tue, 25 Sep 2018 18:21:03 -0700 Subject: Force inline code blocks to honor export options. `exportsCode` is moved from `Blocks.hs` to `Shared.hs` and exported accordingly. --- src/Text/Pandoc/Readers/Org/Blocks.hs | 5 +---- src/Text/Pandoc/Readers/Org/Inlines.hs | 5 +++-- src/Text/Pandoc/Readers/Org/Shared.hs | 4 ++++ test/command/4885.md | 8 ++++++++ 4 files changed, 16 insertions(+), 6 deletions(-) create mode 100644 test/command/4885.md (limited to 'src/Text/Pandoc/Readers/Org') diff --git a/src/Text/Pandoc/Readers/Org/Blocks.hs b/src/Text/Pandoc/Readers/Org/Blocks.hs index d2a749efb..1c52c3477 100644 --- a/src/Text/Pandoc/Readers/Org/Blocks.hs +++ b/src/Text/Pandoc/Readers/Org/Blocks.hs @@ -40,7 +40,7 @@ import Text.Pandoc.Readers.Org.Meta (metaExport, metaKey, metaLine) import Text.Pandoc.Readers.Org.ParserState import Text.Pandoc.Readers.Org.Parsing import Text.Pandoc.Readers.Org.Shared (cleanLinkString, isImageFilename, - originalLang, translateLang) + originalLang, translateLang, exportsCode) import Text.Pandoc.Builder (Blocks, Inlines) import Text.Pandoc.Class (PandocMonad) @@ -314,9 +314,6 @@ codeBlock blockAttrs blockType = do labelledBlock :: F Inlines -> F Blocks labelledBlock = fmap (B.plain . B.spanWith ("", ["label"], [])) - exportsCode :: [(String, String)] -> Bool - exportsCode = maybe True (`elem` ["code", "both"]) . lookup "exports" - exportsResults :: [(String, String)] -> Bool exportsResults = maybe False (`elem` ["results", "both"]) . lookup "exports" diff --git a/src/Text/Pandoc/Readers/Org/Inlines.hs b/src/Text/Pandoc/Readers/Org/Inlines.hs index b7378e3e4..b9a589f03 100644 --- a/src/Text/Pandoc/Readers/Org/Inlines.hs +++ b/src/Text/Pandoc/Readers/Org/Inlines.hs @@ -39,7 +39,7 @@ import Text.Pandoc.Readers.Org.BlockStarts (endOfBlock, noteMarker) import Text.Pandoc.Readers.Org.ParserState import Text.Pandoc.Readers.Org.Parsing import Text.Pandoc.Readers.Org.Shared (cleanLinkString, isImageFilename, - originalLang, translateLang) + originalLang, translateLang, exportsCode) import Text.Pandoc.Builder (Inlines) import qualified Text.Pandoc.Builder as B @@ -529,7 +529,8 @@ inlineCodeBlock = try $ do inlineCode <- enclosedByPair '{' '}' (noneOf "\n\r") let attrClasses = [translateLang lang] let attrKeyVal = originalLang lang <> opts - returnF $ B.codeWith ("", attrClasses, attrKeyVal) inlineCode + let codeInlineBlck = B.codeWith ("", attrClasses, attrKeyVal) inlineCode + returnF $ (if exportsCode opts then codeInlineBlck else mempty) where inlineBlockOption :: PandocMonad m => OrgParser m (String, String) inlineBlockOption = try $ do diff --git a/src/Text/Pandoc/Readers/Org/Shared.hs b/src/Text/Pandoc/Readers/Org/Shared.hs index 17fe34738..71d1dd517 100644 --- a/src/Text/Pandoc/Readers/Org/Shared.hs +++ b/src/Text/Pandoc/Readers/Org/Shared.hs @@ -32,6 +32,7 @@ module Text.Pandoc.Readers.Org.Shared , isImageFilename , originalLang , translateLang + , exportsCode ) where import Prelude @@ -96,3 +97,6 @@ translateLang cs = "sh" -> "bash" "sqlite" -> "sql" _ -> cs + +exportsCode :: [(String, String)] -> Bool +exportsCode = maybe True (`elem` ["code", "both"]) . lookup "exports" diff --git a/test/command/4885.md b/test/command/4885.md new file mode 100644 index 000000000..8611097c2 --- /dev/null +++ b/test/command/4885.md @@ -0,0 +1,8 @@ +``` +% pandoc -f org -t markdown +This won't show the command. +src_maxima[:exports none :results raw]{tex('integrate(sin((e^x)/pi),x,0,inf));} $$\int_{0}^{\infty }{\sin \left({{e^{x}}\over{\pi}}\right)\;dx}$$ +^D +This won\'t show the command. +$$\int_{0}^{\infty }{\sin \left({{e^{x}}\over{\pi}}\right)\;dx}$$ +``` -- cgit v1.2.3 From 4f9ab7e03268e576d86e697f7110869434d08557 Mon Sep 17 00:00:00 2001 From: leungbk Date: Thu, 27 Sep 2018 15:04:56 -0700 Subject: Parse empty argument array in inline src blocks. `enclosedByPair` alone does not the handle the empty array properly since it uses `many1Till`. --- src/Text/Pandoc/Readers/Org/Inlines.hs | 3 ++- test/Tests/Readers/Org/Inline.hs | 7 +++++++ 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'src/Text/Pandoc/Readers/Org') diff --git a/src/Text/Pandoc/Readers/Org/Inlines.hs b/src/Text/Pandoc/Readers/Org/Inlines.hs index b9a589f03..a5335ca57 100644 --- a/src/Text/Pandoc/Readers/Org/Inlines.hs +++ b/src/Text/Pandoc/Readers/Org/Inlines.hs @@ -525,7 +525,8 @@ inlineCodeBlock :: PandocMonad m => OrgParser m (F Inlines) inlineCodeBlock = try $ do string "src_" lang <- many1 orgArgWordChar - opts <- option [] $ enclosedByPair '[' ']' inlineBlockOption + opts <- option [] $ try (enclosedByPair '[' ']' inlineBlockOption) + <|> (mempty <$ string "[]") inlineCode <- enclosedByPair '{' '}' (noneOf "\n\r") let attrClasses = [translateLang lang] let attrKeyVal = originalLang lang <> opts diff --git a/test/Tests/Readers/Org/Inline.hs b/test/Tests/Readers/Org/Inline.hs index 7dfa001e3..9cfcda79f 100644 --- a/test/Tests/Readers/Org/Inline.hs +++ b/test/Tests/Readers/Org/Inline.hs @@ -280,6 +280,13 @@ tests = ) "echo 'Hello, World'") + , "Inline code block with a blank argument array" =: + "src_sh[]{echo 'Hello, World'}" =?> + para (codeWith ( "" + , [ "bash" ] + , [ ("org-language", "sh") ]) + "echo 'Hello, World'") + , "Inline code block with toggle" =: "src_sh[:toggle]{echo $HOME}" =?> para (codeWith ( "" -- cgit v1.2.3 From 600034d7ff83b7ece292016a1e9c232fd7ac66f7 Mon Sep 17 00:00:00 2001 From: Mauro Bieg Date: Thu, 4 Oct 2018 18:45:59 +0200 Subject: Add lookupMeta* functions to Text.Pandoc.Writers.Shared (#4907) Remove exported functions `metaValueToInlines`, `metaValueToString`. Add new exported functions `lookupMetaBool`, `lookupMetaBlocks`, `lookupMetaInlines`, `lookupMetaString`. Use these whenever possible for uniformity in writers. API change (major, because of removed function `metaValueToInlines`. `metaValueToString` wasn't in any released version.) --- src/Text/Pandoc/Readers/Org/DocumentTree.hs | 9 +--- src/Text/Pandoc/Writers/Docx.hs | 29 +++------- src/Text/Pandoc/Writers/OpenDocument.hs | 6 ++- src/Text/Pandoc/Writers/Powerpoint/Presentation.hs | 22 +++----- src/Text/Pandoc/Writers/RST.hs | 5 +- src/Text/Pandoc/Writers/Shared.hs | 62 ++++++++++++++++------ 6 files changed, 68 insertions(+), 65 deletions(-) (limited to 'src/Text/Pandoc/Readers/Org') diff --git a/src/Text/Pandoc/Readers/Org/DocumentTree.hs b/src/Text/Pandoc/Readers/Org/DocumentTree.hs index c7a5f22c4..a9df3b437 100644 --- a/src/Text/Pandoc/Readers/Org/DocumentTree.hs +++ b/src/Text/Pandoc/Readers/Org/DocumentTree.hs @@ -43,7 +43,6 @@ import Text.Pandoc.Readers.Org.BlockStarts import Text.Pandoc.Readers.Org.ParserState import Text.Pandoc.Readers.Org.Parsing -import qualified Data.Map as Map import qualified Text.Pandoc.Builder as B -- @@ -58,7 +57,7 @@ documentTree :: PandocMonad m documentTree blocks inline = do initialBlocks <- blocks headlines <- sequence <$> manyTill (headline blocks inline 1) eof - title <- fmap (getTitle . unMeta) . orgStateMeta <$> getState + title <- fmap docTitle . orgStateMeta <$> getState return $ do headlines' <- headlines initialBlocks' <- initialBlocks @@ -73,12 +72,6 @@ documentTree blocks inline = do , headlineContents = initialBlocks' , headlineChildren = headlines' } - where - getTitle :: Map.Map String MetaValue -> [Inline] - getTitle metamap = - case Map.lookup "title" metamap of - Just (MetaInlines inlns) -> inlns - _ -> [] newtype Tag = Tag { fromTag :: String } deriving (Show, Eq) diff --git a/src/Text/Pandoc/Writers/Docx.hs b/src/Text/Pandoc/Writers/Docx.hs index 5bd7e809b..524d20fd1 100644 --- a/src/Text/Pandoc/Writers/Docx.hs +++ b/src/Text/Pandoc/Writers/Docx.hs @@ -66,8 +66,7 @@ import Text.Pandoc.Readers.Docx.StyleMap import Text.Pandoc.Shared hiding (Element) import Text.Pandoc.Walk import Text.Pandoc.Writers.Math -import Text.Pandoc.Writers.Shared (isDisplayMath, fixDisplayMath, - metaValueToInlines) +import Text.Pandoc.Writers.Shared import Text.Printf (printf) import Text.TeXMath import Text.XML.Light as XML @@ -267,8 +266,9 @@ writeDocx opts doc@(Pandoc meta _) = do -- parse styledoc for heading styles let styleMaps = getStyleMaps styledoc - let tocTitle = fromMaybe (stTocTitle defaultWriterState) $ - metaValueToInlines <$> lookupMeta "toc-title" meta + let tocTitle = case lookupMetaInlines "toc-title" meta of + [] -> stTocTitle defaultWriterState + ls -> ls let initialSt = defaultWriterState { stStyleMaps = styleMaps @@ -760,24 +760,9 @@ writeOpenXML opts (Pandoc meta blocks) = do let tit = docTitle meta let auths = docAuthors meta let dat = docDate meta - let abstract' = case lookupMeta "abstract" meta of - Just (MetaBlocks bs) -> bs - Just (MetaInlines ils) -> [Plain ils] - Just (MetaString s) -> [Plain [Str s]] - _ -> [] - let subtitle' = case lookupMeta "subtitle" meta of - Just (MetaBlocks [Plain xs]) -> xs - Just (MetaBlocks [Para xs]) -> xs - Just (MetaInlines xs) -> xs - Just (MetaString s) -> [Str s] - _ -> [] - let includeTOC = writerTableOfContents opts || - case lookupMeta "toc" meta of - Just (MetaBlocks _) -> True - Just (MetaInlines _) -> True - Just (MetaString (_:_)) -> True - Just (MetaBool True) -> True - _ -> False + let abstract' = lookupMetaBlocks "abstract" meta + let subtitle' = lookupMetaInlines "subtitle" meta + let includeTOC = writerTableOfContents opts || lookupMetaBool "toc" meta title <- withParaPropM (pStyleM "Title") $ blocksToOpenXML opts [Para tit | not (null tit)] subtitle <- withParaPropM (pStyleM "Subtitle") $ blocksToOpenXML opts [Para subtitle' | not (null subtitle')] authors <- withParaProp (pCustomStyle "Author") $ blocksToOpenXML opts $ diff --git a/src/Text/Pandoc/Writers/OpenDocument.hs b/src/Text/Pandoc/Writers/OpenDocument.hs index e3d7f2e5c..676a1acb0 100644 --- a/src/Text/Pandoc/Writers/OpenDocument.hs +++ b/src/Text/Pandoc/Writers/OpenDocument.hs @@ -226,8 +226,10 @@ handleSpaces s -- | Convert Pandoc document to string in OpenDocument format. writeOpenDocument :: PandocMonad m => WriterOptions -> Pandoc -> m Text writeOpenDocument opts (Pandoc meta blocks) = do - lang <- fromMaybe (Lang "en" "US" "" []) <$> - toLang (metaValueToString <$> lookupMeta "lang" meta) + let defLang = Lang "en" "US" "" [] + lang <- case lookupMetaString "lang" meta of + "" -> pure defLang + s -> fromMaybe defLang <$> toLang (Just s) setTranslations lang let colwidth = if writerWrapText opts == WrapAuto then Just $ writerColumns opts diff --git a/src/Text/Pandoc/Writers/Powerpoint/Presentation.hs b/src/Text/Pandoc/Writers/Powerpoint/Presentation.hs index e14476b16..c97d8d770 100644 --- a/src/Text/Pandoc/Writers/Powerpoint/Presentation.hs +++ b/src/Text/Pandoc/Writers/Powerpoint/Presentation.hs @@ -72,7 +72,7 @@ import Text.Pandoc.Logging import Text.Pandoc.Walk import Data.Time (UTCTime) import qualified Text.Pandoc.Shared as Shared -- so we don't overlap "Element" -import Text.Pandoc.Writers.Shared (metaValueToInlines) +import Text.Pandoc.Writers.Shared (lookupMetaInlines) import qualified Data.Map as M import qualified Data.Set as S import Data.Maybe (maybeToList, fromMaybe) @@ -731,9 +731,9 @@ makeEndNotesSlideBlocks = do anchorSet <- M.keysSet <$> gets stAnchorMap if M.null noteIds then return [] - else let title = case lookupMeta "notes-title" meta of - Just val -> metaValueToInlines val - Nothing -> [Str "Notes"] + else let title = case lookupMetaInlines "notes-title" meta of + [] -> [Str "Notes"] + ls -> ls ident = Shared.uniqueIdent title anchorSet hdr = Header slideLevel (ident, [], []) title blks = concatMap (\(n, bs) -> makeNoteEntry n bs) $ @@ -744,13 +744,7 @@ getMetaSlide :: Pres (Maybe Slide) getMetaSlide = do meta <- asks envMetadata title <- inlinesToParElems $ docTitle meta - subtitle <- inlinesToParElems $ - case lookupMeta "subtitle" meta of - Just (MetaString s) -> [Str s] - Just (MetaInlines ils) -> ils - Just (MetaBlocks [Plain ils]) -> ils - Just (MetaBlocks [Para ils]) -> ils - _ -> [] + subtitle <- inlinesToParElems $ lookupMetaInlines "subtitle" meta authors <- mapM inlinesToParElems $ docAuthors meta date <- inlinesToParElems $ docDate meta if null title && null subtitle && null authors && null date @@ -785,9 +779,9 @@ makeTOCSlide blks = local (\env -> env{envCurSlideId = tocSlideId}) $ do contents <- BulletList <$> mapM elementToListItem (Shared.hierarchicalize blks) meta <- asks envMetadata slideLevel <- asks envSlideLevel - let tocTitle = case lookupMeta "toc-title" meta of - Just val -> metaValueToInlines val - Nothing -> [Str "Table of Contents"] + let tocTitle = case lookupMetaInlines "toc-title" meta of + [] -> [Str "Table of Contents"] + ls -> ls hdr = Header slideLevel nullAttr tocTitle blocksToSlide [hdr, contents] diff --git a/src/Text/Pandoc/Writers/RST.hs b/src/Text/Pandoc/Writers/RST.hs index b416eca59..34d5cce04 100644 --- a/src/Text/Pandoc/Writers/RST.hs +++ b/src/Text/Pandoc/Writers/RST.hs @@ -82,10 +82,7 @@ pandocToRST (Pandoc meta blocks) = do else Nothing let render' :: Doc -> Text render' = render colwidth - let subtit = case lookupMeta "subtitle" meta of - Just (MetaBlocks [Plain xs]) -> xs - Just (MetaInlines xs) -> xs - _ -> [] + let subtit = lookupMetaInlines "subtitle" meta title <- titleToRST (docTitle meta) subtit metadata <- metaToJSON opts (fmap render' . blockListToRST) diff --git a/src/Text/Pandoc/Writers/Shared.hs b/src/Text/Pandoc/Writers/Shared.hs index 6113b0a66..323748aad 100644 --- a/src/Text/Pandoc/Writers/Shared.hs +++ b/src/Text/Pandoc/Writers/Shared.hs @@ -42,8 +42,10 @@ module Text.Pandoc.Writers.Shared ( , fixDisplayMath , unsmartify , gridTable - , metaValueToInlines - , metaValueToString + , lookupMetaBool + , lookupMetaBlocks + , lookupMetaInlines + , lookupMetaString , stripLeadingTrailingSpace , groffEscape ) @@ -63,7 +65,6 @@ import Text.Pandoc.Definition import Text.Pandoc.Options import Text.Pandoc.Pretty import Text.Pandoc.Shared (stringify) -import Text.Pandoc.Walk (query) import Text.Pandoc.UTF8 (toStringLazy) import Text.Pandoc.XML (escapeStringForXML) import Text.Printf (printf) @@ -339,19 +340,50 @@ gridTable opts blocksToDoc headless aligns widths headers rows = do body $$ border '-' (repeat AlignDefault) widthsInChars -metaValueToInlines :: MetaValue -> [Inline] -metaValueToInlines (MetaString s) = [Str s] -metaValueToInlines (MetaInlines ils) = ils -metaValueToInlines (MetaBlocks bs) = query return bs -metaValueToInlines (MetaBool b) = [Str $ show b] -metaValueToInlines _ = [] -metaValueToString :: MetaValue -> String -metaValueToString (MetaString s) = s -metaValueToString (MetaInlines ils) = stringify ils -metaValueToString (MetaBlocks bs) = stringify bs -metaValueToString (MetaBool b) = show b -metaValueToString _ = "" + +-- | Retrieve the metadata value for a given @key@ +-- and convert to Bool. +lookupMetaBool :: String -> Meta -> Bool +lookupMetaBool key meta = + case lookupMeta key meta of + Just (MetaBlocks _) -> True + Just (MetaInlines _) -> True + Just (MetaString (_:_)) -> True + Just (MetaBool True) -> True + _ -> False + +-- | Retrieve the metadata value for a given @key@ +-- and extract blocks. +lookupMetaBlocks :: String -> Meta -> [Block] +lookupMetaBlocks key meta = + case lookupMeta key meta of + Just (MetaBlocks bs) -> bs + Just (MetaInlines ils) -> [Plain ils] + Just (MetaString s) -> [Plain [Str s]] + _ -> [] + +-- | Retrieve the metadata value for a given @key@ +-- and extract inlines. +lookupMetaInlines :: String -> Meta -> [Inline] +lookupMetaInlines key meta = + case lookupMeta key meta of + Just (MetaString s) -> [Str s] + Just (MetaInlines ils) -> ils + Just (MetaBlocks [Plain ils]) -> ils + Just (MetaBlocks [Para ils]) -> ils + _ -> [] + +-- | Retrieve the metadata value for a given @key@ +-- and convert to String. +lookupMetaString :: String -> Meta -> String +lookupMetaString key meta = + case lookupMeta key meta of + Just (MetaString s) -> s + Just (MetaInlines ils) -> stringify ils + Just (MetaBlocks bs) -> stringify bs + Just (MetaBool b) -> show b + _ -> "" -- | Escape non-ASCII characters using groff \u[..] sequences. groffEscape :: T.Text -> T.Text -- cgit v1.2.3 From a26b3a2d6af8614e13299bbf477e28c5932ef680 Mon Sep 17 00:00:00 2001 From: Brian Leung Date: Fri, 5 Oct 2018 14:28:17 -0700 Subject: Org reader: Add partial support for `#+EXCLUDE_TAGS` option. (#4950) Closes #4284. Headers with the corresponding tags should not appear in the output. If one or more of the specified tags contains a non-tag character like `+`, Org-mode will not treat that as a valid tag, but will nonetheless continue scanning for valid tags. That behavior is not replicated in this patch; entering `cat+dog` as one of the entries in `#+EXCLUDE_TAGS` and running the file through Pandoc will cause the parser to fail and result in the only excluded tag being the default, `noexport`. --- src/Text/Pandoc/Readers/Org/DocumentTree.hs | 14 +++++++------- src/Text/Pandoc/Readers/Org/Meta.hs | 11 +++++++++++ src/Text/Pandoc/Readers/Org/ParserState.hs | 6 ++++++ src/Text/Pandoc/Readers/Org/Parsing.hs | 8 ++++++++ test/command/4284.md | 29 +++++++++++++++++++++++++++++ 5 files changed, 61 insertions(+), 7 deletions(-) create mode 100644 test/command/4284.md (limited to 'src/Text/Pandoc/Readers/Org') diff --git a/src/Text/Pandoc/Readers/Org/DocumentTree.hs b/src/Text/Pandoc/Readers/Org/DocumentTree.hs index a9df3b437..7d55892fe 100644 --- a/src/Text/Pandoc/Readers/Org/DocumentTree.hs +++ b/src/Text/Pandoc/Readers/Org/DocumentTree.hs @@ -43,6 +43,7 @@ import Text.Pandoc.Readers.Org.BlockStarts import Text.Pandoc.Readers.Org.ParserState import Text.Pandoc.Readers.Org.Parsing +import qualified Data.Set as Set import qualified Text.Pandoc.Builder as B -- @@ -73,9 +74,6 @@ documentTree blocks inline = do , headlineChildren = headlines' } -newtype Tag = Tag { fromTag :: String } - deriving (Show, Eq) - -- | Create a tag containing the given string. toTag :: String -> Tag toTag = Tag @@ -153,7 +151,7 @@ headline blocks inline lvl = try $ do headerTags :: Monad m => OrgParser m [Tag] headerTags = try $ - let tag = many1 (alphaNum <|> oneOf "@%#_") <* char ':' + let tag = orgTagWord <* char ':' in map toTag <$> (skipSpaces *> char ':' *> many1 tag <* skipSpaces) -- | Convert an Org mode headline (i.e. a document tree) into pandoc's Blocks @@ -163,15 +161,17 @@ headlineToBlocks hdln = do let tags = headlineTags hdln let text = headlineText hdln let level = headlineLevel hdln + shouldNotExport <- hasDoNotExportTag tags case () of - _ | any isNoExportTag tags -> return mempty + _ | shouldNotExport -> return mempty _ | any isArchiveTag tags -> archivedHeadlineToBlocks hdln _ | isCommentTitle text -> return mempty _ | maxLevel <= level -> headlineToHeaderWithList hdln _ | otherwise -> headlineToHeaderWithContents hdln -isNoExportTag :: Tag -> Bool -isNoExportTag = (== toTag "noexport") +hasDoNotExportTag :: Monad m => [Tag] -> OrgParser m Bool +hasDoNotExportTag tags = containsExcludedTag . orgStateExcludedTags <$> getState + where containsExcludedTag s = any (`Set.member` s) tags isArchiveTag :: Tag -> Bool isArchiveTag = (== toTag "ARCHIVE") diff --git a/src/Text/Pandoc/Readers/Org/Meta.hs b/src/Text/Pandoc/Readers/Org/Meta.hs index 965e33d94..921cd27e0 100644 --- a/src/Text/Pandoc/Readers/Org/Meta.hs +++ b/src/Text/Pandoc/Readers/Org/Meta.hs @@ -52,6 +52,7 @@ import Data.Char (toLower) import Data.List (intersperse) import Data.Maybe (fromMaybe) import qualified Data.Map as M +import qualified Data.Set as Set import Network.HTTP (urlEncode) -- | Returns the current meta, respecting export options. @@ -158,6 +159,7 @@ optionLine = try $ do "seq_todo" -> todoSequence >>= updateState . registerTodoSequence "typ_todo" -> todoSequence >>= updateState . registerTodoSequence "macro" -> macroDefinition >>= updateState . registerMacro + "exclude_tags" -> excludedTagSet >>= updateState . setExcludedTags "pandoc-emphasis-pre" -> emphChars >>= updateState . setEmphasisPreChar "pandoc-emphasis-post" -> emphChars >>= updateState . setEmphasisPostChar _ -> mzero @@ -190,6 +192,15 @@ parseFormat = try $ replacePlain <|> replaceUrl <|> justAppend rest = manyTill anyChar (eof <|> () <$ oneOf "\n\r") tillSpecifier c = manyTill (noneOf "\n\r") (try $ string ('%':c:"")) +excludedTagSet :: Monad m => OrgParser m (Set.Set Tag) +excludedTagSet = do + skipSpaces + Set.fromList . map Tag <$> + many (orgTagWord <* skipSpaces) <* newline + +setExcludedTags :: Set.Set Tag -> OrgParserState -> OrgParserState +setExcludedTags tagSet st = st { orgStateExcludedTags = tagSet } + setEmphasisPreChar :: Maybe [Char] -> OrgParserState -> OrgParserState setEmphasisPreChar csMb st = let preChars = fromMaybe (orgStateEmphasisPostChars defaultOrgParserState) csMb diff --git a/src/Text/Pandoc/Readers/Org/ParserState.hs b/src/Text/Pandoc/Readers/Org/ParserState.hs index d33602575..381d4c5ee 100644 --- a/src/Text/Pandoc/Readers/Org/ParserState.hs +++ b/src/Text/Pandoc/Readers/Org/ParserState.hs @@ -33,6 +33,7 @@ module Text.Pandoc.Readers.Org.ParserState , defaultOrgParserState , OrgParserLocal (..) , OrgNoteRecord + , Tag(..) , HasReaderOptions (..) , HasQuoteContext (..) , HasMacros (..) @@ -88,6 +89,9 @@ type OrgNoteTable = [OrgNoteRecord] type OrgLinkFormatters = M.Map String (String -> String) -- | Macro expander function type MacroExpander = [String] -> String +-- | Tag +newtype Tag = Tag { fromTag :: String } + deriving (Show, Eq, Ord) -- | The states in which a todo item can be data TodoState = Todo | Done @@ -113,6 +117,7 @@ data OrgParserState = OrgParserState -- specified here. , orgStateEmphasisPostChars :: [Char] -- ^ Chars allowed at after emphasis , orgStateEmphasisNewlines :: Maybe Int + , orgStateExcludedTags :: Set.Set Tag , orgStateExportSettings :: ExportSettings , orgStateHeaderMap :: M.Map Inlines String , orgStateIdentifiers :: Set.Set String @@ -183,6 +188,7 @@ defaultOrgParserState = OrgParserState , orgStateEmphasisCharStack = [] , orgStateEmphasisNewlines = Nothing , orgStateExportSettings = def + , orgStateExcludedTags = Set.singleton $ Tag "noexport" , orgStateHeaderMap = M.empty , orgStateIdentifiers = Set.empty , orgStateIncludeFiles = [] diff --git a/src/Text/Pandoc/Readers/Org/Parsing.hs b/src/Text/Pandoc/Readers/Org/Parsing.hs index b37b36624..52a346e36 100644 --- a/src/Text/Pandoc/Readers/Org/Parsing.hs +++ b/src/Text/Pandoc/Readers/Org/Parsing.hs @@ -46,6 +46,8 @@ module Text.Pandoc.Readers.Org.Parsing , orgArgKey , orgArgWord , orgArgWordChar + , orgTagWord + , orgTagWordChar -- * Re-exports from Text.Pandoc.Parser , ParserContext (..) , many1Till @@ -220,3 +222,9 @@ orgArgWord = many1 orgArgWordChar -- | Chars treated as part of a word in plists. orgArgWordChar :: Monad m => OrgParser m Char orgArgWordChar = alphaNum <|> oneOf "-_" + +orgTagWord :: Monad m => OrgParser m String +orgTagWord = many1 orgTagWordChar + +orgTagWordChar :: Monad m => OrgParser m Char +orgTagWordChar = alphaNum <|> oneOf "@%#_" diff --git a/test/command/4284.md b/test/command/4284.md new file mode 100644 index 000000000..e2a41d14f --- /dev/null +++ b/test/command/4284.md @@ -0,0 +1,29 @@ +``` +% pandoc -f org -t native +#+EXCLUDE_TAGS:apple cat bye dog % + +* This should not appear :apple: +* NOEXPORT should appear if not specified in EXCLUDE_TAGS :noexport: +* This should not appear :cat:hi:laptop: +** Children of headers with excluded tags should not appear :xylophone: +* This should not appear :%: +^D +[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"]]]] +``` + +``` +% pandoc -f org -t native +#+EXCLUDE_TAGS:elephant +* This should not appear :elephant: +* This should appear :fawn: +^D +[Header 1 ("this-should-appear",[],[]) [Str "This",Space,Str "should",Space,Str "appear",Space,Span ("",["tag"],[("tag-name","fawn")]) [SmallCaps [Str "fawn"]]]] +``` + +``` +% pandoc -f org -t native +#+EXCLUDE_TAGS: +* NOEXPORT should appear if not specified in EXCLUDE_TAGS :noexport: +^D +[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"]]]] +``` -- cgit v1.2.3 From e257b54124f69682c237a5c9a5f99c5c72406c88 Mon Sep 17 00:00:00 2001 From: Brian Leung Date: Fri, 5 Oct 2018 22:21:20 -0700 Subject: Org reader: fix behavior for successive calls of `#+EXCLUDE_TAGS`. (#4951) Calling `#+EXCLUDE_TAGS` multiple times should preserve the status of the previously declared tags. --- src/Text/Pandoc/Readers/Org/Meta.hs | 19 +++++++++++-------- src/Text/Pandoc/Readers/Org/ParserState.hs | 2 ++ test/command/4284.md | 11 +++++++++++ 3 files changed, 24 insertions(+), 8 deletions(-) (limited to 'src/Text/Pandoc/Readers/Org') diff --git a/src/Text/Pandoc/Readers/Org/Meta.hs b/src/Text/Pandoc/Readers/Org/Meta.hs index 921cd27e0..cad1d7123 100644 --- a/src/Text/Pandoc/Readers/Org/Meta.hs +++ b/src/Text/Pandoc/Readers/Org/Meta.hs @@ -159,7 +159,7 @@ optionLine = try $ do "seq_todo" -> todoSequence >>= updateState . registerTodoSequence "typ_todo" -> todoSequence >>= updateState . registerTodoSequence "macro" -> macroDefinition >>= updateState . registerMacro - "exclude_tags" -> excludedTagSet >>= updateState . setExcludedTags + "exclude_tags" -> excludedTagList >>= updateState . setExcludedTags "pandoc-emphasis-pre" -> emphChars >>= updateState . setEmphasisPreChar "pandoc-emphasis-post" -> emphChars >>= updateState . setEmphasisPostChar _ -> mzero @@ -192,14 +192,17 @@ parseFormat = try $ replacePlain <|> replaceUrl <|> justAppend rest = manyTill anyChar (eof <|> () <$ oneOf "\n\r") tillSpecifier c = manyTill (noneOf "\n\r") (try $ string ('%':c:"")) -excludedTagSet :: Monad m => OrgParser m (Set.Set Tag) -excludedTagSet = do +excludedTagList :: Monad m => OrgParser m [Tag] +excludedTagList = do skipSpaces - Set.fromList . map Tag <$> - many (orgTagWord <* skipSpaces) <* newline - -setExcludedTags :: Set.Set Tag -> OrgParserState -> OrgParserState -setExcludedTags tagSet st = st { orgStateExcludedTags = tagSet } + map Tag <$> many (orgTagWord <* skipSpaces) <* newline + +setExcludedTags :: [Tag] -> OrgParserState -> OrgParserState +setExcludedTags tagList st = + let finalSet = if orgStateExcludedTagsChanged st + then foldr Set.insert (orgStateExcludedTags st) tagList + else Set.fromList tagList + in st { orgStateExcludedTags = finalSet, orgStateExcludedTagsChanged = True} setEmphasisPreChar :: Maybe [Char] -> OrgParserState -> OrgParserState setEmphasisPreChar csMb st = diff --git a/src/Text/Pandoc/Readers/Org/ParserState.hs b/src/Text/Pandoc/Readers/Org/ParserState.hs index 381d4c5ee..59478256f 100644 --- a/src/Text/Pandoc/Readers/Org/ParserState.hs +++ b/src/Text/Pandoc/Readers/Org/ParserState.hs @@ -118,6 +118,7 @@ data OrgParserState = OrgParserState , orgStateEmphasisPostChars :: [Char] -- ^ Chars allowed at after emphasis , orgStateEmphasisNewlines :: Maybe Int , orgStateExcludedTags :: Set.Set Tag + , orgStateExcludedTagsChanged :: Bool , orgStateExportSettings :: ExportSettings , orgStateHeaderMap :: M.Map Inlines String , orgStateIdentifiers :: Set.Set String @@ -189,6 +190,7 @@ defaultOrgParserState = OrgParserState , orgStateEmphasisNewlines = Nothing , orgStateExportSettings = def , orgStateExcludedTags = Set.singleton $ Tag "noexport" + , orgStateExcludedTagsChanged = False , orgStateHeaderMap = M.empty , orgStateIdentifiers = Set.empty , orgStateIncludeFiles = [] diff --git a/test/command/4284.md b/test/command/4284.md index e2a41d14f..eddd1b03a 100644 --- a/test/command/4284.md +++ b/test/command/4284.md @@ -20,6 +20,17 @@ [Header 1 ("this-should-appear",[],[]) [Str "This",Space,Str "should",Space,Str "appear",Space,Span ("",["tag"],[("tag-name","fawn")]) [SmallCaps [Str "fawn"]]]] ``` +``` +% pandoc -f org -t native +#+EXCLUDE_TAGS: giraffe +#+EXCLUDE_TAGS: hippo +* This should not appear :giraffe: +* This should not appear :hippo: +* This should appear :noexport: +^D +[Header 1 ("this-should-appear",[],[]) [Str "This",Space,Str "should",Space,Str "appear",Space,Span ("",["tag"],[("tag-name","noexport")]) [SmallCaps [Str "noexport"]]]] +``` + ``` % pandoc -f org -t native #+EXCLUDE_TAGS: -- cgit v1.2.3