simple-get-opt (empty) → 0.1.0.0
raw patch · 4 files changed
+237/−0 lines, 4 filesdep +basesetup-changed
Dependencies added: base
Files
- LICENSE +30/−0
- Setup.hs +2/−0
- simple-get-opt.cabal +26/−0
- src/SimpleGetOpt.hs +179/−0
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2015, Iavor S. Diatchki++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Iavor S. Diatchki nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ simple-get-opt.cabal view
@@ -0,0 +1,26 @@+name: simple-get-opt+version: 0.1.0.0+synopsis: A simple library for processing command-line options.+description:+ A simple library for processing command-line options.+ The library captures a common usage pattern of the GetOpt module+ form the standard libraries.++license: BSD3+license-file: LICENSE+author: Iavor S. Diatchki+maintainer: iavor.diatchki@gmail.com+category: Development+build-type: Simple+cabal-version: >=1.10++library+ hs-source-dirs: src+ exposed-modules: SimpleGetOpt+ build-depends: base < 10+ default-language: Haskell2010++source-repository head+ type: git+ location: git://github.com/yav/simple-get-opt.git+
+ src/SimpleGetOpt.hs view
@@ -0,0 +1,179 @@+{- | Provides support for processing command-line arguments.+This is a simple wrapper around get-opt.+Here is an example of a typical usage:++> data Settings = Settings+> { verbose :: Bool+> , inPar :: Int+> , files :: [String]+> }+>+> options :: OptSpec Settings+> options = OptSpec+> { progDefaults = Settings { verbose = False+> , inPar = 1+> , files = []+> }+>+> , progOptions =+> [ Option ['v'] ["verbose"]+> "Display more information while working."+> $ NoArg $ \s -> Right s { verbose = True }+>+> , Option ['p'] ["par"]+> "Process that many files at once."+> $ ReqArg "NUM" $ \a s ->+> case readMaybe a of+> Just n | n > 0 -> Right s { inPar = n }+> _ -> Left "Invalid value for `par`"+> ]+>+> , progParamDocs =+> [ ("FILES", "The files that need processing.") ]+>+> , progParams = \p s -> Right s { files = p : files s }+> }++Here is what the usage information looks like:++> *Main> dumpUsage options +> Parameters:+> FILES The files that need processing.+>+> Flags:+> -v --verbose Display more information while working.+> -p NUM --par=NUM Process that many files at once.+-}++module SimpleGetOpt+ ( -- * Basic functionality+ getOpts+ , OptSpec(..)+ , OptDescr(..)+ , OptSetter+ , ArgDescr(..)++ -- * Information and error reporting.+ , dumpUsage+ , reportUsageError+ , usageString+ ) where++import qualified System.Console.GetOpt as GetOpt+import System.IO(stderr,hPutStrLn)+import System.Exit(exitFailure)+import System.Environment(getArgs)++import Control.Monad(unless)++++-- | Specification of a collection of options, described by type @a@.+data OptSpec a = OptSpec+ { progDefaults :: a+ -- ^ Default options.+ -- This is what is used if no other options are provided.++ , progOptions :: [OptDescr a]+ -- ^ A list of options and command-line flags.++ , progParamDocs :: [(String,String)]+ -- ^ Documentatio for the free-form parameters.++ , progParams :: String -> OptSetter a+ -- ^ Add a parameter that is not an option or a flag+ -- (i.e., this is just a free form command line parameter).++ }++-- | Describe an option.+data OptDescr a = Option+ { optShortFlags :: [Char]+ , optLongFlags :: [String]+ , optDescription :: String+ , optArgument :: ArgDescr a+ }++-- | Manipulate options of type @a@, with support for errors.+type OptSetter a = a -> Either String a++-- | Describe an option argumnet.+data ArgDescr a =++ NoArg (OptSetter a)+ -- ^ This option does not take an argument.++ | ReqArg String (String -> OptSetter a)+ -- ^ This optoin has a required arugment.+ -- The string describes the type of the argument.++ | OptArg String (Maybe String -> OptSetter a)+ -- ^ This optoin has an optional arugment.+ -- The string describes the type of the argument.+++opts :: OptSpec a -> [ GetOpt.OptDescr (OptSetter a) ]+opts = map convertOpt . progOptions++convertArg :: ArgDescr a -> GetOpt.ArgDescr (OptSetter a)+convertArg arg =+ case arg of+ NoArg a -> GetOpt.NoArg a+ ReqArg s a -> GetOpt.ReqArg a s+ OptArg s a -> GetOpt.OptArg a s++convertOpt :: OptDescr a -> GetOpt.OptDescr (OptSetter a)+convertOpt (Option a b c d) = GetOpt.Option a b (convertArg d) c++++addOpt :: (a, [String]) -> (a -> Either String a) -> (a, [String])+addOpt (a,es) f = case f a of+ Left e -> (a,e:es)+ Right a1 -> (a1,es)++addFile :: (String -> OptSetter a) -> (a, [String]) -> String -> (a,[String])+addFile add (a,es) file = case add file a of+ Left e -> (a,e:es)+ Right a1 -> (a1,es)+++-- | Get the command-line options and process them according to the given spec.+-- The options will be permuted to get flags.+getOpts :: OptSpec a -> IO a+getOpts os =+ do as <- getArgs+ let (funs,files,errs) = GetOpt.getOpt GetOpt.Permute (opts os) as+ unless (null errs) $ reportUsageError os errs+ let (a, errs1) = foldl addOpt (progDefaults os,[]) funs+ unless (null errs1) $ reportUsageError os errs1+ let (b, errs2) = foldl (addFile (progParams os)) (a,[]) files+ unless (null errs2) $ reportUsageError os errs2+ return b++-- | Print the given messages on 'stderr' and show the program's usage info.+reportUsageError :: OptSpec a -> [String] -> IO b+reportUsageError os es =+ do hPutStrLn stderr "Invalid command line options:"+ hPutStrLn stderr $ unlines $ map (" " ++) es+ dumpUsage os+ exitFailure++-- | Show the program's usage information on 'stderr'.+dumpUsage :: OptSpec a -> IO ()+dumpUsage os = hPutStrLn stderr (usageString os)+++-- | A string descibing the options.+usageString :: OptSpec a -> String+usageString os = GetOpt.usageInfo (params ++ "Flags:") (opts os)+ where+ params = case concatMap ppParam (progParamDocs os) of+ "" -> ""+ ps -> "Parameters:\n" ++ ps ++ "\n"++ ppParam (x,y) = " " ++ x ++ " " ++ y ++ "\n"++++