System.Console.GetOpt mistakenly rejects options as ambiguous.
authorMalcolm.Wallace@cs.york.ac.uk <unknown>
Wed, 12 Mar 2008 11:10:47 +0000 (11:10 +0000)
committerMalcolm.Wallace@cs.york.ac.uk <unknown>
Wed, 12 Mar 2008 11:10:47 +0000 (11:10 +0000)
From "Eelis van der Weegen" <haskell-libs@contacts.eelis.net>.
Testcase:

> import System.Console.GetOpt
>
> type Color = String
>
> optsDesc :: [OptDescr Color]
> optsDesc = [Option "" ["color", "colour"]
>                    (ReqArg id "color") "Foreground color"]
>
> main = do
>   let args = ["--col=blue"]
>   case getOpt RequireOrder optsDesc args of
>     (_, _, err:_) -> putStrLn err
>     _ -> return ()

Output:
  option `--col' is ambiguous; could be one of:
      --color=color, --colour=color  Foreground color
      --color=color, --colour=color  Foreground color

This error is silly, because the two alternatives listed are the same
option.  The problem is caused by incorrect use of a generator in a list
comprehension.

System/Console/GetOpt.hs

index d6e996b..92ebd52 100644 (file)
@@ -62,7 +62,7 @@ module System.Console.GetOpt (
 
 import Prelude -- necessary to get dependencies right
 
-import Data.List ( isPrefixOf )
+import Data.List ( isPrefixOf, find )
 
 -- |What to do with options following non-options
 data ArgOrder a
@@ -193,7 +193,8 @@ getNext a            rest _        = (NonOpt a,rest)
 longOpt :: String -> [String] -> [OptDescr a] -> (OptKind a,[String])
 longOpt ls rs optDescr = long ads arg rs
    where (opt,arg) = break (=='=') ls
-         getWith p = [ o  | o@(Option _ xs _ _) <- optDescr, x <- xs, opt `p` x ]
+         getWith p = [ o | o@(Option _ xs _ _) <- optDescr
+                         , find (p opt) xs /= Nothing ]
          exact     = getWith (==)
          options   = if null exact then getWith isPrefixOf else exact
          ads       = [ ad | Option _ _ ad _ <- options ]