# optparse-declarative `optparse-declarative` is a declarative and easy to use command-line option parser. # Install ```bash $ cabal install optparse-declarative ``` # Usage ## Writing a simple command First, you need to enable `DataKinds` extension and import `Options.Declarative` module. ```hs {-# LANGUAGE DataKinds #-} import Options.Declarative ``` Then, define the command line option as a **type of the function**. For example, this is a simple greeting program: ```hs greet :: Flag "g" '["greet"] "STRING" "greeting message" (Def "Hello" String) -> Arg "NAME" String -> Cmd "greet" greet msg name = Cmd $ do putStrLn $ get msg ++ ", " ++ get name ++ "!" ``` There are two type of options, `Flag` and `Arg`. `Flag` is named argument and `Arg` is unnamed argument. Last argument of both options is value type. If you need to specify default value, use the modifiers such as `Def`. In above, variable `msg` has a very complex type (`Flag "g" '["greet"] "STRING" "greeting message" (Def "Hello" String)`). In order to get the value of usual type (in this case, that is `String`), you can use `get` function. The whole type of command is `Cmd`. `Cmd ` is basically newtype of `IO ()`, except this contains extra information. When you define the command, there remains only invoking the command. ```hs main :: IO () main = run_ greet ``` You can execute this program like this: ```bash $ ghc simple.hs $ ./simple simple: not enough arguments Try 'simple --help' for more information. $ ./simple --help Usage: simple [OPTION...] NAME Options: -g STRING --greet=STRING greeting message -? --help display this help and exit $ ./simple World Hello, World! $ ./simple --greet=Goodbye World Goodbye, World! ``` ## Writing multiple sum-commands You can write (nested) sub-commands. Just groupe subcommands by `Group`, you got sub-command parser. This is the example: ```hs {-# LANGUAGE DataKinds #-} import Options.Declarative main :: IO () main = run_ $ Group "Test program for library" [ subCmd "greet" greet , subCmd "connect" connect ] greet :: Flag "g" '["greet"] "STRING" "greeting message" (Def "Hello" String) -> Flag "" '["decolate"] "" "decolate message" Bool -> Arg "NAME" String -> Cmd "Greeting command" greet msg deco name = Cmd $ do let f x | get deco = "*** " ++ x ++ " ***" | otherwise = x putStrLn $ f $ get msg ++ ", " ++ get name ++ "!" connect :: Flag "h" '["host"] "HOST" "host name" (Def "localhost" String) -> Flag "p" '["port"] "PORT" "port number" (Def "8080" Int ) -> Cmd "Connect command" connect host port = Cmd $ do let addr = get host ++ ":" ++ show (get port) putStrLn $ "connect to " ++ addr ``` And this is the output: ```bash $ ./subcmd --help Usage: subcmd [OPTION...] [ARGS...] Options: -? --help display this help and exit Commands: greet Greeting command port Server command $ ./subcmd connect --port=1234 connect to localhost:1234 ``` For more examples, please see `example` directory.