+<sect> <idx/GetOpt/
+<label id="sec:GetOpt">
+<p>
+
+The <tt/GetOpt/ library contains Sven Panne's Haskell implementation
+of <tt/getopt/, providing features nigh-on identical to GNU <tt/getopt/:
+
+<tscreen><verb>
+module GetOpt where
+
+-- representing a single option:
+data OptDescr a
+ = Option [Char] -- list of short option characters
+ [String] -- list of long option strings (without "--")
+ (ArgDescr a) -- argument descriptor
+ String -- explanation of option for user
+
+-- argument option:
+data ArgDescr a
+ = NoArg a -- no argument expected
+ | ReqArg (String -> a) String -- option requires argument
+ | OptArg (Maybe String -> a) String -- optional argument
+
+usageInfo :: String -- header
+ -> [OptDescr a] -- options recognised
+ -> String -- nicely formatted decription of options
+
+getOpt :: ArgOrder a -- non-option handling
+ -> [OptDescr a] -- options recognised
+ -> [String] -- the command-line
+ -> ( [a] -- options
+ , [String] -- non-options
+ ,[String] -- error messages
+ )
+
+data ArgOrder a
+ = RequireOrder
+ | Permute
+ | ReturnInOrder (String -> a)
+
+</verb></tscreen>
+
+<itemize>
+<item> The command-line options recognised is described by a list of
+<tt/OptDescr/ values. The <tt/OptDescr/ describes the long and short
+strings that recognise the option, together with a help string and
+info on whether the option takes extra arguments, if any.
+<item>
+From a list of option values, <tt/usageInfo/ returns a nicely
+formatted string that enumerates the different options supported
+together with a short message about what
+<item>
+To decode a command-line with respect to a list of options,
+<tt/getOpt/ is used. It processes the command-line, and returns
+the list of values that matched (and those that didn't). The first
+argument to <tt/getOpt/ controls whether the user is to give the
+options in any old order or not.
+</itemize>
+
+To hopefully illuminate the role of the different <tt/GetOpt/ data
+structures, here's the command-line options for a (very simple)
+compiler:
+
+<tscreen><verb>
+module Opts where
+
+import GetOpt
+import 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 "stdout"
+
+compilerOpts :: [String] -> IO ([Flag], [String])
+compilerOpts argv =
+ case (getOpt Permute options argv) of
+ (o,n,[] ) -> return (o,n)
+ (_,_,errs) -> fail (userError (concat errs ++ usageInfo header options))
+ where header = "Usage: ic [OPTION...] files..."
+</verb></tscreen>
+
+