orgmode-parse-0.1.0.4: src/Data/OrgMode/Parse/Attoparsec/PropertyDrawer.hs
-----------------------------------------------------------------------------
-- |
-- Module : Data.OrgMode.Parse.Attoparsec.PropertyDrawer
-- Copyright : © 2014 Parnell Springmeyer
-- License : All Rights Reserved
-- Maintainer : Parnell Springmeyer <parnell@digitalmentat.com>
-- Stability : stable
--
-- Parsing combinators for org-mode entry property drawers.
----------------------------------------------------------------------------
{-# LANGUAGE OverloadedStrings #-}
module Data.OrgMode.Parse.Attoparsec.PropertyDrawer
( parseDrawer
, property
)
where
import Control.Applicative ((*>), (<*))
import Data.Attoparsec.Text as T
import Data.Attoparsec.Types as TP
import Data.HashMap.Strict (fromList)
import Data.Text as Text (Text, strip)
import Prelude hiding (concat, null, takeWhile)
import Data.OrgMode.Parse.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:
parseDrawer :: TP.Parser Text Properties
parseDrawer = return . fromList =<< begin *> manyTill property end
where
begin = ident "PROPERTIES"
end = ident "END"
ident v = skipSpace *> skip (== ':') *>
asciiCI v <*
skip (== ':') <* skipSpace
-- | 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 :: TP.Parser Text (PropertyKey, PropertyVal)
property = do
key <- skipSpace *> skip (== ':') *> takeWhile1 (/= ':') <* skip (== ':')
val <- skipSpace *> takeValue
return (key, strip val)
where
takeValue = takeWhile1 (not . isEndOfLine)