module Test.Hspec.Core.Config.Util where

import           System.Console.GetOpt

import           Test.Hspec.Core.Util

modifyHelp :: (String -> String) -> OptDescr a -> OptDescr a
modifyHelp :: (String -> String) -> OptDescr a -> OptDescr a
modifyHelp String -> String
modify (Option String
s [String]
n ArgDescr a
a String
help) = String -> [String] -> ArgDescr a -> String -> OptDescr a
forall a. String -> [String] -> ArgDescr a -> String -> OptDescr a
Option String
s [String]
n ArgDescr a
a (String -> String
modify String
help)

mkUsageInfo :: String -> [OptDescr a] -> String
mkUsageInfo :: String -> [OptDescr a] -> String
mkUsageInfo String
title = String -> [OptDescr a] -> String
forall a. String -> [OptDescr a] -> String
usageInfo String
title ([OptDescr a] -> String)
-> ([OptDescr a] -> [OptDescr a]) -> [OptDescr a] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [OptDescr a] -> [OptDescr a]
forall a. [OptDescr a] -> [OptDescr a]
addLineBreaksForHelp ([OptDescr a] -> [OptDescr a])
-> ([OptDescr a] -> [OptDescr a]) -> [OptDescr a] -> [OptDescr a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [OptDescr a] -> [OptDescr a]
forall a. [OptDescr a] -> [OptDescr a]
condenseNoOptions

addLineBreaksForHelp :: [OptDescr a] -> [OptDescr a]
addLineBreaksForHelp :: [OptDescr a] -> [OptDescr a]
addLineBreaksForHelp [OptDescr a]
options = (OptDescr a -> OptDescr a) -> [OptDescr a] -> [OptDescr a]
forall a b. (a -> b) -> [a] -> [b]
map ((String -> String) -> OptDescr a -> OptDescr a
forall a. (String -> String) -> OptDescr a -> OptDescr a
modifyHelp String -> String
addLineBreaks) [OptDescr a]
options
  where
    withoutHelpWidth :: [OptDescr a] -> Int
withoutHelpWidth = String -> Int
maxLength (String -> Int) -> ([OptDescr a] -> String) -> [OptDescr a] -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [OptDescr a] -> String
forall a. String -> [OptDescr a] -> String
usageInfo String
"" ([OptDescr a] -> String)
-> ([OptDescr a] -> [OptDescr a]) -> [OptDescr a] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (OptDescr a -> OptDescr a) -> [OptDescr a] -> [OptDescr a]
forall a b. (a -> b) -> [a] -> [b]
map OptDescr a -> OptDescr a
forall a. OptDescr a -> OptDescr a
removeHelp
    helpWidth :: Int
helpWidth = Int
80 Int -> Int -> Int
forall a. Num a => a -> a -> a
- [OptDescr a] -> Int
forall a. [OptDescr a] -> Int
withoutHelpWidth [OptDescr a]
options

    addLineBreaks :: String -> String
addLineBreaks = [String] -> String
unlines ([String] -> String) -> (String -> [String]) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> String -> [String]
lineBreaksAt Int
helpWidth

    maxLength :: String -> Int
maxLength = [Int] -> Int
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum ([Int] -> Int) -> (String -> [Int]) -> String -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String -> Int) -> [String] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([String] -> [Int]) -> (String -> [String]) -> String -> [Int]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String]
lines
    removeHelp :: OptDescr a -> OptDescr a
removeHelp = (String -> String) -> OptDescr a -> OptDescr a
forall a. (String -> String) -> OptDescr a -> OptDescr a
modifyHelp (String -> String -> String
forall a b. a -> b -> a
const String
"")

condenseNoOptions :: [OptDescr a] -> [OptDescr a]
condenseNoOptions :: [OptDescr a] -> [OptDescr a]
condenseNoOptions [OptDescr a]
options = case [OptDescr a]
options of
  Option String
"" [String
optionA] ArgDescr a
arg String
help : Option String
"" [String
optionB] ArgDescr a
_ String
_ : [OptDescr a]
ys | String
optionB String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== (String
"no-" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
optionA) ->
    String -> [String] -> ArgDescr a -> String -> OptDescr a
forall a. String -> [String] -> ArgDescr a -> String -> OptDescr a
Option String
"" [String
"[no-]" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
optionA] ArgDescr a
arg String
help OptDescr a -> [OptDescr a] -> [OptDescr a]
forall a. a -> [a] -> [a]
: [OptDescr a] -> [OptDescr a]
forall a. [OptDescr a] -> [OptDescr a]
condenseNoOptions [OptDescr a]
ys
  OptDescr a
x : [OptDescr a]
xs -> OptDescr a
x OptDescr a -> [OptDescr a] -> [OptDescr a]
forall a. a -> [a] -> [a]
: [OptDescr a] -> [OptDescr a]
forall a. [OptDescr a] -> [OptDescr a]
condenseNoOptions [OptDescr a]
xs
  [] -> []

formatOrList :: [String] -> String
formatOrList :: [String] -> String
formatOrList [String]
xs = case [String]
xs of
  [] -> String
""
  String
x : [String]
ys -> (case [String]
ys of
    [] -> String
x
    String
_ : [] -> String
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" or "
    String
_ : String
_ : [String]
_ -> String
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
", ") String -> String -> String
forall a. [a] -> [a] -> [a]
++ [String] -> String
formatOrList [String]
ys