-----------------------------------------------------------------------------
-- |
-- Module : System.Console.GetOpt
--- Copyright : (c) Sven Panne Oct. 1996 (small changes Dec. 1997)
+-- Copyright : (c) Sven Panne 2002-2004
-- License : BSD-style (see the file libraries/base/LICENSE)
--
-- Maintainer : libraries@haskell.org
(e.g. '-help' is recognised as '--help', as long as there is no short
option 'h').
-Other differences between GNU's getopt and this implementation: * To
-enforce a coherent description of options and arguments, there are
-explanation fields in the option/argument descriptor. * Error
-messages are now more informative, but no longer POSIX
-compliant... :-( And a final Haskell advertisement: The GNU C
-implementation uses well over 1100 lines, we need only 195 here,
-including a 46 line example! :-)
+Other differences between GNU's getopt and this implementation:
+
+* To enforce a coherent description of options and arguments, there
+ are explanation fields in the option/argument descriptor.
+
+* Error messages are now more informative, but no longer POSIX
+ compliant... :-(
+
+And a final Haskell advertisement: The GNU C implementation uses well
+over 1100 lines, we need only 195 here, including a 46 line example!
+:-)
-}
module System.Console.GetOpt (
- -- * GetOpt
- getOpt,
- usageInfo,
- ArgOrder(..),
- OptDescr(..),
- ArgDescr(..),
+ -- * GetOpt
+ getOpt,
+ usageInfo,
+ ArgOrder(..),
+ OptDescr(..),
+ ArgDescr(..),
+
+ -- * Example
- -- * Example
-
- -- $example
- ) where
+ -- $example
+) where
-import Prelude
-import Data.List ( isPrefixOf )
+import Data.List ( isPrefixOf )
-- |What to do with options following non-options
data ArgOrder a
* list of short option characters
-* list of long option strings (without "--")
+* list of long option strings (without \"--\")
* argument descriptor
-> [OptDescr a] -- option descriptors
-> String -- nicely formatted decription of options
usageInfo header optDescr = unlines (header:table)
- where (ss,ls,ds) = (unzip3 . map fmtOpt) optDescr
+ where (ss,ls,ds) = (unzip3 . concatMap fmtOpt) optDescr
table = zipWith3 paste (sameLen ss) (sameLen ls) ds
paste x y z = " " ++ x ++ " " ++ y ++ " " ++ z
sameLen xs = flushLeft ((maximum . map length) xs) xs
flushLeft n xs = [ take n (x ++ repeat ' ') | x <- xs ]
-fmtOpt :: OptDescr a -> (String,String,String)
-fmtOpt (Option sos los ad descr) = (sepBy ',' (map (fmtShort ad) sos),
- sepBy ',' (map (fmtLong ad) los),
- descr)
+fmtOpt :: OptDescr a -> [(String,String,String)]
+fmtOpt (Option sos los ad descr) =
+ case lines descr of
+ [] -> [(sosFmt,losFmt,"")]
+ (d:ds) -> (sosFmt,losFmt,d) : [ ("","",d') | d' <- ds ]
where sepBy _ [] = ""
sepBy _ [x] = x
sepBy ch (x:xs) = x ++ ch:' ':sepBy ch xs
+ sosFmt = sepBy ',' (map (fmtShort ad) sos)
+ losFmt = sepBy ',' (map (fmtLong ad) los)
fmtShort :: ArgDescr a -> Char -> String
fmtShort (NoArg _ ) so = "-" ++ [so]
* The option descriptions (see 'OptDescr')
* The actual command line arguments (presumably got from
- 'System.Console.Environment.getArgs').
+ 'System.Environment.getArgs').
'getOpt' returns a triple, consisting of the argument values, a list
of options that didn\'t match, and a list of error messages.
longOpt :: String -> [String] -> [OptDescr a] -> (OptKind a,[String])
longOpt ls rs optDescr = long ads arg rs
where (opt,arg) = break (=='=') ls
- options = [ o | o@(Option _ ls _ _) <- optDescr, l <- ls, opt `isPrefixOf` l ]
+ getWith p = [ o | o@(Option _ ls _ _) <- optDescr, l <- ls, opt `p` l ]
+ exact = getWith (==)
+ options = if null exact then getWith isPrefixOf else exact
ads = [ ad | Option _ _ ad _ <- options ]
optStr = ("--"++opt)
{- $example
-To hopefully illuminate the role of the different "GetOpt" data
+To hopefully illuminate the role of the different data
structures, here\'s the command-line options for a (very simple)
compiler:
> module Opts where
>
-> import GetOpt
-> import Maybe ( fromMaybe )
+> import System.Console.GetOpt
+> import Data.Maybe ( fromMaybe )
>
> data Flag
> = Verbose | Version
> | Input String | Output String | LibDir String
-> deriving Show
+> deriving Show
>
> options :: [OptDescr Flag]
> options =
>
> compilerOpts :: [String] -> IO ([Flag], [String])
> compilerOpts argv =
-> case (getOpt Permute options argv) of
-> (o,n,[] ) -> return (o,n)
-> (_,_,errs) -> failIO (concat errs ++ usageInfo header options)
+> 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..."
-}