cmdargs-0.1: System/Console/CmdArgs/Type.hs
{-# 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 <function>"
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