module Commander.Params (
Flag(..),
Value(..),
FromString(..)
) where
import Data.Proxy (Proxy(..))
import GHC.TypeLits (Symbol, KnownSymbol, symbolVal)
import Text.Read (readMaybe)
import Commander.Commands (ToParam(..), ParamFlags(..), ParamHelp(..))
data Flag (flags :: [Symbol]) (help :: Symbol) a = Flag a
instance FromString a => ToParam (Flag flags help (Maybe a)) where
toParam (Just str) = fmap (Flag . Just) (fromString str)
toParam Nothing = Right (Flag Nothing)
instance ToParam (Flag flags help Bool) where
toParam (Just "") = Right (Flag True)
toParam (Just _) = Left "boolean string does not expect to have a value"
toParam Nothing = Right (Flag False)
instance FromString a => ToParam (Flag flags help a) where
toParam (Just str) = fmap Flag (fromString str)
toParam Nothing = Left "flag expected but not found"
instance KnownSymbols flags => ParamFlags (Flag flags help a) where
paramFlags _ = Just $ symbolVals (Proxy :: Proxy flags)
instance KnownSymbol help => ParamHelp (Flag flags help a) where
paramHelp _ = symbolVal (Proxy :: Proxy help)
data Value (help :: Symbol) a = Value a
instance FromString a => ToParam (Value help a) where
toParam (Just str) = fmap Value (fromString str)
toParam Nothing = Left "value expected but none found"
instance ParamFlags (Value help a) where
paramFlags _ = Nothing
instance KnownSymbol help => ParamHelp (Value help a) where
paramHelp _ = symbolVal (Proxy :: Proxy help)
class FromString a where
fromString :: String -> Either String a
instance FromString String where
fromString = Right
instance Read a => FromString a where
fromString str = case readMaybe str of
Nothing -> Left "string could not be cast to required type"
Just a -> Right a
class KnownSymbols (s :: [Symbol]) where
symbolVals :: proxy s -> [String]
instance (KnownSymbol s, KnownSymbols ss) => KnownSymbols (s ': ss) where
symbolVals _ = symbolVal (Proxy :: Proxy s) : symbolVals (Proxy :: Proxy ss)
instance KnownSymbols '[] where
symbolVals _ = []