@@ -77,14 +77,24 @@ data ManToken = MStr RoffStr
7777 | MEndMacro
7878 deriving Show
7979
80−data RoffState = RoffState { fontKind :: Font
80+data RoffState = RoffState { fontKind :: Font
8181 } deriving Show
8282
8383instance Default RoffState where
84− def = RoffState {fontKind = singleton Regular}
84+ def = RoffState { fontKind = singleton Regular }
85+
86+data ManState = ManState { customMacros :: M.Map String Blocks
87+ , readerOptions :: ReaderOptions
88+ , metadata :: Meta
89+ } deriving Show
90+
91+instance Default ManState where
92+ def = ManState { customMacros = mempty
93+ , readerOptions = def
94+ , metadata = nullMeta }
8595
8696type ManLexer m = ParserT [Char] RoffState m
87−type ManParser m = ParserT [ManToken] ParserState m
97+type ManParser m = ParserT [ManToken] ManState m
8898
8999
90100-- | Read man (troff) from an input string and return a Pandoc document.
@@ -94,15 +104,15 @@ readMan opts txt = do
94104 case eithertokens of
95105 Left e -> throwError e
96106 Right tokenz -> do
97− let state = def {stateOptions = opts} :: ParserState
107+ let state = def {readerOptions = opts} :: ManState
98108 eitherdoc <- readWithMTokens parseMan state tokenz
99109 either throwError return eitherdoc
100110
101111 where
102112
103113 readWithMTokens :: PandocMonad m
104− => ParserT [ManToken] ParserState m a -- ^ parser
105− -> ParserState -- ^ initial state
114+ => ParserT [ManToken] ManState m a -- ^ parser
115+ -> ManState -- ^ initial state
106116 -> [ManToken] -- ^ input
107117 -> m (Either PandocError a)
108118 readWithMTokens parser state input =
@@ -123,7 +133,7 @@ lexMan = many (lexComment <|> lexMacro <|> lexLine <|> lexEmptyLine)
123133parseMan :: PandocMonad m => ManParser m Pandoc
124134parseMan = do
125135 bs <- many parseBlock <* eof
126− meta <- stateMeta <$> getState
136+ meta <- metadata <$> getState
127137 let (Pandoc _ blocks) = doc $ mconcat bs
128138 return $ Pandoc meta blocks
129139
@@ -137,7 +147,7 @@ parseBlock = choice [ parseList
137147 , parseCodeBlock
138148 , parseHeader
139149 , parseMacroDef
140− , parseSkipMacro
150+ , parseUnkownMacro
141151 ]
142152
143153eofline :: Stream s m Char => ParsecT s u m ()
@@ -410,7 +420,7 @@ parseTitle = do
410420 [x,y] -> setMeta "title" x . setMeta "section" y
411421 [x] -> setMeta "title" x
412422 [] -> id
413− modifyState $ \st -> st{ stateMeta = adjustMeta $ stateMeta st }
423+ modifyState $ \st -> st{ metadata = adjustMeta $ metadata st }
414424 return mempty
415425
416426parseSkippedContent :: PandocMonad m => ManParser m Blocks
@@ -570,9 +580,16 @@ parseDefinitionList = definitionList <$> many1 definitionListItem
570580
571581parseMacroDef :: PandocMonad m => ManParser m Blocks
572582parseMacroDef = do
573− MMacro _ _args <- mmacro "de"
574− bs <- manyTill parseBlock endMacro
575− return mempty -- TODO for now just skip it
583+ MMacro _ args <- mmacro "de"
584+ (macroName, endMacro') <-
585+ case args of
586+ ((x,_):(y,_):_) -> return (x, mmacro y) -- optional second arg
587+ ((x,_):_) -> return (x, endMacro)
588+ [] -> fail "No argument to .de"
589+ bs <- mconcat <$> manyTill parseBlock endMacro'
590+ modifyState $ \st ->
591+ st{ customMacros = M.insert macroName bs (customMacros st) }
592+ return mempty
576593
577594 where
578595 endMacro = (msatisfy (\t -> case t of
@@ -580,11 +597,16 @@ parseMacroDef = do
580597 _ -> False))
581598
582599-- In case of weird man file it will be parsed succesfully
583−parseSkipMacro :: PandocMonad m => ManParser m Blocks
584−parseSkipMacro = do
600+parseUnkownMacro :: PandocMonad m => ManParser m Blocks
601+parseUnkownMacro = do
585602 pos <- getPosition
586603 tok <- mmacroAny
587604 case tok of
588− MMacro mkind _ -> report $ SkippedContent ('.':mkind) pos
589− _ -> return () -- shouldn't happen
590− return mempty
605+ MMacro mkind _ -> do
606+ macros <- customMacros <$> getState
607+ case M.lookup mkind macros of
608+ Nothing -> do
609+ report $ SkippedContent ('.':mkind) pos
610+ return mempty
611+ Just bs -> return bs
612+ _ -> fail "the impossible happened"