-- | Run parser, return configured options environment and arguments
parseOptions' :: (Configurable t) =>
                 ParsingConf  -- ^ parsing configuration
              -> [String]     -- ^ raw arguments
              -> IO t
parseOptions' conf rawArgs = do
  let initial = defConf

      usageStr sign = flip usageInfo optdescr . init . unlines $
                        [ "USAGE: " ++ pcProgName conf ++ " " ++ sign
                        , ""
                        , pcHelpExtraInfo conf
                        ]

      showHelp opts = do
        putStrLn $ usageStr (signature initial)
        exitWith ExitSuccess >>= \_ -> return opts

      helpdescr = case pcHelpFlag conf of
                    Just flag -> [ Option [] [flag] (NoArg showHelp) "print this help message and exit." ]
                    Nothing -> []

      parsers = runOptM parseOpts

      optdescr = helpdescr ++ concatMap (\x -> case x of {ParseOpt d -> [d]; _ -> []} ) parsers

      --argparsers = concatMap (\x -> case x of {(Arg p) -> [p]; _ -> []} ) parsers

  let (actions, _args, msgs) = getOpt Permute optdescr rawArgs
      --argActions = parseArgs args argparsers

      groupedByShort = M.fromListWith (++) $ catMaybes $
                       map (\o@(Option (listToMaybe -> s) _ _ _) -> fmap (\x -> ('-':x:[], [o])) s) optdescr
      groupedByLong  = M.fromListWith (++) $ catMaybes $
                       map (\o@(Option _ (listToMaybe -> l) _ _) -> fmap (\x -> ("--"++x, [o])) l) optdescr

      duplicates = M.keys . M.filter (>1) . M.map length $ (M.unionWith (++) groupedByShort groupedByLong)

  unless (null duplicates) $
       error $ "Parsing error. Duplicate flags defined: " ++ intercalate ", " duplicates

  mapM_ (error . flip (++) (usageStr (signature initial))) msgs

  opts <- foldl' (>>=) (return initial) (actions) -- ++ argActions)
  return opts
parseOptions' :: (Configurable t) =>
                 ParsingConf  -- ^ parsing configuration
              -> [String]     -- ^ raw arguments
              -> IO t
parseOptions' conf rawArgs = do
  let initial = defConf

      usageStr sign = flip usageInfo optdescr . init . unlines $
                        [ "USAGE: " ++ pcProgName conf ++ " " ++ sign
                        , ""
                        , pcHelpExtraInfo conf
                        ]

      showHelp opts = do
        putStrLn $ usageStr (signature initial)
        exitWith ExitSuccess >>= \_ -> return opts

      helpdescr = case pcHelpFlag conf of
                    Just flag -> [ Option [] [flag] (NoArg showHelp) "print this help message and exit." ]
                    Nothing -> []

      parsers = runOptM parseOpts

      optdescr = helpdescr ++ concatMap (\x -> case x of {ParseOpt d -> [d]; _ -> []} ) parsers

      --argparsers = concatMap (\x -> case x of {(Arg p) -> [p]; _ -> []} ) parsers

  let (actions, _args, msgs) = getOpt Permute optdescr rawArgs
      --argActions = parseArgs args argparsers

      groupedByShort = M.fromListWith (++) $ catMaybes $
                       map (\o@(Option (listToMaybe -> s) _ _ _) -> fmap (\x -> ('-':x:[], [o])) s) optdescr
      groupedByLong  = M.fromListWith (++) $ catMaybes $
                       map (\o@(Option _ (listToMaybe -> l) _ _) -> fmap (\x -> ("--"++x, [o])) l) optdescr

      duplicates = M.keys . M.filter (>1) . M.map length $ (M.unionWith (++) groupedByShort groupedByLong)

  unless (null duplicates) $
       error $ "Parsing error. Duplicate flags defined: " ++ intercalate ", " duplicates

  mapM_ (error . flip (++) (usageStr (signature initial))) msgs

  opts <- foldl' (>>=) (return initial) (actions) -- ++ argActions)
  return opts
parseOptions' conf rawArgs = do
  let initial = defConf

      usageStr sign = flip usageInfo optdescr . init . unlines $
                        [ "USAGE: " ++ pcProgName conf ++ " " ++ sign
                        , ""
                        , pcHelpExtraInfo conf
                        ]

      showHelp opts = do
        putStrLn $ usageStr (signature initial)
        exitWith ExitSuccess >>= \_ -> return opts

      helpdescr = case pcHelpFlag conf of
                    Just flag -> [ Option [] [flag] (NoArg showHelp) "print this help message and exit." ]
                    Nothing -> []

      parsers = runOptM parseOpts

      optdescr = helpdescr ++ concatMap (\x -> case x of {ParseOpt d -> [d]; _ -> []} ) parsers

      --argparsers = concatMap (\x -> case x of {(Arg p) -> [p]; _ -> []} ) parsers

  let (actions, _args, msgs) = getOpt Permute optdescr rawArgs
      --argActions = parseArgs args argparsers

      groupedByShort = M.fromListWith (++) $ catMaybes $
                       map (\o@(Option (listToMaybe -> s) _ _ _) -> fmap (\x -> ('-':x:[], [o])) s) optdescr
      groupedByLong  = M.fromListWith (++) $ catMaybes $
                       map (\o@(Option _ (listToMaybe -> l) _ _) -> fmap (\x -> ("--"++x, [o])) l) optdescr

      duplicates = M.keys . M.filter (>1) . M.map length $ (M.unionWith (++) groupedByShort groupedByLong)

  unless (null duplicates) $
       error $ "Parsing error. Duplicate flags defined: " ++ intercalate ", " duplicates

  mapM_ (error . flip (++) (usageStr (signature initial))) msgs

  opts <- foldl' (>>=) (return initial) (actions) -- ++ argActions)
  return opts