{-# LANGUAGE CPP #-}
module GetOpt.Declarative.Util (mkUsageInfo, mapOptDescr) where

import           Prelude ()
import           Test.Hspec.Core.Compat

import           System.Console.GetOpt

import           Test.Hspec.Core.Util

modifyHelp :: (String -> String) -> OptDescr a -> OptDescr a
modifyHelp :: forall a. (String -> String) -> OptDescr a -> OptDescr a
modifyHelp String -> String
modify (Option String
s [String]
n ArgDescr a
a String
help) = 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 :: forall a. String -> [OptDescr a] -> String
mkUsageInfo String
title = forall a. String -> [OptDescr a] -> String
usageInfo String
title forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [OptDescr a] -> [OptDescr a]
addLineBreaksForHelp forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [OptDescr a] -> [OptDescr a]
condenseNoOptions

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

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

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

condenseNoOptions :: [OptDescr a] -> [OptDescr a]
condenseNoOptions :: forall a. [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 forall a. Eq a => a -> a -> Bool
== (String
"no-" forall a. [a] -> [a] -> [a]
++ String
optionA) ->
    forall a. String -> [String] -> ArgDescr a -> String -> OptDescr a
Option String
"" [String
"[no-]" forall a. [a] -> [a] -> [a]
++ String
optionA] ArgDescr a
arg String
help forall a. a -> [a] -> [a]
: forall a. [OptDescr a] -> [OptDescr a]
condenseNoOptions [OptDescr a]
ys
  OptDescr a
x : [OptDescr a]
xs -> OptDescr a
x forall a. a -> [a] -> [a]
: forall a. [OptDescr a] -> [OptDescr a]
condenseNoOptions [OptDescr a]
xs
  [] -> []

mapOptDescr :: (a -> b) -> OptDescr a -> OptDescr b
#if MIN_VERSION_base(4,7,0)
mapOptDescr :: forall a b. (a -> b) -> OptDescr a -> OptDescr b
mapOptDescr = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap
#else
mapOptDescr f opt = case opt of
  Option short long arg help -> Option short long (mapArgDescr f arg) help

mapArgDescr :: (a -> b) -> ArgDescr a -> ArgDescr b
mapArgDescr f arg = case arg of
  NoArg a -> NoArg (f a)
  ReqArg parse name -> ReqArg (fmap f parse) name
  OptArg parse name -> OptArg (fmap f parse) name
#endif