| Copyright | (c) Sven Panne 2002-2005 | 
|---|---|
| License | BSD-style (see the file libraries/base/LICENSE) | 
| Maintainer | [email protected] | 
| Stability | experimental | 
| Portability | portable | 
| Safe Haskell | Safe | 
| Language | Haskell2010 | 
This library provides facilities for parsing the command-line options in a standalone program. It is essentially a Haskell port of the GNU getopt library.
getOpt :: ArgOrder a -> [OptDescr a] -> [String] -> ([a], [String], [String]) Source
Process the command-line, and return the list of values that matched (and those that didn't). The arguments are:
ArgOrder)OptDescr)getArgs).getOpt returns a triple consisting of the option arguments, a list of non-options, and a list of error messages.
getOpt' :: ArgOrder a -> [OptDescr a] -> [String] -> ([a], [String], [String], [String]) Source
This is almost the same as getOpt, but returns a quadruple consisting of the option arguments, a list of non-options, a list of unrecognized options, and a list of error messages.
usageInfo :: String -> [OptDescr a] -> String Source
Return a string describing the usage of a command, derived from the header (first argument) and the options described by the second argument.
What to do with options following non-options
| RequireOrder | no option processing after first non-option  | 
| Permute | freely intersperse options and non-options  | 
| ReturnInOrder (String -> a) | wrap non-options into options  | 
Each OptDescr describes a single option.
The arguments to Option are:
Describes whether an option takes an argument or not, and if so how the argument is injected into a value of type a.
| NoArg a | no argument expected  | 
| ReqArg (String -> a) String | option requires argument  | 
| OptArg (Maybe String -> a) String | optional argument  | 
To hopefully illuminate the role of the different data structures, here are the command-line options for a (very simple) compiler, done in two different ways. The difference arises because the type of getOpt is parameterized by the type of values derived from flags.
A simple choice for the type associated with flags is to define a type Flag as an algebraic type representing the possible flags and their arguments:
   module Opts1 where
   
   import System.Console.GetOpt
   import Data.Maybe ( fromMaybe )
   
   data Flag 
    = Verbose  | Version 
    | Input String | Output String | LibDir String
      deriving Show
   
   options :: [OptDescr Flag]
   options =
    [ Option ['v']     ["verbose"] (NoArg Verbose)       "chatty output on stderr"
    , Option ['V','?'] ["version"] (NoArg Version)       "show version number"
    , Option ['o']     ["output"]  (OptArg outp "FILE")  "output FILE"
    , Option ['c']     []          (OptArg inp  "FILE")  "input FILE"
    , Option ['L']     ["libdir"]  (ReqArg LibDir "DIR") "library directory"
    ]
   
   inp,outp :: Maybe String -> Flag
   outp = Output . fromMaybe "stdout"
   inp  = Input  . fromMaybe "stdin"
   
   compilerOpts :: [String] -> IO ([Flag], [String])
   compilerOpts argv = 
      case getOpt Permute options argv of
         (o,n,[]  ) -> return (o,n)
         (_,_,errs) -> ioError (userError (concat errs ++ usageInfo header options))
     where header = "Usage: ic [OPTION...] files..."
Then the rest of the program will use the constructed list of flags to determine it's behaviour.
A different approach is to group the option values in a record of type Options, and have each flag yield a function of type Options -> Options transforming this record.
   module Opts2 where
   import System.Console.GetOpt
   import Data.Maybe ( fromMaybe )
   data Options = Options
    { optVerbose     :: Bool
    , optShowVersion :: Bool
    , optOutput      :: Maybe FilePath
    , optInput       :: Maybe FilePath
    , optLibDirs     :: [FilePath]
    } deriving Show
   defaultOptions    = Options
    { optVerbose     = False
    , optShowVersion = False
    , optOutput      = Nothing
    , optInput       = Nothing
    , optLibDirs     = []
    }
   options :: [OptDescr (Options -> Options)]
   options =
    [ Option ['v']     ["verbose"]
        (NoArg (\ opts -> opts { optVerbose = True }))
        "chatty output on stderr"
    , Option ['V','?'] ["version"]
        (NoArg (\ opts -> opts { optShowVersion = True }))
        "show version number"
    , Option ['o']     ["output"]
        (OptArg ((\ f opts -> opts { optOutput = Just f }) . fromMaybe "output")
                "FILE")
        "output FILE"
    , Option ['c']     []
        (OptArg ((\ f opts -> opts { optInput = Just f }) . fromMaybe "input")
                "FILE")
        "input FILE"
    , Option ['L']     ["libdir"]
        (ReqArg (\ d opts -> opts { optLibDirs = optLibDirs opts ++ [d] }) "DIR")
        "library directory"
    ]
   compilerOpts :: [String] -> IO (Options, [String])
   compilerOpts argv =
      case getOpt Permute options argv of
         (o,n,[]  ) -> return (foldl (flip id) defaultOptions o, n)
         (_,_,errs) -> ioError (userError (concat errs ++ usageInfo header options))
     where header = "Usage: ic [OPTION...] files..."
Similarly, each flag could yield a monadic function transforming a record, of type Options -> IO Options (or any other monad), allowing option processing to perform actions of the chosen monad, e.g. printing help or version messages, checking that file arguments exist, etc.
    © The University of Glasgow and others
Licensed under a BSD-style license (see top of the page).
    https://downloads.haskell.org/~ghc/7.10.3/docs/html/libraries/base-4.8.2.0/System-Console-GetOpt.html