module Data.OrgMode.Doc (Node(..), Prefix(..), Drawer(..),
OrgFileProperty(..), Babel(..), Table(..),
OrgDoc(..), NodeChild(..), updateNode, trim,
makeNodeLine) where
import Data.List (intercalate)
import Data.OrgMode.Text
data Prefix = Prefix String deriving (Eq, Show)
data Drawer = Drawer
{ drName :: String
, drProperties :: [(String, String)]
, drLines :: [TextLine]
} deriving (Eq, Show)
data Babel = Babel [TextLine] deriving (Eq, Show)
data Table = Table [TextLine] deriving (Eq, Show)
data NodeChild = ChildText TextLine
| ChildDrawer Drawer
| ChildNode Node
| ChildBabel Babel
| ChildTable Table
deriving (Eq, Show)
data Node = Node
{ nDepth :: Int
, nPrefix :: Maybe Prefix
, nTags :: [String]
, nChildren :: [NodeChild]
, nTopic :: String
, nLine :: TextLine
} deriving (Eq, Show)
data OrgFileProperty = OrgFileProperty { fpName :: String
, fpValue :: String
} deriving (Eq, Show)
data OrgDoc = OrgDoc
{ odNodes :: [Node]
, odProperties :: [OrgFileProperty]
, odLines :: [TextLine]
} deriving (Eq, Show)
instance TextLineSource NodeChild where
getTextLines (ChildText l) = [l]
getTextLines (ChildDrawer d) = drLines d
getTextLines (ChildNode n) = getTextLines n
getTextLines (ChildBabel (Babel lines)) = lines
getTextLines (ChildTable (Table lines)) = lines
instance TextLineSource Node where
getTextLines node =
(nLine node) : (concatMap getTextLines $ nChildren node)
instance TextLineSource OrgFileProperty where
getTextLines prop =
[TextLine 0 ("#+" ++ (fpName prop) ++ ": " ++ (fpValue prop)) Nothing]
trim xs =
let rstrip xs = reverse $ lstrip $ reverse xs
lstrip = dropWhile (== ' ')
in lstrip $ rstrip xs
makeNodeLine :: Node -> String
makeNodeLine (Node depth prefix tags children topic _) =
stars ++ " " ++ pfx ++ topic ++ " " ++ tgs
where
stars = take depth $ repeat '*'
pfx = case prefix of
Just (Prefix s) -> (s ++ " ")
Nothing -> ""
tgs = if length tags > 0
then ":" ++ (intercalate ":" tags) ++ ":"
else ""
updateNode :: (Node -> Maybe Node) -> Node -> Node
updateNode fn root =
let top = case (fn root) of
Nothing -> root
Just t -> t
all_children = nChildren top
updateChild c =
case c of
(ChildNode n) -> ChildNode $ updateNode fn n
otherwise -> c
in top { nChildren = map updateChild $ all_children }