ndmitchell / cmdargs

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

Incorrect handling of subcommands with the same argument #67

Open ad-si opened 2 years ago

ad-si commented 2 years ago

Given following program:

data Cli
  = Serve { filePath :: FilePath }
  | Inspect { filePath :: FilePath }
  deriving (Show, Data, Typeable)

cliServe :: Cli
cliServe = Serve { filePath = def &= typ "Path to file" &= args }

cliInspect :: Cli
cliInspect = Inspect { filePath = def &= typ "Path to file" &= args }

Executing it leads to this help text:

 $ stack run -- --help
The cli program

cli [COMMAND] ... [OPTIONS]

Common flags:
  -? --help           Display help message
  -V --version        Print version information

cli serve [OPTIONS] [Path to file]

cli inspect [OPTIONS]

  -f --filepath=ITEM

For serve it gets parsed as a normal argument and for inspect as a flag.

When I change the typ of one of them to something else, it works. 😳

This also happens when I remove both typ expressions, since the name then seems to default to ITEM.

This can't be right, can it?

kbmackenzie commented 7 months ago

Having the exact same issue with version 0.10.22 of cmdargs.

I also get a similarly odd issue when using the enum function from System.Console.CmdArgs.Implicit with the same arguments in two subcommands.

The following snippet:

data EnumTest =
      CaseA { state :: State }
    | CaseB { state :: State }
    deriving (Show, Data, Typeable)
data State = On | Off deriving (Show, Data, Typeable)

caseA :: EnumTest
caseA = CaseA { state = enum [ On &= help "Is on" , Off &= help "Is off" ] }
    &= help "Case A"

caseB :: EnumTest
caseB = CaseB { state = enum [ On &= help "Is on" , Off &= help "Is off" ] }
    &= help "Case B"

runTest :: IO EnumTest
runTest = cmdArgsRun $ cmdArgsMode $ modes [caseA, caseB]

Gives this --help text:

The enumtest program

enumtest [COMMAND] ... [OPTIONS]

Common flags:
  -? --help         Display help message
  -V --version      Print version information

enumtest casea [OPTIONS]
  Case A

     --on           Is on
     --off          Is off

enumtest caseb [OPTIONS]
  Case B

  -s --state=STATE

As you can see, the enum values are listed properly as the flags --on and --off in CaseA, but aren't listed at all in CaseB, with just the "state" field being listed instead.

I spent a long time trying to debug this before coming here to see if anyone was having similar issues. Definitely looks like a bug to me.