1{-# LANGUAGE OverloadedStrings #-}
2{- |
3   Module      : Text.Pandoc.Readers.Org.BlockStarts
4   Copyright   : Copyright (C) 2014-2021 Albert Krewinkel
5   License     : GNU GPL, version 2 or above
6
7   Maintainer  : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
8
9Parsers for Org-mode inline elements.
10-}
11module Text.Pandoc.Readers.Org.BlockStarts
12  ( exampleLineStart
13  , hline
14  , noteMarker
15  , tableStart
16  , drawerStart
17  , headerStart
18  , metaLineStart
19  , latexEnvStart
20  , commentLineStart
21  , bulletListStart
22  , orderedListStart
23  , endOfBlock
24  ) where
25
26import Control.Monad (void)
27import Data.Text (Text)
28import qualified Data.Text as T
29import Text.Pandoc.Readers.Org.Parsing
30
31-- | Horizontal Line (five -- dashes or more)
32hline :: Monad m => OrgParser m ()
33hline = try $ do
34  skipSpaces
35  string "-----"
36  many (char '-')
37  skipSpaces
38  newline
39  return ()
40
41-- | Read the start of a header line, return the header level
42headerStart :: Monad m => OrgParser m Int
43headerStart = try $
44  (length <$> many1 (char '*')) <* many1 (char ' ') <* updateLastPreCharPos
45
46tableStart :: Monad m => OrgParser m Char
47tableStart = try $ skipSpaces *> char '|'
48
49gridTableStart :: Monad m => OrgParser m ()
50gridTableStart = try $ skipSpaces <* char '+' <* char '-'
51
52
53latexEnvStart :: Monad m => OrgParser m Text
54latexEnvStart = try $
55  skipSpaces *> string "\\begin{"
56             *> latexEnvName
57             <* string "}"
58             <* blankline
59 where
60   latexEnvName :: Monad m => OrgParser m Text
61   latexEnvName = try $ mappend <$> many1Char alphaNum <*> option "" (textStr "*")
62
63bulletListStart :: Monad m => OrgParser m Int
64bulletListStart = try $ do
65  ind <- length <$> many spaceChar
66   -- Unindented lists cannot use '*' bullets.
67  oneOf (if ind == 0 then "+-" else "*+-")
68  skipSpaces1 <|> lookAhead eol
69  return (ind + 1)
70
71genericListStart :: Monad m
72                 => OrgParser m Text
73                 -> OrgParser m Int
74genericListStart listMarker = try $ do
75  ind <- length <$> many spaceChar
76  void listMarker
77  skipSpaces1 <|> lookAhead eol
78  return (ind + 1)
79
80eol :: Monad m => OrgParser m ()
81eol = void (char '\n')
82
83orderedListStart :: Monad m => OrgParser m Int
84orderedListStart = genericListStart orderedListMarker
85  -- Ordered list markers allowed in org-mode
86  where orderedListMarker = T.snoc <$> many1Char digit <*> oneOf ".)"
87
88drawerStart :: Monad m => OrgParser m Text
89drawerStart = try $ skipSpaces *> drawerName <* skipSpaces <* newline
90 where drawerName = char ':' *> manyTillChar nonspaceChar (char ':')
91
92metaLineStart :: Monad m => OrgParser m ()
93metaLineStart = try $ skipSpaces <* string "#+"
94
95commentLineStart :: Monad m => OrgParser m ()
96commentLineStart = try $
97  -- the first char after '#' must be a plain space character or a newline
98  skipSpaces <* string "#" <* lookAhead (oneOf " \n")
99
100exampleLineStart :: Monad m => OrgParser m ()
101exampleLineStart = () <$ try (skipSpaces *> string ": ")
102
103noteMarker :: Monad m => OrgParser m Text
104noteMarker = try $ do
105  char '['
106  choice [ many1TillChar digit (char ']')
107         , (<>) <$> textStr "fn:"
108                <*> many1TillChar (noneOf "\n\r\t ") (char ']')
109         ]
110
111-- | Succeeds if the parser is at the end of a block.
112endOfBlock :: Monad m => OrgParser m ()
113endOfBlock = lookAhead . try $
114  void blankline <|> anyBlockStart
115 where
116   -- Succeeds if there is a new block starting at this position.
117   anyBlockStart :: Monad m => OrgParser m ()
118   anyBlockStart = try . choice $
119     [ exampleLineStart
120     , hline
121     , metaLineStart
122     , commentLineStart
123     , gridTableStart
124     , void noteMarker
125     , void tableStart
126     , void drawerStart
127     , void headerStart
128     , void latexEnvStart
129     , void bulletListStart
130     , void orderedListStart
131     ]
132