packages feed

system-uuid-1.3.0: Main.hs

{- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

 USAGE: hooty (-1|-4)? (-n <number to make>)?

  The `hooty` program generates any number of UUIDs (one by default), using
  either the version 1 (time and MAC) or version 4 (random) algorithm (version
  1 is the default). On all platforms, `hooty` uses the native implementation.

    -n, --number <number>       Create <number> many UUIDs in one go.

    -1, --sequential            Create version 1 (time and MAC) UUIDs.

    -4, --random                Create version 4 (random) UUIDs.

    -h, -?, --help              Print this help and exit.

    --version                   Print version and exit.

 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -}

{-# LANGUAGE TemplateHaskell
           , PatternGuards
  #-}

import qualified System.UUID.V1 as V1
import qualified System.UUID.V4 as V4
import Options
import Messages 
import qualified Macros as Macros
import System.Environment
import System.Exit
import Control.Monad
import Control.Applicative
import Data.Maybe
import Data.Word
import qualified Data.Map as Map

main                         =  do
  m                         <-  opts
  let
    lk                       =  (`Map.lookup` m)
  when (isJust $ lk "h") $ do
    stdout << usage
    exitWith ExitSuccess
  when (isJust $ lk "version") $ do
    stdout << version
    exitWith ExitSuccess
  when (all (isJust . lk) ["1","4"]) $ do
    bail "Please specify either version 1 or version 4, not both."
  let
    n                       ::  Word
    n                        =  fromMaybe 1 $ maybeRead =<< lk "n"
    gen =
      if isJust $ lk "4"
        then  V4.uuid
        else  V1.uuid
  mapM_ (const $ print =<< gen) [1..n]


bail                        ::  String -> IO a
bail s                       =  do 
  stderr << s
  stderr << usage
  exitFailure


usage                        =  $(Macros.usage)

version                      =  "hooty-" ++ $(Macros.version)


opts                         =  do
  args                      <-  getArgs
  case runParser options () "command line arguments" args of
    Right list              ->  return $ foldr ($) Map.empty list
    Left e                  ->  bail $ show e


options                      =  do
  res                       <-  choice
    [ eof >> return []
    , many1 options'
    ]
  eof
  return res


options'                     =  do
  o                         <-  choice opts
  opt o
 where
  opt o@[c]
    | c `elem` "h14"         =  return $ Map.insert o ""
    | c == 'n'               =  choice
          [ eof >> fail "Option requires an argument."
          , try $ do
              s             <-  initialChar '-'
              fail $ "Option requiring argument followed by:\n  " ++ s
          , fmap (Map.insert o) anyString
          ]
    | otherwise              =  prb $ "unimplemented option '" ++ o ++ "'"
  opt "version"              =  return $ Map.insert "version" ""
  opt o                      =  prb $ "unimplemented option '" ++ o ++ "'"
  prb s                      =  fail $ "Please report a bug -- " ++ s ++ "."
  opts                       =  map try
    [ option    "h?"            ["help"]
    , option    "1"             ["sequential"]
    , option    "4"             ["random"]
    , option    "n"             ["number"]
    , option    ""              ["version"]
    ] ++ [ fail "Invalid option." ]


maybeRead s
  | [(a, _)]     <- reads s  =  Just a
  | otherwise                =  Nothing