optparse-declarative
optparse-declarative
is a declarative and easy to use command-line option parser.
Install
$ cabal install optparse-declarative
Usage
Writing a simple command
First, you need to enable DataKinds
extension and import Options.Declarative
module.
{-# 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:
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_
.
main :: IO ()
main = run_ greet
You can execute this program like this:
$ 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:
{-# 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:
$ ./subcmd --help
Usage: subcmd [OPTION...] <COMMAND> [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.