{-# LANGUAGE DeriveDataTypeable #-} module System.Console.Internal where import Control.Exception (Exception) import Data.Map (Map) import Data.Typeable (Typeable) import qualified System.Console.GetOpt as GetOpt type UserCommand = [String] -- | An @Action m@ is an action (in the monad @m@), which may take arguments -- (\"non-options\") and options from the command line. data Action m = Action { run :: [String] -> Settings -> m () , nonOptions :: [String] , options :: [((Identifier,[OptionName]),GetOpt.OptDescr CanonicalSetting)] , ignoringOptions :: [GetOpt.OptDescr CanonicalSetting] } -- | A value of type @Option a@ describes an option, that delivers a value -- to the program of type @a@. data Option a = Option [OptionName] (GetOpt.OptDescr (Identifier,Maybe String)) a (Maybe String -> Either String a) data OptionName = Short Char | Long String deriving (Eq,Ord) instance Show OptionName where show (Short c) = '-' : c : [] show (Long i) = "--" ++ i -- The @Identifier@ of an option should identify it uniquely. newtype Identifier = Id OptionName deriving (Eq,Ord) type Setting = (OptionName,Maybe String) type CanonicalSetting = (Identifier,Maybe String) type Settings = Map Identifier (Maybe String) identify :: [OptionName] -> Identifier identify (n : _) = Id n identify _ = error "System.Console.Internal.identify: option without option names." -- | A @Command m@ is an action (in the monad @m@), together with some -- descriptive information. data Command m = Command { -- | This determines which command is executed. name :: String -- | For usage info. , description :: String -- | The actual action performed by this command. , action :: Action m -- | Prefer shortened subcommands over non-option arguments. , shorten :: Bool } data ConsoleProgramException = UnknownCommand String deriving (Typeable) instance Show ConsoleProgramException where show (UnknownCommand c) = "Error: unused non-option or unrecognised command: " ++ c instance Exception ConsoleProgramException