# getopt-generics
## Status
This library is experimental.
## Usage
`getopt-generics` tries to make it very simple to create executables that parse
command line options. All you have to do is to define a type and derive some
instances:
~~~ {.haskell}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
module Readme where
import Data.Typeable
import GHC.Generics
import System.Console.GetOpt.Generics
import System.Environment
data Options
= Options {
port :: Int,
daemonize :: Bool,
config :: Maybe FilePath
}
deriving (Show, GHC.Generics.Generic)
instance System.Console.GetOpt.Generics.Generic Options
instance HasDatatypeInfo Options
~~~
Then you can use `getArguments` to create a command-line argument parser:
~~~ {.haskell}
main :: IO ()
main = do
options <- getArguments
print (options :: Options)
~~~
This program has
- a non-optional `--port` flag with an integer argument,
- a boolean flag `--daemonize`,
- an optional flag `--config` expecting a file argument and
- a generic `--help` option.
Here's in example of the program above in bash:
``` bash
$ 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
not an integer: foo
$ program
missing option: --port=int
$ program --help
program
--port=integer
--daemonize
--config=string (optional)
```
## Constraints
There are some constraints that the defined datatype has to fulfill:
* It has to have only one constructor,
* that constructor has to have field selectors (i.e. use record syntax) and
* all fields have to be of a type that has an instance for `Option`.
(Types declared with `newtype` are allowed with the same constraints.)
## Using Custom Field Types
It is possible to use custom field types by providing an instance for `Option`.
Here's an example:
~~~ {.haskell}
data File = File FilePath
deriving (Show, Typeable)
instance Option File where
argumentType Proxy = "file"
parseArgument f = Just (File f)
data FileOptions
= FileOptions {
file :: File
}
deriving (Show, GHC.Generics.Generic)
instance System.Console.GetOpt.Generics.Generic FileOptions
instance HasDatatypeInfo FileOptions
-- Returns: FileOptions {file = File "some/file"}
getFileOptions :: IO FileOptions
getFileOptions = withArgs (words "--file some/file") getArguments
~~~