{- | Module : System.Console.HsOptions.Types Description : Data types and Types for HsOptions Copyright : (c) Jose Raymundo Cruz (jose.r.cruz01@gmail.com) License : Apache-2.0 Maintainer : Jose Raymundo Cruz (jose.r.cruz01@gmail.com) Stability : stable Portability : portable Modules that contains all types and data types created in the library. -} module System.Console.HsOptions.Types where import qualified Data.Map as Map -- | Data type that represents a defined flag. -- It contains: -- -- * the name of the flag -- * help text for the flag -- * list of configurations for the flags such as type, default values, etc. data Flag a = Flag String String [FlagConf a] -- | Data type for a flag error. It will contain the error message and -- what kind of error occurred: -- -- * FatalError: an error that the system can't recover from -- * NonFatalError: an error that does not stop the process data FlagError = FlagNonFatalError String | FlagFatalError String -- | Type that represents a collection of all defined flags. -- -- It has three components: -- -- * A flag map: The key is the flag name and the value is the flag data -- * An alias map: A map that connects any flag alias with it's unique flag -- name. This is used to convert each flag alias to it's flag name when -- parsing. -- * A list of global validation rules type FlagData = (FlagDataMap, FlagAliasMap, [GlobalRule]) -- | Type that holds a collection of all flags. -- -- It's a map from flag name to flag data. The flag data holds all defined -- configuration for each flag such as flag type, parser, default, etc. type FlagDataMap = Map.Map String (String, [FlagDataConf]) -- | Type that holds a map from flag alias to flag name. -- -- It is used to identify the corresponding flag given a flag alias. For -- example if the user_id flag has two alias, @u@ and @uid@, this map will -- have these entries: { @uid@ => @user_id@, @u@ => @user_id@ }. type FlagAliasMap = (Map.Map String String) -- | Type that represents the final result of the parse process. -- -- It maps a flag name to it's value. This value is of type 'FlagArgument', -- which means that it can be empty or not. -- -- This type is used by the user to get each flag value in the main method by -- using the 'get' method and passing a flag variable. type FlagResults = (Map.Map String FlagArgument) -- | Data type that represents an input flag argument. -- -- It's type will vary depending on the user input. For example if the user -- calls the program that expects the @user_id@ flag: -- -- >>> ./runhaskell Program.hs -- FlagArgument = FlagMissing "user_id" -- -- >>> ./runhaskell Program.hs --user_id -- FlagArgument = FlagValueMissing "user_id"' -- -- >>> ./runhaskell Program.hs --user_id 8 -- FlagArgument = FlagValue "user_id" "8" -- data FlagArgument = FlagMissing String -- ^ argument not provided | FlagValueMissing String -- ^ argument provided but -- not it's value | FlagValue String String -- ^ argument with value -- provided -- | Type that is the list of remaining positional arguments after the parse -- process is completed. For example: -- -- > ./runhaskell Program.hs --user_id 8 one two three -- -- 'ArgsResults' will contain the list [\"one\", \"two\", \"three\"] type ArgsResults = [String] -- | Type that holds the 'FlagResults' and 'ArgsResults' together. type ParseResults = (FlagResults, ArgsResults) -- | Type of the return value of the 'process' function and it's sub-functions. type ProcessResults = (FlagResults, ArgsResults) -- | Type that represents a pipeline validation/processing function. -- -- It takes a previous state as a parameter and does a set of modifications -- to this state. -- -- It returns a list of errors (if any error occurred) and -- a modified state that will be passed in to the next function in the -- pipeline. type PipelineFunction = (FlagData, FlagResults) -> ([FlagError], FlagResults) -- | Type that represents a global validation rule for a 'FlagResults'. -- -- It is used to create global validation after the flags are processed. If -- the result is a 'Nothing' then the rule passed. Otherwise if a -- @'Just' err'@ is returned then the ruled failed with the message \"@err@\". type GlobalRule = FlagResults -> Maybe String -- | Type that represents the result of the 'tokenize' function and it's -- sub-functions. -- -- It returns either a list of errors or a valid list of tokens. type TokenizeResult = Either [FlagError] [Token] -- | Type that specifies whether a given validation was successful or not. -- -- If it was not successful it contains a 'FlagError' that explains what -- failed. data ValidationResult = ValidationError FlagError | ValidationSuccess -- | Data type that represent a flag configuration. -- -- It is used when a flag is created to set the type of the flag, how it is -- parsed, if the flag is required or optional, etc. data FlagConf a = -- | Function that parses the input value of the flag to it's -- corresponding type, see 'charParser' for an example of this -- type of function. -- -- The flag input text is of type 'FlagArgument', so you can determine -- how to map the value if it's missing or it's value is missing or if -- it's value was provided. -- -- The function returns a 'Maybe a' type, -- @'Nothing'@ if the string value cannot be parsed from the input text and -- @'Just'@ value if it can be parsed. FlagConf_Parser (FlagArgument -> Maybe a) -- | Function that sets a dependent default value to the flag. -- -- If the flag was not provided by the user this will be the default -- value for the flag if the default value getter function returns -- `Just`. | FlagConf_DefaultIf (FlagResults -> Maybe a) -- | Function that given a 'FlagResults' constraints the flag to be -- either required or not required. -- -- If this function returns true then the flag will be required, and if -- not present a @flag is required@ message will be displayed to the user. -- -- If this function returns false then the flag presence will be ignored. | FlagConf_RequiredIf (FlagResults -> Bool) -- | Default value for the flag when the flag was provided by the user -- but not the flag value (@i.e. runhaskell Program.hs --user_id@). -- -- In this example @user_id@ will take the default value configured with -- this flag configuration since it's value is 'FlagValueMissing' | FlagConf_EmptyValueIs a -- | Alias for the flags. Allows the user to specify multiple names for -- the same flag, such as short name or synonyms. | FlagConf_Alias [String] -- | Default operation for flag when no operation is specified. -- -- >>> runhaskell Program.hs --user_name += batman -- Operation was specified: Operation = "Append value" -- -- >>> runhaskell Program.hs --user_name batman -- Operation not specified: Operation = 'FlagConf_DefaultOperation' | FlagConf_DefaultOperation OperationToken -- | Data type that represents a generic flag type configuration. -- -- It is mapped from the 'FlagConf' of each flag so that it can be bundled -- together with all other flag's data. It is used at the validation/parsing -- phase of the 'process' method to verify that the input flag value is -- valid for each flag (i.e. if a required flag was not provided by the user -- but this flag has a default value then an error does not occur). -- -- It has a direct mapping of each 'FlagData' to a non-generic version. data FlagDataConf = -- | Determines if a flag value is valid for a given flag. -- -- Corresponds to 'FlagConf_Parser' and returns 'True' if the result value -- of the 'FlagConf_Parser' is 'Just', returns 'False' otherwise FlagDataConf_Validator (FlagArgument -> Bool) -- | Determines if a flag has a dependent default value configured. -- -- Corresponds just to the predicate part of 'FlagConf_DefaultIf'. | FlagDataConf_HasDefault (FlagResults -> Bool) -- | Exactly the same as 'FlagConf_RequiredIf' | FlagDataConf_RequiredIf (FlagResults -> Bool) -- | Determines if a flag has a @empty value@ configured. -- -- It is mapped from an 'FlagConf_EmptyValueIs'. | FlagDataConf_HasEmptyValue -- | Exactly the same as 'FlagConf_Alias' | FlagDataConf_Alias [String] -- | Exactly the same as 'FlagConf_DefaultOperation' | FlagDataConf_DefaultOperation OperationToken -- | Data types for the flag operations data OperationToken = -- Assign operation for a flag (=). OperationTokenAssign -- Append operation for a flag (+=). | OperationTokenAppend -- Append' operation for a flag (+=!). | OperationTokenAppend' -- Prepend' operation for a flag (=+). | OperationTokenPrepend -- Prepend' operation for a flag (=+!). | OperationTokenPrepend' deriving (Eq) -- | Data type that represents the value for a flag when parsed from the -- input stream. data FlagValueToken = -- Type taken when the flag value was not provided. FlagValueTokenEmpty -- Type taken when the flag value was provided. | FlagValueToken String -- | Data type that represents a flag stream using tokens. data Token = -- | Token for a flag. Contains name, operation and value. FlagToken String OperationToken FlagValueToken -- | Token for a positional argument. Contains the value of the argument. | ArgToken String -- | Type that contains a map from flag name to default flag operation. type DefaultOp = Map.Map String OperationToken -- | Making 'FlagError' an instance of 'Show' instance Show FlagError where -- | To show a 'FlagFatalError' we just return the error message show (FlagFatalError err) = err -- | To show a 'FlagNonFatalError' we just return the error message show (FlagNonFatalError err) = err {-# ANN module "HLint: ignore Use camelCase" #-}