packages feed

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 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"++++