    {-# LANGUAGE Safe #-}
    {-
    Copyright (c) 2005-2011 John Goerzen <jgoerzen@complete.org>

    All rights reserved.

    For license and copyright information, see the file LICENSE
    -}

    {- |
       Module     : MissingH.getOpt
       Copyright  : Copyright (C) 2005-2011 John Goerzen
       SPDX-License-Identifier: BSD-3-Clause

       Stability  : provisional
       Portability: portable

    Written by John Goerzen, jgoerzen\@complete.org

    Utilities for command-line parsing, including wrappers around
    the standard System.Console.GetOpt module.
    -}
    module System.Console.GetOpt.Utils (parseCmdLine,
                            validateCmdLine,
                            StdOption,
                            stdRequired,
                            stdOptional
                           )
    where
    import           System.Console.GetOpt
    import           System.Environment

    {- | Simple command line parser -- a basic wrapper around the system's
    default getOpt.  See the System.Console.GetOpt manual for a description of the
    first two parameters.

    The third parameter is a usage information header.

    The return value consists of the list of parsed flags and a list of
    non-option arguments. -}
    parseCmdLine :: ArgOrder a -> [OptDescr a] -> String -> IO ([a], [String])
    parseCmdLine :: ArgOrder a -> [OptDescr a] -> String -> IO ([a], [String])
    parseCmdLine order :: ArgOrder a
    order options :: [OptDescr a]
    options header :: String
    header =
        do [String]
    argv <- IO [String]
    getArgs
           case ArgOrder a -> [OptDescr a] -> [String] -> ([a], [String], [String])
    forall a.
    ArgOrder a -> [OptDescr a] -> [String] -> ([a], [String], [String])
    getOpt ArgOrder a
    order [OptDescr a]
    options [String]
    argv of
             (o :: [a]
    o, n :: [String]
    n, []) -> ([a], [String]) -> IO ([a], [String])
    forall (m :: * -> *) a. Monad m => a -> m a
    return ([a]
    o, [String]
    n)
             (_, _, errors :: [String]
    errors) -> IOError -> IO ([a], [String])
    forall a. IOError -> IO a
    ioError (String -> IOError
    userError ([String] -> String
    forall (t :: * -> *) a. Foldable t => t [a] -> [a]
    concat [String]
    errors String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++
                                                   String -> [OptDescr a] -> String
    forall a. String -> [OptDescr a] -> String
    usageInfo String
    header [OptDescr a]
    options))

    {- | Similar to 'parseCmdLine', but takes an additional function that validates
    the post-parse command-line arguments.  This is useful, for example, in
    situations where there are two arguments that are mutually-exclusive and only
    one may legitimately be given at a time.

    The return value of the function indicates whether or not it detected an
    error condition.  If it returns Nothing, there is no error.  If it returns
    Just String, there was an error, described by the String.
    -}
    validateCmdLine :: ArgOrder a -> [OptDescr a] -> String ->
                       (([a],[String]) -> Maybe String) -> IO ([a], [String])
    validateCmdLine :: ArgOrder a
    -> [OptDescr a]
    -> String
    -> (([a], [String]) -> Maybe String)
    -> IO ([a], [String])
    validateCmdLine order :: ArgOrder a
    order options :: [OptDescr a]
    options header :: String
    header func :: ([a], [String]) -> Maybe String
    func =
        do ([a], [String])
    res <- ArgOrder a -> [OptDescr a] -> String -> IO ([a], [String])
    forall a.
    ArgOrder a -> [OptDescr a] -> String -> IO ([a], [String])
    parseCmdLine ArgOrder a
    order [OptDescr a]
    options String
    header
           case ([a], [String]) -> Maybe String
    func ([a], [String])
    res of
             Nothing -> ([a], [String]) -> IO ([a], [String])
    forall (m :: * -> *) a. Monad m => a -> m a
    return ([a], [String])
    res
             Just errormsg :: String
    errormsg -> IOError -> IO ([a], [String])
    forall a. IOError -> IO a
    ioError (String -> IOError
    userError (String
    errormsg String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ "\n" String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++
                                                  String -> [OptDescr a] -> String
    forall a. String -> [OptDescr a] -> String
    usageInfo String
    header [OptDescr a]
    options))

    {- | A type to standardize some common uses of GetOpt.

    The first component of the tuple is the long name of the option.

    The second component is empty if there is no arg, or has the arg otherwise. -}
    type StdOption = (String, String)

    {- | Handle a required argument. -}
    stdRequired :: String           -- ^ Name of arg
                -> String -> StdOption
    stdRequired :: String -> String -> StdOption
    stdRequired name :: String
    name value :: String
    value = (String
    name, String
    value)

    {- | Handle an optional argument. -}
    stdOptional :: String           -- ^ Name of arg
                   -> Maybe String -> StdOption
    stdOptional :: String -> Maybe String -> StdOption
    stdOptional name :: String
    name Nothing  = (String
    name, "")
    stdOptional name :: String
    name (Just x :: String
    x) = (String
    name, String
    x)