module Main where import Control.Monad import Data.List import System.Console.GetOpt import System.Environment import System.Exit import System.IO import System.Random import Data.Elocrypt version = "elocrypt 0.3.2" main :: IO () main = do args <- getArgs opts <- elocryptOpts args gen <- getStdGen -- TODO: Refactor me if (optHelp opts) then do hPutStrLn stderr usage exitSuccess else return () -- TODO: Refactor me if (optVersion opts) then do hPutStrLn stderr version exitSuccess else return () putStrLn (passwords opts gen) passwords :: RandomGen g => Options -> g -> String passwords opts gen = concat . intersperse "\n" . map (concat . intersperse "\t") . group $ ps where ps = take (optNumber opts) . newPasswords (optLength opts) $ gen group (p:ps:pss:psss) = [p, ps, pss]:(group psss) group ps = [ps] data Options = Options { optLength :: Int, -- Size of the password(s) optNumber :: Int, -- Number of passwords to generate optHelp :: Bool, optVersion :: Bool } deriving (Show) defaultOptions :: Options defaultOptions = Options { optLength = 8, optNumber = 42, optHelp = False, optVersion = False } options :: [OptDescr (Options -> Options)] options = [Option ['n'] ["number"] (ReqArg (\n o -> o {optNumber = read n}) "NUMBER") "The number of passwords to generate (default: 42)", Option ['h'] ["help"] (NoArg (\o -> o { optHelp = True })) "Show this help", Option ['v'] ["version"] (NoArg (\o -> o { optVersion = True })) "Show version and exit"] elocryptOpts :: [String] -> IO Options elocryptOpts args = do (opts, nonopts) <- elocryptOpts' args return $ if (null nonopts) then opts else opts { optLength = read (head nonopts) } elocryptOpts' :: [String] -> IO (Options, [String]) elocryptOpts' args = case getOpt Permute options args of (opts, nonopts, []) -> return (foldl (flip id) defaultOptions opts, nonopts) (_ , _ , errs) -> do -- TODO: Refactor me hPutStrLn stderr (concat errs) hPutStrLn stderr usage exitFailure usage :: String usage = usageInfo header options where header = "Usage: elocrypt [option...] length"