{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Text.Enum.Optparse
(
parseIO
, parseIOWithArgs
, pureParse
, testCLI
, ParserDetails(..)
, mkParserInfo
, MetaVar
, HelpText
, FlagName
, FlagChar
, enumArgP
, argP
, argP'
, enumOptP
, optP
, enumSwitchesP
, shortEnumSwitchesP
, module Text.Enum.Text
) where
import Control.Applicative
import Data.Char
import qualified Data.Text as T
import Fmt
import Options.Applicative
import System.Environment
import Text.Enum.Text
parseIO :: ParserDetails -> Parser a -> IO a
parseIO pd psr = getArgs >>= parseIOWithArgs pd psr
parseIOWithArgs :: ParserDetails -> Parser a -> [String] -> IO a
parseIOWithArgs pd psr as = handleParseResult $
execParserPure (prefs idm) (mkParserInfo pd psr) as
pureParse :: ParserDetails -> Parser a -> [String] -> Maybe a
pureParse pd p =
getParseResult . execParserPure (prefs idm) (mkParserInfo pd p)
testCLI :: Show a => ParserDetails -> Parser a -> [String] -> IO ()
testCLI pd psr ss = do
x <- handleParseResult $
execParserPure (prefs idm) (mkParserInfo pd psr) ss
print x
data ParserDetails =
ParserDetails
{ _pd_desc :: String
, _pd_header :: String
, _pd_footer :: String
}
deriving (Show)
mkParserInfo :: ParserDetails -> Parser a -> ParserInfo a
mkParserInfo ParserDetails{..} p =
info (helper <*> p)
$ fullDesc
<> progDesc _pd_desc
<> header _pd_header
<> footer _pd_footer
type MetaVar = String
type HelpText = String
type FlagName = String
type FlagChar = Char
enumArgP :: forall a . EnumText a => MetaVar -> Parser a
enumArgP var = argP var hlp
where
hlp = T.unpack $ T.intercalate "|" $
map (fmt . build) [minBound..maxBound :: a]
argP :: TextParsable a => MetaVar -> HelpText -> Parser a
argP = argP' parseText
argP' :: (T.Text->Either String a) -> MetaVar -> String -> Parser a
argP' prs var hlp = argument (eitherReader $ prs . T.pack)
$ metavar var
<> help hlp
enumOptP :: forall a . EnumText a => FlagChar -> MetaVar -> Parser a
enumOptP c var = optP c var hlp
where
hlp = T.unpack $ T.intercalate "|" $
map (fmt . build) [minBound..maxBound :: a]
optP :: TextParsable a => FlagChar -> FlagName -> HelpText -> Parser a
optP ch nme hlp = option (eitherReader parse_string)
$ metavar var
<> short ch
<> long lng
<> help hlp
where
var = map toUpper nme
lng = map toLower nme
enumSwitchesP :: EnumText a => Parser a
enumSwitchesP = shortEnumSwitchesP $ const Nothing
shortEnumSwitchesP :: forall a . EnumText a => (a->Maybe FlagChar) -> Parser a
shortEnumSwitchesP sh_f = foldr (<|>) empty $ map mk [minBound..maxBound]
where
mk :: a -> Parser a
mk x = flag' x $ (long $ fmt $ build x) <> shrt
where
shrt = case sh_f x of
Nothing -> mempty
Just c -> short c
parse_string :: TextParsable a => String -> Either String a
parse_string = parseText . T.pack