ndmitchell / cmdargs

Haskell library for command line argument processing
Other
91 stars 12 forks source link

Inconsistency in handling boolean arguments #60

Open ozgurakgun opened 4 years ago

ozgurakgun commented 4 years ago

It seems both --flag=value and --flag value style works for all argument types except booleans. Here is a small example to reproduce.

It could probably be made smaller by relying on implicits, but I am afraid of leaving things implicit, so everything is explicit. :)

{-# LANGUAGE DeriveDataTypeable #-}

module Test where

import Data.Data ( Data, Typeable )

import System.Console.CmdArgs

data Test
    = Foo
        { flagS :: String
        , flagI :: Int
        , flagB :: Bool
        }
    deriving (Eq, Ord, Show, Data, Typeable)

ui :: Test
ui = modes
    [ Foo
        { flagS
            = "abc"
            &= typ "STR"
            &= name "flag-s"
            &= name "s"
            &= explicit
            &= help "flag s"
        , flagI
            = 0
            &= typ "INT"
            &= name "flag-i"
            &= name "i"
            &= explicit
            &= help "flag i"
        , flagB
            = True
            &= typ "BOOL"
            &= name "flag-b"
            &= name "b"
            &= explicit
            &= help "flag b"
        }   &= name "foo"
            &= explicit
            &= help "do some foo"
    ]       &= program "test"
            &= helpArg [explicit, name "help"]
            &= versionArg [explicit, name "version"]
            &= summary "This is a test program"
            &= help "This is a test program"

main :: IO ()
main = do
    cli <- cmdArgs ui
    print cli

test.sh

$ cat test.sh

stack runhaskell Test.hs -- -s X
stack runhaskell Test.hs -- -s=X
stack runhaskell Test.hs -- --flag-s X
stack runhaskell Test.hs -- --flag-s=X

stack runhaskell Test.hs -- -i 42
stack runhaskell Test.hs -- -i=42
stack runhaskell Test.hs -- --flag-i 42
stack runhaskell Test.hs -- --flag-i=42

stack runhaskell Test.hs -- -b off
stack runhaskell Test.hs -- -b=off
stack runhaskell Test.hs -- --flag-b off
stack runhaskell Test.hs -- --flag-b=off

$ bash test.sh
Foo {flagS = "X", flagI = 0, flagB = True}
Foo {flagS = "X", flagI = 0, flagB = True}
Foo {flagS = "X", flagI = 0, flagB = True}
Foo {flagS = "X", flagI = 0, flagB = True}
Foo {flagS = "abc", flagI = 42, flagB = True}
Foo {flagS = "abc", flagI = 42, flagB = True}
Foo {flagS = "abc", flagI = 42, flagB = True}
Foo {flagS = "abc", flagI = 42, flagB = True}
Unhandled argument, none expected: off
Foo {flagS = "abc", flagI = 0, flagB = False}
Unhandled argument, none expected: off
Foo {flagS = "abc", flagI = 0, flagB = False}
ndmitchell commented 4 years ago

That inconsistency is actually deliberate, see https://hackage.haskell.org/package/cmdargs-0.10.20/docs/System-Console-CmdArgs-Explicit.html#v:FlagOptRare. Boolean arguments go into the rare category since normally you want to leave them unadorned, and have --flag off be two separate arguments.