{-# LANGUAGE DeriveDataTypeable, RecordWildCards #-} import System.IO import System.Console.CmdArgs import System.Environment (getArgs, withArgs) import Control.Monad (when) import Paths_alea (getDataFileName) import Diceware import Random _NAME = "Alea" _VERSION = "0.1.0" _INFO = _NAME ++ " version " ++ _VERSION _ABOUT = "a diceware passphrase generator" _COPYRIGHT = "(C) Rnhmjoj 2014" data Args = Args { interactive :: Bool , dictionary :: FilePath , phraseLength :: Int , phrases :: Int } deriving (Data, Typeable, Show, Eq) progArgs :: Args progArgs = Args { interactive = def &= help "Manually insert numbers" , dictionary = def &= help "Specify dictionary file path" , phraseLength = def &= help "Number of words in a passphrase" , phrases = def &= help "Number of passphrases to generate" } getProgArgs :: IO Args getProgArgs = cmdArgs $ progArgs &= versionArg [explicit, name "version", name "v", summary _INFO] &= summary (_INFO ++ ", " ++ _COPYRIGHT) &= help _ABOUT &= helpArg [explicit, name "help", name "h"] &= program _NAME main :: IO () main = do args <- getArgs opts <- getProgArgs exec opts exec :: Args -> IO () exec opts@Args{..} = do opts <- getProgArgs defaultDict <- getDataFileName "diceware" file <- readFile (if null dictionary then defaultDict else dictionary) if interactive then interact (unlines . map (dice file) . lines) else do phrase <- randWords (size $ parseDiceware file) phraseLength' putStrLn . unwords . map (dice' file) $ phrase when (phrases > 1) $ exec opts {phrases = phrases - 1} where -- helpers dice x n = readDiceware (parseDiceware x) (read n :: Int) dice' x n = readDiceware' (parseDiceware x) n -- default arguments phraseLength' = if phraseLength == 0 then 6 else phraseLength