I use cmdargs
to write CLI parsers for my Haskell programs.
Let's assume this program, derived directly from their example:
{-# LANGUAGE DeriveDataTypeable #-}
import System.Console.CmdArgs.Implicit
data Sample = Sample {hello :: String} deriving (Show, Data, Typeable)
sample = Sample{hello = def &= help "World argument" &= opt "world"}
&= summary "Sample v1"
main = print =<< cmdArgs sample
If this program is called cmdtest.hs
, I can execute
$ runghc cmdtest.hs --hello=world
Sample {hello = "world"}
However, if I leave off the equals sign (like in the -o
option in gcc -o foo foobar.c
), cmdargs tries to recognize world
as a positional argument
$ runghc cmdtest.hs --hello world
Unhandled argument, none expected: world
Is there any option / annotation I can set to allow this syntax in cmdargs?
Update: Using the short option exposes the same problem:
$ runghc cmdtest.hs -h world
Unhandled argument, none expected: world
Update 2: The FlagInfo
data
in the cmdargs Explicit
module seems to suggest it is somehow possible, at least if using Explicit
instead of Implicit
Depending on the implementation used to parse command line arguments, the details and flexibility in accepting them may differ. Mentioned earlier short flags concatenation may not work, forcing us to provide all flags separately.
When a parameter is passed to the method, it is called an argument. So, from the example above: fname is a parameter, while Liam, Jenny and Anja are arguments. You can also use a default parameter value, by using the equals sign ( = ). If we call the method without an argument, it uses the default value ("Norway"):
As a rule, the command should not expect flags and value arguments to be in any particular order. Which makes sense – we shouldn’t expect the user to remember the order on top of the kind of arguments the executable accepts. Those two calls are correct and equal:
Sometimes long-style named arguments may accept or even require to pass a value with an equals sign instead of space in-between, like --block-size=K. On the other hand, a single-letter named arguments may accept or require to pass value without space, like this: -w50.
Your problem is that you're using opt
which makes the value of --hello
optional. So --hello world
is taken to mean --hello
without a value, followed by world
as a positional parameter. This is of course a design choice in cmdargs
, but I think it's a reasonable one, and it matches the behaviour of most other programs. Take out the opt
and see if it works the way you want.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With