-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Create command line interfaces with ease -- -- Create command line interfaces with ease @package getopt-generics @version 0.11 module WithCli -- | withCli converts an IO operation into a program with a proper -- CLI. Retrieves command line arguments through withArgs. -- main (the given IO operation) can have arbitrarily many -- parameters provided all parameters have instances for -- HasArguments. -- -- May throw the following exceptions: -- -- -- -- Example: -- --
--   import WithCli
--   
--   main :: IO ()
--   main = withCli run
--   
--   run :: String -> Int -> Bool -> IO ()
--   run s i b = print (s, i, b)
--   
-- -- Using the above program in a shell: -- --
--   $ program foo 42 true
--   ("foo",42,True)
--   $ program --help
--   program [OPTIONS] STRING INTEGER BOOL
--     -h  --help  show help and exit
--   $ program foo 42 bar
--   cannot parse as BOOL: bar
--   # exit-code 1
--   $ program
--   missing argument of type STRING
--   missing argument of type INTEGER
--   missing argument of type BOOL
--   # exit-code 1
--   $ program foo 42 yes bar
--   unknown argument: bar
--   # exit-code 1
--   
withCli :: WithCli main => main -> IO () -- | Everything that can be used as a main function with -- withCli needs to have an instance of WithCli. You -- shouldn't need to implement your own instances. class WithCli main -- | Everything that can be used as an argument to your main -- function (see withCli) needs to have a HasArguments -- instance. -- -- HasArguments also allows to conjure up instances for record -- types to create more complex command line interfaces. Here's an -- example: -- --
--   {-# LANGUAGE DeriveGeneric #-}
--   
--   import qualified GHC.Generics
--   import           System.Console.GetOpt.Generics
--   
--   data Options
--     = Options {
--       port :: Int,
--       daemonize :: Bool,
--       config :: Maybe FilePath
--     }
--     deriving (Show, GHC.Generics.Generic)
--   
--   instance Generic Options
--   instance HasDatatypeInfo Options
--   instance HasArguments Options
--   
--   main :: IO ()
--   main = withCli run
--   
--   run :: Options -> IO ()
--   run = print
--   
-- -- In a shell this program behaves like this: -- --
--   $ program --port 8080 --config some/path
--   Options {port = 8080, daemonize = False, config = Just "some/path"}
--   $ program  --port 8080 --daemonize
--   Options {port = 8080, daemonize = True, config = Nothing}
--   $ program --port foo
--   cannot parse as INTEGER: foo
--   # exit-code 1
--   $ program
--   missing option: --port=INTEGER
--   # exit-code 1
--   $ program --help
--   program [OPTIONS]
--         --port=INTEGER
--         --daemonize
--         --config=STRING (optional)
--     -h  --help                      show help and exit
--   
class HasArguments a where argumentsParser = const . genericParser argumentsParser :: HasArguments a => Modifiers -> Maybe String -> Result (Parser Unnormalized a) -- | Useful for implementing your own instances of HasArguments on -- top of a custom Argument instance. atomicArgumentsParser :: Argument a => Modifiers -> Maybe String -> Result (Parser Unnormalized a) -- | Argument is a typeclass for things that can be parsed as atomic -- values from single command line arguments, e.g. strings (and -- filenames) and numbers. -- -- Occasionally you might want to declare your own instance for -- additional type safety and for providing a more informative command -- argument type. Here's an example: -- --
--   {-# LANGUAGE DeriveDataTypeable #-}
--   
--   import WithCli
--   
--   data File = File FilePath
--     deriving (Show, Typeable)
--   
--   instance Argument File where
--     argumentType Proxy = "custom-file-type"
--     parseArgument f = Just (File f)
--   
--   instance HasArguments File where
--     argumentsParser = atomicArgumentsParser
--   
--   main :: IO ()
--   main = withCli run
--   
--   run :: File -> IO ()
--   run = print
--   
-- -- And this is how the above program behaves: -- --
--   $ program --help
--   program [OPTIONS] custom-file-type
--     -h  --help  show help and exit
--   $ program some/file
--   File "some/file"
--   
class Argument a argumentType :: Argument a => Proxy a -> String parseArgument :: Argument a => String -> Maybe a -- | This is a variant of withCli that allows to tweak the generated -- command line interface by providing a list of Modifiers. withCliModified :: WithCli main => [Modifier] -> main -> IO () -- | Modifiers can be used to customize the command line parser. data Modifier -- | AddShortOption fieldName c adds the Char c as -- a short option for the field addressed by fieldName. AddShortOption :: String -> Char -> Modifier -- | RenameOption fieldName customName renames the option -- generated through the fieldName by customName. RenameOption :: String -> String -> Modifier -- | RenameOptions f renames all options with the given functions. -- In case the function returns Nothing the original field name -- is used. -- -- Can be used together with stripPrefix. RenameOptions :: (String -> Maybe String) -> Modifier -- | UseForPositionalArguments fieldName argumentType fills the -- field addressed by fieldName with the positional arguments -- (i.e. arguments that don't correspond to a flag). The field has to -- have type [String]. -- -- argumentType is used as the type of the positional arguments -- in the help output. UseForPositionalArguments :: String -> String -> Modifier -- | AddOptionHelp fieldName helpText adds a help text for the -- option fieldName. AddOptionHelp :: String -> String -> Modifier -- | AddVersionFlag version adds a --version flag. AddVersionFlag :: String -> Modifier -- | The class of representable datatypes. -- -- The SOP approach to generic programming is based on viewing datatypes -- as a representation (Rep) built from the sum of products of its -- components. The components of are datatype are specified using the -- Code type family. -- -- The isomorphism between the original Haskell datatype and its -- representation is witnessed by the methods of this class, from -- and to. So for instances of this class, the following laws -- should (in general) hold: -- --
--   to . from === id :: a -> a
--   from . to === id :: Rep a -> Rep a
--   
-- -- You typically don't define instances of this class by hand, but rather -- derive the class instance automatically. -- -- Option 1: Derive via the built-in GHC-generics. For this, you -- need to use the DeriveGeneric extension to first derive an -- instance of the Generic class from module GHC.Generics. -- With this, you can then give an empty instance for Generic, and -- the default definitions will just work. The pattern looks as follows: -- --
--   import qualified GHC.Generics as GHC
--   import Generics.SOP
--   
--   ...
--   
--   data T = ... deriving (GHC.Generic, ...)
--   
--   instance Generic T -- empty
--   instance HasDatatypeInfo T -- empty, if you want/need metadata
--   
-- -- Option 2: Derive via Template Haskell. For this, you need to -- enable the TemplateHaskell extension. You can then use -- deriveGeneric from module Generics.SOP.TH to have the -- instance generated for you. The pattern looks as follows: -- --
--   import Generics.SOP
--   import Generics.SOP.TH
--   
--   ...
--   
--   data T = ...
--   
--   deriveGeneric ''T -- derives HasDatatypeInfo as well
--   
-- -- Tradeoffs: Whether to use Option 1 or 2 is mainly a matter of -- personal taste. The version based on Template Haskell probably has -- less run-time overhead. -- -- Non-standard instances: It is possible to give Generic -- instances manually that deviate from the standard scheme, as long as -- at least -- --
--   to . from === id :: a -> a
--   
-- -- still holds. class (SingI [[*]] (Code a), All [*] (SingI [*]) (Code a)) => Generic a where type family Code a :: [[*]] -- | A class of datatypes that have associated metadata. -- -- It is possible to use the sum-of-products approach to generic -- programming without metadata. If you need metadata in a function, an -- additional constraint on this class is in order. -- -- You typically don't define instances of this class by hand, but rather -- derive the class instance automatically. See the documentation of -- Generic for the options. class HasDatatypeInfo a -- | The code of a datatype. -- -- This is a list of lists of its components. The outer list contains one -- element per constructor. The inner list contains one element per -- constructor argument (field). -- -- Example: The datatype -- --
--   data Tree = Leaf Int | Node Tree Tree
--   
-- -- is supposed to have the following code: -- --
--   type instance Code (Tree a) =
--     '[ '[ Int ]
--      , '[ Tree, Tree ]
--      ]
--   
-- | Require a constraint for every element of a list of lists. -- -- If you have a datatype that is indexed over a type-level list of -- lists, then you can use All2 to indicate that all elements of -- the innert lists must satisfy a given constraint. -- -- Example: The constraint -- --
--   All2 Eq '[ '[ Int ], '[ Bool, Char ] ]
--   
-- -- is equivalent to the constraint -- --
--   (Eq Int, Eq Bool, Eq Char)
--   
-- -- Example: A type signature such as -- --
--   f :: All2 Eq xss => SOP I xs -> ...
--   
-- -- means that f can assume that all elements of the sum of -- product satisfy Eq. -- | The class Typeable allows a concrete representation of a type -- to be calculated. class Typeable (a :: k) -- | A concrete, poly-kinded proxy type data Proxy (t :: k) :: k -> * Proxy :: Proxy instance WithCli.WithCli (GHC.Types.IO ()) instance (WithCli.HasArguments.HasArguments a, WithCli.WithCli rest) => WithCli.WithCli (a -> rest) module System.Console.GetOpt.Generics -- | withCli converts an IO operation into a program with a proper -- CLI. Retrieves command line arguments through withArgs. -- main (the given IO operation) can have arbitrarily many -- parameters provided all parameters have instances for -- HasArguments. -- -- May throw the following exceptions: -- -- -- -- Example: -- --
--   import WithCli
--   
--   main :: IO ()
--   main = withCli run
--   
--   run :: String -> Int -> Bool -> IO ()
--   run s i b = print (s, i, b)
--   
-- -- Using the above program in a shell: -- --
--   $ program foo 42 true
--   ("foo",42,True)
--   $ program --help
--   program [OPTIONS] STRING INTEGER BOOL
--     -h  --help  show help and exit
--   $ program foo 42 bar
--   cannot parse as BOOL: bar
--   # exit-code 1
--   $ program
--   missing argument of type STRING
--   missing argument of type INTEGER
--   missing argument of type BOOL
--   # exit-code 1
--   $ program foo 42 yes bar
--   unknown argument: bar
--   # exit-code 1
--   
withCli :: WithCli main => main -> IO () -- | Everything that can be used as a main function with -- withCli needs to have an instance of WithCli. You -- shouldn't need to implement your own instances. class WithCli main -- | Everything that can be used as an argument to your main -- function (see withCli) needs to have a HasArguments -- instance. -- -- HasArguments also allows to conjure up instances for record -- types to create more complex command line interfaces. Here's an -- example: -- --
--   {-# LANGUAGE DeriveGeneric #-}
--   
--   import qualified GHC.Generics
--   import           System.Console.GetOpt.Generics
--   
--   data Options
--     = Options {
--       port :: Int,
--       daemonize :: Bool,
--       config :: Maybe FilePath
--     }
--     deriving (Show, GHC.Generics.Generic)
--   
--   instance Generic Options
--   instance HasDatatypeInfo Options
--   instance HasArguments Options
--   
--   main :: IO ()
--   main = withCli run
--   
--   run :: Options -> IO ()
--   run = print
--   
-- -- In a shell this program behaves like this: -- --
--   $ program --port 8080 --config some/path
--   Options {port = 8080, daemonize = False, config = Just "some/path"}
--   $ program  --port 8080 --daemonize
--   Options {port = 8080, daemonize = True, config = Nothing}
--   $ program --port foo
--   cannot parse as INTEGER: foo
--   # exit-code 1
--   $ program
--   missing option: --port=INTEGER
--   # exit-code 1
--   $ program --help
--   program [OPTIONS]
--         --port=INTEGER
--         --daemonize
--         --config=STRING (optional)
--     -h  --help                      show help and exit
--   
class HasArguments a where argumentsParser = const . genericParser -- | Argument is a typeclass for things that can be parsed as atomic -- values from single command line arguments, e.g. strings (and -- filenames) and numbers. -- -- Occasionally you might want to declare your own instance for -- additional type safety and for providing a more informative command -- argument type. Here's an example: -- --
--   {-# LANGUAGE DeriveDataTypeable #-}
--   
--   import WithCli
--   
--   data File = File FilePath
--     deriving (Show, Typeable)
--   
--   instance Argument File where
--     argumentType Proxy = "custom-file-type"
--     parseArgument f = Just (File f)
--   
--   instance HasArguments File where
--     argumentsParser = atomicArgumentsParser
--   
--   main :: IO ()
--   main = withCli run
--   
--   run :: File -> IO ()
--   run = print
--   
-- -- And this is how the above program behaves: -- --
--   $ program --help
--   program [OPTIONS] custom-file-type
--     -h  --help  show help and exit
--   $ program some/file
--   File "some/file"
--   
class Argument a argumentType :: Argument a => Proxy a -> String parseArgument :: Argument a => String -> Maybe a -- | This is a variant of withCli that allows to tweak the generated -- command line interface by providing a list of Modifiers. withCliModified :: WithCli main => [Modifier] -> main -> IO () -- | Modifiers can be used to customize the command line parser. data Modifier -- | AddShortOption fieldName c adds the Char c as -- a short option for the field addressed by fieldName. AddShortOption :: String -> Char -> Modifier -- | RenameOption fieldName customName renames the option -- generated through the fieldName by customName. RenameOption :: String -> String -> Modifier -- | RenameOptions f renames all options with the given functions. -- In case the function returns Nothing the original field name -- is used. -- -- Can be used together with stripPrefix. RenameOptions :: (String -> Maybe String) -> Modifier -- | UseForPositionalArguments fieldName argumentType fills the -- field addressed by fieldName with the positional arguments -- (i.e. arguments that don't correspond to a flag). The field has to -- have type [String]. -- -- argumentType is used as the type of the positional arguments -- in the help output. UseForPositionalArguments :: String -> String -> Modifier -- | AddOptionHelp fieldName helpText adds a help text for the -- option fieldName. AddOptionHelp :: String -> String -> Modifier -- | AddVersionFlag version adds a --version flag. AddVersionFlag :: String -> Modifier -- | Parses command line arguments (gotten from withArgs) and -- returns the parsed value. This function should be enough for simple -- use-cases. -- -- Throws the same exceptions as withCli. -- -- Here's an example: -- --
--   {-# LANGUAGE DeriveGeneric #-}
--   
--   module RecordType where
--   
--   import qualified GHC.Generics
--   import           System.Console.GetOpt.Generics
--   
--   -- All you have to do is to define a type and derive some instances:
--   
--   data Options
--     = Options {
--       port :: Int,
--       daemonize :: Bool,
--       config :: Maybe FilePath
--     }
--     deriving (Show, GHC.Generics.Generic)
--   
--   instance Generic Options
--   instance HasDatatypeInfo Options
--   
--   -- Then you can use `getArguments` to create a command-line argument parser:
--   
--   main :: IO ()
--   main = do
--     options <- getArguments
--     print (options :: Options)
--   
-- -- And this is how the above program behaves: -- --
--   $ program --port 8080 --config some/path
--   Options {port = 8080, daemonize = False, config = Just "some/path"}
--   $ program  --port 8080 --daemonize
--   Options {port = 8080, daemonize = True, config = Nothing}
--   $ program --port foo
--   cannot parse as INTEGER: foo
--   # exit-code 1
--   $ program
--   missing option: --port=INTEGER
--   # exit-code 1
--   $ program --help
--   program [OPTIONS]
--         --port=INTEGER
--         --daemonize
--         --config=STRING (optional)
--     -h  --help                      show help and exit
--   
getArguments :: (Generic a, HasDatatypeInfo a, All2 HasArguments (Code a)) => IO a -- | Like getArguments but allows you to pass in Modifiers. modifiedGetArguments :: (Generic a, HasDatatypeInfo a, All2 HasArguments (Code a)) => [Modifier] -> IO a -- | Pure variant of modifiedGetArguments. -- -- Does not throw any exceptions. parseArguments :: (Generic a, HasDatatypeInfo a, All2 HasArguments (Code a)) => String -> [Modifier] -> [String] -> Result a -- | Type to wrap results from the pure parsing functions. data Result a -- | The CLI was used correctly and a value of type a was -- successfully constructed. Success :: a -> Result a -- | The CLI was used incorrectly. The Result contains a list of -- error messages. -- -- It can also happen that the data type you're trying to use isn't -- supported. See the README for details. Errors :: [String] -> Result a -- | The CLI was used with --help. The Result contains the -- help message. OutputAndExit :: String -> Result a -- | The class of representable datatypes. -- -- The SOP approach to generic programming is based on viewing datatypes -- as a representation (Rep) built from the sum of products of its -- components. The components of are datatype are specified using the -- Code type family. -- -- The isomorphism between the original Haskell datatype and its -- representation is witnessed by the methods of this class, from -- and to. So for instances of this class, the following laws -- should (in general) hold: -- --
--   to . from === id :: a -> a
--   from . to === id :: Rep a -> Rep a
--   
-- -- You typically don't define instances of this class by hand, but rather -- derive the class instance automatically. -- -- Option 1: Derive via the built-in GHC-generics. For this, you -- need to use the DeriveGeneric extension to first derive an -- instance of the Generic class from module GHC.Generics. -- With this, you can then give an empty instance for Generic, and -- the default definitions will just work. The pattern looks as follows: -- --
--   import qualified GHC.Generics as GHC
--   import Generics.SOP
--   
--   ...
--   
--   data T = ... deriving (GHC.Generic, ...)
--   
--   instance Generic T -- empty
--   instance HasDatatypeInfo T -- empty, if you want/need metadata
--   
-- -- Option 2: Derive via Template Haskell. For this, you need to -- enable the TemplateHaskell extension. You can then use -- deriveGeneric from module Generics.SOP.TH to have the -- instance generated for you. The pattern looks as follows: -- --
--   import Generics.SOP
--   import Generics.SOP.TH
--   
--   ...
--   
--   data T = ...
--   
--   deriveGeneric ''T -- derives HasDatatypeInfo as well
--   
-- -- Tradeoffs: Whether to use Option 1 or 2 is mainly a matter of -- personal taste. The version based on Template Haskell probably has -- less run-time overhead. -- -- Non-standard instances: It is possible to give Generic -- instances manually that deviate from the standard scheme, as long as -- at least -- --
--   to . from === id :: a -> a
--   
-- -- still holds. class (SingI [[*]] (Code a), All [*] (SingI [*]) (Code a)) => Generic a where type family Code a :: [[*]] -- | A class of datatypes that have associated metadata. -- -- It is possible to use the sum-of-products approach to generic -- programming without metadata. If you need metadata in a function, an -- additional constraint on this class is in order. -- -- You typically don't define instances of this class by hand, but rather -- derive the class instance automatically. See the documentation of -- Generic for the options. class HasDatatypeInfo a -- | The code of a datatype. -- -- This is a list of lists of its components. The outer list contains one -- element per constructor. The inner list contains one element per -- constructor argument (field). -- -- Example: The datatype -- --
--   data Tree = Leaf Int | Node Tree Tree
--   
-- -- is supposed to have the following code: -- --
--   type instance Code (Tree a) =
--     '[ '[ Int ]
--      , '[ Tree, Tree ]
--      ]
--   
-- | Require a constraint for every element of a list of lists. -- -- If you have a datatype that is indexed over a type-level list of -- lists, then you can use All2 to indicate that all elements of -- the innert lists must satisfy a given constraint. -- -- Example: The constraint -- --
--   All2 Eq '[ '[ Int ], '[ Bool, Char ] ]
--   
-- -- is equivalent to the constraint -- --
--   (Eq Int, Eq Bool, Eq Char)
--   
-- -- Example: A type signature such as -- --
--   f :: All2 Eq xss => SOP I xs -> ...
--   
-- -- means that f can assume that all elements of the sum of -- product satisfy Eq.