@@ -0,0 +1,118 @@
1+{-
2+ Copyright (C) 2018 Yan Pashkovsky <yanp.bugz@gmail.com>
3+
4+This program is free software; you can redistribute it and/or modify
5+it under the terms of the GNU General Public License as published by
6+the Free Software Foundation; either version 2 of the License, or
7+(at your option) any later version.
8+
9+This program is distributed in the hope that it will be useful,
10+but WITHOUT ANY WARRANTY; without even the implied warranty of
11+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+GNU General Public License for more details.
13+
14+You should have received a copy of the GNU General Public License
15+along with this program; if not, write to the Free Software
16+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17+-}
18+
19+{- |
20+ Module : Text.Pandoc.Readers.Man
21+ Copyright : Copyright (C) 2018 Yan Pashkovsky
22+ License : GNU GPL, version 2 or above
23+
24+ Maintainer : Yan Pashkovsky <yanp.bugz@gmail.com>
25+ Stability : WIP
26+ Portability : portable
27+
28+Conversion of man to 'Pandoc' document.
29+-}
30+module Text.Pandoc.Readers.Man where
31+
32+import Control.Monad.Except (liftM2, throwError, guard)
33+import Text.Pandoc.Class (PandocMonad(..))
34+import Text.Pandoc.Definition
35+import Text.Pandoc.Options
36+import Text.Pandoc.Parsing hiding (enclosed)
37+import Text.Pandoc.Shared (crFilter)
38+import Text.Parsec
39+import Text.Parsec.Char
40+import Data.Text (Text)
41+import Data.Map (empty)
42+import qualified Data.Text as T
43+
44+
45+-- | Read man (troff) from an input string and return a Pandoc document.
46+readMan :: PandocMonad m
47+ => ReaderOptions
48+ -> Text
49+ -> m Pandoc
50+readMan opts s = do
51+ parsed <- readWithM parseMan def{ stateOptions = opts } (T.unpack s)
52+ case parsed of
53+ Right result -> return result
54+ Left e -> throwError e
55+
56+type ManParser m = ParserT [Char] ParserState m
57+
58+comment :: PandocMonad m => ManParser m String
59+comment = do
60+ string ".\\\" "
61+ many anyChar
62+
63+data Macro = Macro { macroName :: String
64+ , macroArgs :: [String]
65+ }
66+
67+parseMacro :: PandocMonad m => ManParser m Block
68+parseMacro = do
69+ m <- macro
70+ return $ Plain (map Str $ (macroName m : macroArgs m))
71+
72+macro :: PandocMonad m => ManParser m Macro
73+macro = do
74+ char '.' <|> char '\''
75+ many space
76+ name <- many1 letter
77+ --args <- many parseArg
78+ return $ Macro { macroName = name, macroArgs = [] }
79+
80+ where
81+
82+ parseArg :: PandocMonad m => ManParser m String
83+ parseArg = do
84+ many1 space
85+ plainArg
86+
87+ quotedArg :: PandocMonad m => ManParser m String
88+ quotedArg = do
89+ char '"'
90+ val <- many1 quotedChar
91+ char '"'
92+ return val
93+
94+ plainArg :: PandocMonad m => ManParser m String
95+ plainArg = do
96+ many1 $ noneOf " \t"
97+
98+ quotedChar :: PandocMonad m => ManParser m Char
99+ quotedChar = do
100+ noneOf "\""
101+ <|> try (string "\"\"" >> return '"')
102+
103+parseLine :: PandocMonad m => ManParser m Block
104+parseLine = do
105+ str <- many anyChar
106+ return $ Plain [Str str]
107+
108+parseBlock :: PandocMonad m => ManParser m Block
109+parseBlock = do
110+ choice [ parseMacro
111+ , parseLine
112+ ]
113+
114+parseMan :: PandocMonad m => ManParser m Pandoc
115+parseMan = do
116+ blocks <- parseBlock `sepBy` newline
117+
118+ return $ Pandoc Meta{unMeta = empty} blocks