snm-0.0.1: bin/snm.hs
-- Generate simple and nice looking manuals
import Manual
import System.Environment
import System.Console.GetOpt
import Data.Maybe
import Data.List
import System.FilePath
import Control.Monad
import Data.Map (Map)
import qualified Data.Map as M
import Data.Maybe
import System.IO
-- Flags determine how we should behave
data ManFlag =
Dump
| OutputFile (Maybe String)
| OutputType {out_type :: OutputType}
| Help
deriving Eq
-- Match only output types
only_types :: ManFlag -> Bool
only_types (OutputType _) = True
only_types _ = False
-- Match only output flag
only_output :: ManFlag -> Bool
only_output (OutputFile _) = True
only_output _ = False
-- Get the output file
output_dir :: FilePath -> ManFlag -> FilePath
output_dir defaul flg =
case flg of
OutputFile ms -> fromMaybe defaul ms
_ -> error "Bug in snm.hs::output_dir!\nContact John Morrice at spoon@killersmurf.com"
-- The order of the arguments
order :: ArgOrder ManFlag
order = Permute
-- The options we use
options :: [OptDescr ManFlag]
options =
[dump, output_file, help, text_out, xhtml_out]
-- The user is requesting help
help :: OptDescr ManFlag
help =
Option "h" ["help"] (NoArg Help) "Print usage information"
-- The user requests output in xhtml
xhtml_out :: OptDescr ManFlag
xhtml_out =
Option "x" ["xhtml", "html"] (NoArg $ OutputType XHtml) "Output in xhtml format."
-- The user requests output in text
text_out :: OptDescr ManFlag
text_out =
Option "t" ["text", "txt"] (NoArg $ OutputType Text) "Text output."
-- The user requests ouput dumped to stdout
dump :: OptDescr ManFlag
dump =
Option "d" ["dump"] (NoArg Dump) "Print output to stdout."
-- The user requests output dumped to file
output_file :: OptDescr ManFlag
output_file =
Option "o" ["output"] (OptArg OutputFile "A file name") "Write output to a file. Multiple outputs ignored, printing warning to stderr."
-- Print usage information
usage :: IO ()
usage = do
nm <- getProgName
putStrLn $ usageInfo
(unlines [nm ++ ": The Simple Nice-Looking Manual Generator"
,"\nusage: "
," " ++ nm ++ " documentation_source_directory options*"
,"\nWhere options* stands for zero or more of the options below."
,"\nNote:"
," Only one output format is permitted per invocation."
," If -d or --dump is used, snm will not write a file unless -o or --output is also used."
," There can be no whitespace between -o and its argument, nor can there be whitespace between --output= and its argument"
," If no arguments are given to -o, then the file written will have the same filename as the documentation source directory, with an appropriate extension added."
," " ++ nm ++ " will always add an appropriate extension to output files."
," By default, snm will emit xhtml, and act as if the user had specified -o without an argument."])
options
-- "Make it so" - Jean Luc Picard.
main :: IO ()
main = do
-- get the args
as <- getArgs
-- get the options
let (unclean_flags, non, err) = getOpt order options as
-- clean the flags
flags = nub unclean_flags
user_output = msum $ map (flip M.lookup formats) $ map out_type $ filter only_types flags
output = fromMaybe (xhtml_format) user_output
-- terminate if there were errors
if null err
then do
case non of
(input:[]) -> do
man <- load_manual input
-- did the user tell us what to do?
if null flags
then
uncurry (undirected input man) output
else
if elem Help flags
then usage
else
uncurry (directed input man flags input) output
_ -> usage
else
usage
where
-- The user has specified what to do
directed input man flags defaul format ext = do
let outs = filter only_output flags
dump = elem Dump flags
-- dump the text if dump is present
when dump $ putStrLn $ format man
mout <- case outs of
(out:[]) -> return $ Just out
(out:n:_) -> do
hPutStrLn stderr
("Warning: multiple outputs ignored.")
return (Just out)
_ -> if dump then return Nothing else return $ Just $ OutputFile Nothing
maybe (return ())
(\out ->
write_manual format ext man $ output_dir defaul out)
mout
-- The default behaviour
undirected input man format ext =
write_manual format ext man (dropExtensions $ takeFileName input)