----------------------------------------------------------------------------- -- | -- Module : Data.OrgMode.Parse.Attoparsec.Drawer.Property -- Copyright : © 2014 Parnell Springmeyer -- License : All Rights Reserved -- Maintainer : Parnell Springmeyer -- Stability : stable -- -- Parsing combinators for org-mode section property drawers. ---------------------------------------------------------------------------- {-# LANGUAGE OverloadedStrings #-} module Data.OrgMode.Parse.Attoparsec.Drawer.Property ( parseProperties , property , PropertyKey , PropertyVal ) where import Control.Applicative ((*>), (<*)) import Data.Attoparsec.Text as T import Data.Attoparsec.Types as Attoparsec import Data.HashMap.Strict (fromList) import Data.Text (Text) import qualified Data.Text as Text import Data.OrgMode.Parse.Attoparsec.Drawer.Generic as Drawer.Generic import Data.OrgMode.Types type PropertyKey = Text type PropertyVal = Text -- | Parse a @PROPERTY@ drawer. -- -- > :PROPERTIES: -- > :DATE: [2014-12-14 11:00] -- > :NOTE: Something really crazy happened today! -- > :END: parseProperties :: Attoparsec.Parser Text Properties parseProperties = Properties . fromList <$> (drawerBegin *> manyTill property Drawer.Generic.drawerEnd) where drawerBegin = Drawer.Generic.parseDrawerDelim "PROPERTIES" -- | Parse a property of a drawer. -- -- Properties *must* be a `:KEY: value` pair, the key can be of any -- case and contain any characters except for newlines and colons -- (since they delimit the start and end of the key). property :: Attoparsec.Parser Text (PropertyKey, PropertyVal) property = (,) <$> parseKey <*> parseVal where parseKey = skipSpace *> skip (== ':') *> takeWhile1 (/= ':') <* skip (== ':') parseVal = Text.strip <$> (skipSpace *> takeValue) takeValue = takeWhile1 (not . isEndOfLine)