{-# LANGUAGE DeriveDataTypeable, RecordWildCards #-} import System.IO import System.Console.CmdArgs import Control.Monad (when) import Paths_alea (getDataFileName) import Alea.Diceware import Alea.Random _NAME = "Alea" _VERSION = "0.1.0" _INFO = _NAME ++ " version " ++ _VERSION _ABOUT = "a diceware passphrase generator" _COPYRIGHT = "(C) Michele Guerini Rocco 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 = getProgArgs >>= defaults >>= exec -- Assign defaults value to unspecified args defaults :: Args -> IO Args defaults args@Args{..} = do dictionary <- getDataFileName "dict/diceware" >>= readFile return args { dictionary = dictionary , phraseLength = if phraseLength == 0 then 6 else phraseLength } exec :: Args -> IO () exec args@Args{..} = if interactive then interact (unlines . map dice . lines) else do randWords dictSize phraseLength >>= putStrLn . unwords . map dice' when (phrases > 1) $ exec args {phrases = phrases - 1} where -- helpers dice n = readDiceware (parseDiceware dictionary) (read n :: Int) dice' n = readDiceware' (parseDiceware dictionary) n dictSize = size $ parseDiceware dictionary