packages feed

alea-0.3.3.0: src/Main.hs

{-# LANGUAGE RecordWildCards #-}

import System.IO
import System.Console.ArgParser
import Control.Monad
import Control.Applicative

import Paths_alea (getDataFileName)
import Alea.Diceware
import Alea.Random

data ProgArgs = ProgArgs
	{ interactive  :: Bool
	, dictionary   :: FilePath
	, phraseLength :: Int
	, phrases      :: Int
	} deriving (Show)

parser :: IO (ParserSpec ProgArgs)
parser = (\path -> ProgArgs
  `parsedBy` boolFlag      "interactive" `Descr` "Manually insert numbers"
  `andBy`    optFlag  path "dictionary"  `Descr` "Specify dictionary file path"
  `andBy`    optFlag  6    "lenght"      `Descr` "Number of words in a passphrase"
  `andBy`    optFlag  1    "phrases"     `Descr` "Number of passphrases to generate")
  <$> path

interface :: IO (CmdLnInterface ProgArgs)
interface =
  (`setAppDescr` "A diceware passphrase generator") <$>
  (`setAppEpilog` "Alea iacta est.") <$>
  (mkApp =<< parser)

main :: IO ()
main = interface >>= flip runApp (readDict >=> exec)

-- Default path of the dictionary
path :: IO FilePath
path = getDataFileName "dict/diceware"

-- Read dictionary file
readDict :: ProgArgs -> IO ProgArgs
readDict args@ProgArgs{..} =
  (\x -> args {dictionary = x}) <$> readFile dictionary

-- Main function
exec :: ProgArgs -> IO ()
exec args@ProgArgs{..} =
	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
	  (dict, dictSize) = (parseDiceware dictionary, length dict)
	  dice  n = readDiceware  dict (read n :: Int)
	  dice' n = readDiceware' dict n