Copyright © 2007 Dave Bayer. Subject to a BSD-style license.
This module is part of the Annote project.
module GetOpt
(OptionList,OptionSpecs,noArg,reqArg,optArg,makeOptions,parseOptions,
isOption,getOption,getOptionOr)
where
GetOpt handles command line options.
It is a wrapper around System.Console.GetOpt.
The modules
Options,
Convert, and
Main demonstate its use.
This design was influenced by the Haskell Cafe thread Avoiding boilerplate retrieving GetOpt cmd line args. See also the Haskell Wiki page GetOpt.
System.Console.GetOpt
is a Haskell port of GNU
getopt.
We import the following functions:
getOpt :: ArgOrder a -> [OptDescr a] -> [String] -> ([a], [String], [String])
usageInfo :: String -> [OptDescr a] -> String
import System.Console.GetOpt
(getOpt,usageInfo,ArgOrder(Permute),OptDescr(..),ArgDescr(..))
System.IO is the standard IO library.
We import the following functions:
hPutStr :: Handle -> String -> IO ()
hPutStrLn :: Handle -> String -> IO ()
import System.IO (stdout,stderr,hPutStr,hPutStrLn)
System.Exit handles exiting the program.
We import the following function:
exitWith :: ExitCode -> IO a
import System.Exit (ExitCode(..),exitWith)
We maintain option settings as association lists.
OptVal associates an option key with a string, which may be empty.ArgType is the type of noArg, reqArg, and optArg, defined below.OptionList is an association list of option keys and their values.OptionSpecs declares options in the form needed by getOpt.type OptVal a = (a,String) type ArgType a = a → String → ArgDescr (OptVal a) type OptionList a = [OptVal a] type OptionSpecs a = [OptDescr (OptVal a)]
noArg, reqArg, optArg are helper functions for use in constructing
an OptDescr list. While their constructor counterparts
NoArg, ReqArg, and OptArg have distinct types, we give these the
consistent type ArgType for ease of handling.
noArg, reqArg, optArg :: ArgType a
noArg x _ = NoArg (x,"")
reqArg x s = ReqArg f s
where f y = (x,y)
optArg x s = OptArg f s
where f (Just y) = (x,y)
f Nothing = (x,"")
makeOptions creates an OptionSpecs list from a list of
option specification tuples. A sample list entry is
(g,c,s,h,t,m) = (DateFormat, 'd', "date", reqArg, "format", "Date format")
where
g is the option key.c is the short option character.s is the long option string.h is one of noArg, reqArg, or optArg.t is the argument descriptor.m is an explanation of the option for the user
makeOptions :: [(a,Char,String,ArgType a,String,String)] → OptionSpecs a
makeOptions xs = map f xs
where f (g,c,s,h,t,m) = Option [c] [s] (h g t) m
parseOptions calls getOpt to process the command line arguments.
It is adapted from Don Stewart's example,
parseOptions ::
Eq a ⇒ [String] → OptionList a → String → OptionSpecs a
→ a → String → a
→ IO (OptionList a,[String])
parseOptions argv defaults usage flags version versionStr help =
case getOpt Permute flags argv of
(args,files,[]) → do
if isOption version args
then do hPutStr stdout versionStr
else return ()
if isOption help args
then do hPutStr stdout (usageInfo usage flags)
else return ()
return (args ++ defaults, files)
(_,_,errs) → do
hPutStrLn stderr (concat errs ++ usageInfo usage flags)
exitWith (ExitFailure 1)
isOption, getOption access the OptVal association list.
For getOption, the first match is returned, which is why parseOptions
appends default values to the association list.
isOption :: Eq a ⇒ a → OptionList a → Bool
isOption options assoc = case lookup options assoc of
Nothing → False
Just _ → True
getOption :: Eq a ⇒ a → OptionList a → String
getOption options assoc = case lookup options assoc of
Nothing → ""
Just s → s
getOptionOr substitutes a default for missing or empty strings.
This can be useful if the desired default is context-dependent, or
with optArg.
getOptionOr :: Eq a ⇒ a → OptionList a → String → String
getOptionOr options assoc def = case lookup options assoc of
Nothing → def
Just "" → def
Just s → s