-- |
-- /NOTE:/ This module is not meant for public consumption.  For user
-- documentation look at http://hspec.github.io/hspec-discover.html.
module Test.Hspec.Discover.Config (
  Config (..)
, defaultConfig
, parseConfig
, usage
) where

import           Data.Maybe
import           System.Console.GetOpt

data Config = Config {
  Config -> Bool
configNested :: Bool
, Config -> Maybe String
configFormatter :: Maybe String
, Config -> Bool
configNoMain :: Bool
, Config -> Maybe String
configModuleName :: Maybe String
} deriving (Config -> Config -> Bool
(Config -> Config -> Bool)
-> (Config -> Config -> Bool) -> Eq Config
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Config -> Config -> Bool
$c/= :: Config -> Config -> Bool
== :: Config -> Config -> Bool
$c== :: Config -> Config -> Bool
Eq, Int -> Config -> ShowS
[Config] -> ShowS
Config -> String
(Int -> Config -> ShowS)
-> (Config -> String) -> ([Config] -> ShowS) -> Show Config
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Config] -> ShowS
$cshowList :: [Config] -> ShowS
show :: Config -> String
$cshow :: Config -> String
showsPrec :: Int -> Config -> ShowS
$cshowsPrec :: Int -> Config -> ShowS
Show)

defaultConfig :: Config
defaultConfig :: Config
defaultConfig = Bool -> Maybe String -> Bool -> Maybe String -> Config
Config Bool
False Maybe String
forall a. Maybe a
Nothing Bool
False Maybe String
forall a. Maybe a
Nothing

options :: [OptDescr (Config -> Config)]
options :: [OptDescr (Config -> Config)]
options = [
    String
-> [String]
-> ArgDescr (Config -> Config)
-> String
-> OptDescr (Config -> Config)
forall a. String -> [String] -> ArgDescr a -> String -> OptDescr a
Option [] [String
"nested"] ((Config -> Config) -> ArgDescr (Config -> Config)
forall a. a -> ArgDescr a
NoArg ((Config -> Config) -> ArgDescr (Config -> Config))
-> (Config -> Config) -> ArgDescr (Config -> Config)
forall a b. (a -> b) -> a -> b
$ \Config
c -> Config
c {configNested :: Bool
configNested = Bool
True}) String
""
  , String
-> [String]
-> ArgDescr (Config -> Config)
-> String
-> OptDescr (Config -> Config)
forall a. String -> [String] -> ArgDescr a -> String -> OptDescr a
Option [] [String
"formatter"] ((String -> Config -> Config)
-> String -> ArgDescr (Config -> Config)
forall a. (String -> a) -> String -> ArgDescr a
ReqArg (\String
s Config
c -> Config
c {configFormatter :: Maybe String
configFormatter = String -> Maybe String
forall a. a -> Maybe a
Just String
s}) String
"FORMATTER") String
""
  , String
-> [String]
-> ArgDescr (Config -> Config)
-> String
-> OptDescr (Config -> Config)
forall a. String -> [String] -> ArgDescr a -> String -> OptDescr a
Option [] [String
"module-name"] ((String -> Config -> Config)
-> String -> ArgDescr (Config -> Config)
forall a. (String -> a) -> String -> ArgDescr a
ReqArg (\String
s Config
c -> Config
c {configModuleName :: Maybe String
configModuleName = String -> Maybe String
forall a. a -> Maybe a
Just String
s}) String
"NAME") String
""
  , String
-> [String]
-> ArgDescr (Config -> Config)
-> String
-> OptDescr (Config -> Config)
forall a. String -> [String] -> ArgDescr a -> String -> OptDescr a
Option [] [String
"no-main"] ((Config -> Config) -> ArgDescr (Config -> Config)
forall a. a -> ArgDescr a
NoArg ((Config -> Config) -> ArgDescr (Config -> Config))
-> (Config -> Config) -> ArgDescr (Config -> Config)
forall a b. (a -> b) -> a -> b
$ \Config
c   -> Config
c {configNoMain :: Bool
configNoMain = Bool
True}) String
""
  ]

usage :: String -> String
usage :: ShowS
usage String
prog = String
"\nUsage: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
prog String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" SRC CUR DST [--module-name=NAME]\n"

parseConfig :: String -> [String] -> Either String Config
parseConfig :: String -> [String] -> Either String Config
parseConfig String
prog [String]
args = case ArgOrder (Config -> Config)
-> [OptDescr (Config -> Config)]
-> [String]
-> ([Config -> Config], [String], [String])
forall a.
ArgOrder a -> [OptDescr a] -> [String] -> ([a], [String], [String])
getOpt ArgOrder (Config -> Config)
forall a. ArgOrder a
Permute [OptDescr (Config -> Config)]
options [String]
args of
    ([Config -> Config]
opts, [], []) -> let
        c :: Config
c = ((Config -> (Config -> Config) -> Config)
-> Config -> [Config -> Config] -> Config
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl (((Config -> Config) -> Config -> Config)
-> Config -> (Config -> Config) -> Config
forall a b c. (a -> b -> c) -> b -> a -> c
flip (Config -> Config) -> Config -> Config
forall a. a -> a
id) Config
defaultConfig [Config -> Config]
opts)
      in
        if (Config -> Bool
configNoMain Config
c Bool -> Bool -> Bool
&& Maybe String -> Bool
forall a. Maybe a -> Bool
isJust (Config -> Maybe String
configFormatter Config
c))
           then
             String -> Either String Config
forall b. String -> Either String b
formatError String
"option `--formatter=<fmt>' does not make sense with `--no-main'\n"
           else
             Config -> Either String Config
forall a b. b -> Either a b
Right Config
c
    ([Config -> Config]
_, [String]
_, String
err:[String]
_)  -> String -> Either String Config
forall b. String -> Either String b
formatError String
err
    ([Config -> Config]
_, String
arg:[String]
_, [String]
_)  -> String -> Either String Config
forall b. String -> Either String b
formatError (String
"unexpected argument `" String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
arg String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"'\n")
  where
    formatError :: String -> Either String b
formatError String
err = String -> Either String b
forall a b. a -> Either a b
Left (String
prog String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
": " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
err String -> ShowS
forall a. [a] -> [a] -> [a]
++ ShowS
usage String
prog)