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 modify :: String -> String
modify (Option s :: String
s n :: [String]
n a :: ArgDescr a
a help :: 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 title :: 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 options :: [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 "" ([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 = 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 "")

condenseNoOptions :: [OptDescr a] -> [OptDescr a]
condenseNoOptions :: [OptDescr a] -> [OptDescr a]
condenseNoOptions options :: [OptDescr a]
options = case [OptDescr a]
options of
  Option "" [optionA :: String
optionA] arg :: ArgDescr a
arg help :: String
help : Option "" [optionB :: String
optionB] _ _ : ys :: [OptDescr a]
ys | String
optionB String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== ("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 "" ["[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
  x :: OptDescr a
x : xs :: [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 xs :: [String]
xs = case [String]
xs of
  [] -> ""
  x :: String
x : ys :: [String]
ys -> (case [String]
ys of
    [] -> String
x
    _ : [] -> String
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ " or "
    _ : _ : _ -> String
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ ", ") String -> String -> String
forall a. [a] -> [a] -> [a]
++ [String] -> String
formatOrList [String]
ys