# optparse-declarative [![Hackage](https://matrix.hackage.haskell.org/api/v2/packages/optparse-declarative/badge)](http://hackage.haskell.org/package/optparse-declarative) [![GitHub Actions: test](https://github.com/tanakh/optparse-declarative/workflows/test/badge.svg)](https://github.com/tanakh/optparse-declarative/actions?query=workflow%3Atest) [![Join the chat at https://gitter.im/optparse-declarative/community](https://badges.gitter.im/optparse-declarative/community.svg)](https://gitter.im/optparse-declarative/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) `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 "Greeting command" () greet msg name = liftIO $ 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 an instance of `MonadIO` and it has some extra information. After defining a command, you just invoke it by `run_`. ```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 sub-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 = do let f x | get deco = "*** " ++ x ++ " ***" | otherwise = x liftIO $ 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 = do let addr = get host ++ ":" ++ show (get port) liftIO $ 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.