{-# LANGUAGE ScopedTypeVariables, PatternGuards #-} {-# OPTIONS_GHC -fno-warn-missing-fields #-} module System.Console.CmdArgs.Type where import Data.Dynamic import Data.Data import Data.List import Data.Maybe import Data.Char import Data.Function data Mode a = Mode {modeVal :: a ,modeName :: String ,modeText :: String ,modeHelpSuffix :: [String] ,modeExplicit :: Bool ,modeDef :: Bool ,modeProg :: Maybe String ,modeFlags :: [Flag] } deriving Show -- FIXME: The Show should be the --help modeDefault = Mode{modeText="",modeHelpSuffix=[],modeExplicit=False,modeDef=False,modeProg=Nothing} data Flag = Flag {flagName :: String -- field name ,flagKey :: String -- disambiguator (equal to field name, apart from enums) ,flagArgs :: Maybe (Maybe Int) -- Nothing = all arguments, Just i = position i, 0-based ,flagType :: FlagType ,flagVal :: Dynamic -- FIXME: Remove, only used in default computation ,flagOpt :: Maybe String ,flagTyp :: String ,flagText :: String ,flagFlag :: [String] ,flagUnknown :: Bool -- place to put unknown args ,flagExplicit :: Bool } deriving Show flagDefault = Flag{flagArgs=Nothing,flagOpt=Nothing,flagTyp="",flagText="",flagFlag=[],flagUnknown=False,flagExplicit=False} --------------------------------------------------------------------- -- STRUCTURED FLAGS isFlagFlag = not . isFlagArgs isFlagArgs = isJust . flagArgs isFlagBool x = case flagType x of FlagBool{} -> True; _ -> False isFlagOpt = isJust . flagOpt flagTypDef def x = case flagTyp x of "" -> def; y -> y -- Flag types data FlagType = FlagBool Dynamic | FlagItem (String -> Maybe (Dynamic -> Dynamic)) instance Show FlagType where show (FlagBool x) = "FlagBool " ++ show x show (FlagItem x) = "FlagItem " toFlagType :: TypeRep -> Maybe FlagType toFlagType typ | typ == typeOf True = Just $ FlagBool $ toDyn True | Just r <- toFlagTypeRead False typ = Just $ FlagItem r | a == typeRepTyCon (typeOf ""), Just r <- toFlagTypeRead True (head b) = Just $ FlagItem r where (a,b) = splitTyConApp typ toFlagTypeRead :: Bool -> TypeRep -> Maybe (String -> Maybe (Dynamic -> Dynamic)) toFlagTypeRead list x | x == typeOf "" = with (\x -> [(x,"")]) | x == typeOf (0 :: Int) = with (reads :: ReadS Int) | x == typeOf (0 :: Integer) = with (reads :: ReadS Integer) | x == typeOf (0 :: Float) = with (reads :: ReadS Float) | x == typeOf (0 :: Double) = with (reads :: ReadS Double) | otherwise = Nothing where with :: forall a . Typeable a => ReadS a -> Maybe (String -> Maybe (Dynamic -> Dynamic)) with r = Just $ \x -> case r x of [(v,"")] -> Just $ \old -> if list then toDyn $ fromJust (fromDynamic old) ++ [v] else toDyn v _ -> Nothing