packages feed

alea 0.4.0.0 → 0.5.0.0

raw patch · 5 files changed

+107/−85 lines, 5 filesdep +optparse-applicativedep +randomdep +textdep −argparserdep −containersdep −threefish

Dependencies added: optparse-applicative, random, text

Dependencies removed: argparser, containers, threefish

Files

alea.cabal view
@@ -1,5 +1,5 @@ name:                alea-version:             0.4.0.0+version:             0.5.0.0 synopsis:            a diceware passphrase generator description: @@ -10,7 +10,7 @@ homepage:            https://github.com/Rnhmjoj/alea license:             MIT license-file:        LICENSE-author:              Rnhmjoj+author:              rnhmjoj maintainer:          micheleguerinirocco@me.com copyright:           (C) Michele Guerini Rocco 2015 category:            Utility@@ -27,8 +27,8 @@   main-is:             Main.hs   hs-source-dirs:      src   default-language:    Haskell2010-  other-modules:       Alea.Diceware, Alea.List, Alea.Random+  other-modules:       Alea.Diceware   other-extensions:    DeriveDataTypeable, RecordWildCards-  build-depends:       base >=4.8 && < 5.0, containers,-                       argparser, threefish+  build-depends:       base >=4.8 && < 5.0, random, text,+                       optparse-applicative    ghc-options:         -O2
src/Alea/Diceware.hs view
@@ -1,28 +1,42 @@+{-# LANGUAGE OverloadedStrings #-}+ module Alea.Diceware where -import Data.List  (intersect, elemIndex)-import Alea.List+import Data.Monoid   ((<>))+import Data.List     (intersect, elemIndex)+import Data.Text     (Text, pack)+import System.Random+import qualified Data.Text as T --- Diceware dictionary type-type Diceware = [String] --- Parse file content to a Diceware-parseDiceware :: String -> Diceware-parseDiceware x = map (last . split ' ') $ lines x+-- | Diceware dictionary alias+type Diceware = [Text] --- Lookup word with dice index-readDiceware :: Diceware -> Int -> String-readDiceware d n = show n ++ " -> " ++-  case (undice n) of-    Just x -> d !! x-    Nothing -> "Does not exist" --- Lookup word with linear index-readDiceware' :: Diceware -> Int -> String+-- | Produces k random indices to be extracted+randIndices :: Int -> Int -> IO [Int]+randIndices n k = take k <$> randomRs (0, n-1) <$> newStdGen+++-- | Parse file content to a Diceware+parseDiceware :: Text -> Diceware+parseDiceware = map (last . T.splitOn " ") . T.lines+++-- | Lookup word with dice index+readDiceware :: Diceware -> Int -> Text+readDiceware d n =+  pack (show n) <> " -> " <>+  maybe "Does not exists" (d !!) (fromDice n)+++-- | Lookup word with linear index+readDiceware' :: Diceware -> Int -> Text readDiceware' d n = d !! n --- Dice numbers to numbers--- Ex. undice 11121 == Just 6-undice :: Int -> Maybe Int-undice n = elemIndex n . filter-  (null . (intersect "0789") . show) $ [11111..66666]++-- | Dice numbers to numbers+-- > fromDice 11121 == Just 6+fromDice :: Int -> Maybe Int+fromDice n = elemIndex n (filter isDice [11111..66666])+  where isDice = null . (intersect "0789") . show
− src/Alea/List.hs
@@ -1,10 +0,0 @@-module Alea.List where---- Split a list into a list of lists--- ex. split ',' "ab,cd,ef" == ["ab","cd","ef"]-split :: (Eq a) => a -> [a] -> [[a]]-split _ [] = [[]]-split delim (c:cs)-  | c == delim = [] : rest-  | otherwise = (c : head rest) : tail rest-  where rest = split delim cs
− src/Alea/Random.hs
@@ -1,6 +0,0 @@-module Alea.Random where--import Crypto.Threefish.Random--randWords :: Int -> Int -> IO [Int]-randWords n k = take k . randomRs (0, n-1) <$> newSkeinGen
src/Main.hs view
@@ -1,55 +1,79 @@ {-# LANGUAGE RecordWildCards #-} -import System.IO-import System.Console.ArgParser-import Control.Monad--import Paths_alea (getDataFileName)+import Control.Monad             (when, forever)+import Data.Text                 (unpack)+import Options.Applicative import Alea.Diceware-import Alea.Random+import Paths_alea                (getDataFileName) -data ProgArgs = ProgArgs-	{ interactive  :: Bool-	, dictionary   :: FilePath-	, phraseLength :: Int-	, phrases      :: Int-	} deriving (Show)+import qualified Data.Text    as T+import qualified Data.Text.IO as I -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)+-- * Command line interface description +-- | Program arguments record+data Options = Options+  { interactive  :: Bool+  , dictionary   :: Maybe FilePath+  , phraseLength :: Int+  , phrases      :: Int+  }+++-- | Argument parser +options :: Parser Options+options = Options +  <$> switch+      ( long "interactive"+     <> help "Manually insert numbers from a dice" )+  <*> optional (option auto+      ( long "dictionary"+     <> metavar "FILEPATH"+     <> help "Specify dictionary filepath" ))+  <*> option auto+      ( long "length"+     <> value 6+     <> metavar "N"+     <> help "Number of words in a passphrase")+  <*> option auto+     ( long "phrases"+    <> value 1+    <> metavar "M"+    <> help "Number of passphrases to generate" )+  ++-- | Program description+description :: ParserInfo Options+description = info (helper <*> options)+  ( fullDesc+ <> progDesc "A diceware passphrase generator"+ <> footer "Alea iacta est." )++++-- * Program++-- | Main function main :: IO ()-main = interface >>= flip runApp (readDict >=> exec)+main = execParser description >>= diceware --- 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+-- | Actual application +diceware :: Options -> IO ()+diceware opts@Options{..} = do+  path <- case dictionary of+    Nothing -> getDataFileName "dict/diceware"+    Just x  -> return x+  dict <- parseDiceware <$> I.readFile path+  let size  = length dict-1+      dice  = readDiceware  dict . read . unpack+      dice' = readDiceware' dict --- 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+  if interactive+    then forever (dice <$> I.getLine >>= I.putStrLn)+    else do+      indices <- randIndices size phraseLength+      I.putStrLn $ T.unwords (map dice' indices)+      when (phrases > 1) $+        diceware opts {phrases = phrases - 1}