packages feed

simpleargs (empty) → 0.1

raw patch · 5 files changed

+187/−0 lines, 5 filesdep +basesetup-changed

Dependencies added: base

Files

+ Example.hs view
@@ -0,0 +1,8 @@+-- | Simple example, demonstrating the usage+--   This requires the first arg to be an int, and the second to be a string.+import System.SimpleArgs++main = do+  (i,name) <- getArgs+  print (i+10::Int)+  print ("Hello, "++name++"!")
+ README view
@@ -0,0 +1,74 @@++SimpleArgs - provide a more flexible and informative replacement for getArgs ++For "real" command line programs, you usually want to provide a+flexible command line with various options and settings, sensibly+named and with auto-generated help.  In that case, SimpleArgs is not+for you, stop reading this, and look up System.Console.GetOpt+instead. ++But sometimes, a quick hack is just what you need.  Previously, you+were wont to do:++      main = do+      	   [count',gender'] <- getArgs+	   let count = read count+	   let gender = case gender' of +	       	      	     "M" -> 'M'+			     "F" -> 'F'+	   main_real count gender++This is somewhat tedious, wastes precious sceen estate, users+supplying parameters of the wrong type will get obscure errors, and+while any programming errors you might introduce probably will be+trivial, it would be better to avoid them entirely.++The SimpleArgs module provides getArgs with an overloaded return type,+so that command line parameters are parsed as the types required by+the rest of the program.++Using SimpleArgs, the above could therefore look like this:++      main = do +      	   (count,gender) <- getArgs+	   main_real count gender++or even (I think):++      main = getArgs >>= return . uncurry main_real++If that was a bit contrieved, let's say you just want to read a file+name:++     main = do+     	  [filename] <- getArgs+	  readFile filename >>= print . length ++I'm sure you could avoid the information-free name "filename" by some+esoteric tranformation to more point-free style, but I argue that+SimpleArgs makes this natural and easy:++     main = getArgs >>= readFile >>= print . length++I don't think 'wc -c' gets much easier than this.++Instead of reporting incomplete cases or read failures, SimpleArgs+will provide more sensible error reporting. (To try this, build Example+by executing 'ghc --make Example.hs').  It will:++      1) report incorrect number of parameters,+      	 also mentioning the expected parameters and types:++	  % ./Example foo+	  Example: Incorrect number of arguments, got 1,+	  expected 2 (Int,[Char])++	This also gives you a useful hint if you just run the program+	without any parameters.++      2) report parameters that fail to parse as the required type:++          % ./Example foo 10+ 	  Example: Couldn't parse parameter "foo" as type Int++Nice, huh?  Please enjoy, and let me know how you fare at ketil@malde.org.
+ Setup.hs view
@@ -0,0 +1,5 @@+#!/usr/bin/env runhaskell++import Distribution.Simple+main = defaultMain+
+ System/SimpleArgs.hs view
@@ -0,0 +1,76 @@+{-# LANGUAGE FlexibleInstances #-}+{-# OPTIONS -fallow-undecidable-instances  -fno-monomorphism-restriction -fallow-overlapping-instances #-}++-- | Provide a @getArgs@ function that returns a tuple (including the 0-tuple @()@ or 1-tuple)+--   if the supplied arguments match the demands of the program, in number and in type. +--   The returned tuple must contain elements that are in the @Typeable@ and @Read@ classes.+--+-- Here's how to do a line count, @getArgs@ takes a single argument, returning it+-- as a @String@:+-- +-- > main = getArgs >>= readFile >>= print . length . lines+--+-- Two different parameters, a @Char@ and a @String@:+--+-- > main = do+-- >    (ch,name) <- getArgs+-- >    putStrLn (ch:"Name is: "++name)++module System.SimpleArgs (Args, getArgs) where++import qualified System.Environment as S (getArgs)+import Data.Dynamic (Typeable, typeOf)++class Args a where+    -- | Return appropriately typed program arguments.+    getArgs :: IO a++argerror :: Typeable a => Int -> [String] -> a+argerror n xs = let ret = error ("Incorrect number of arguments, got "++show (length xs)++",\n"+                                ++"expected "++show n ++ " "++show (typeOf ret))+                in ret++instance Args () where+    getArgs = S.getArgs >>= return . g+        where g [] = ()+              g xs = argerror 0 xs++instance (Read b, Typeable b) => Args b where+    getArgs = S.getArgs >>= return . g+        where g [x] = myread x+              g xs = argerror 1 xs++instance (Read x, Typeable x, Read y, Typeable y) => Args (x,y) where+    getArgs = S.getArgs >>= return . g+        where g [x1,x2] = (myread x1,myread x2)+              g xs = argerror 2 xs++instance (Read t1, Typeable t1,Read t2, Typeable t2,Read t3, Typeable t3) => Args (t1,t2,t3) where+    getArgs = S.getArgs >>= return . g+        where g [x1,x2,x3] = (myread x1,myread x2,myread x3)+              g xs = argerror 3 xs++instance (Read t1,Typeable t1,Read t2,Typeable t2,Read t3,Typeable t3,Read t4,Typeable t4) => Args (t1,t2,t3,t4) where+    getArgs = S.getArgs >>= return . g+        where g [x1,x2,x3,x4] = (myread x1,myread x2,myread x3,myread x4)+              g xs = argerror 4 xs++instance (Read t1,Typeable t1,Read t2,Typeable t2,Read t3,Typeable t3,Read t4,Typeable t4,Read t5,Typeable t5) => Args (t1,t2,t3,t4,t5) where+    getArgs = S.getArgs >>= return . g+        where g [x1,x2,x3,x4,x5] = (myread x1,myread x2,myread x3,myread x4,myread x5)+              g xs = argerror 5 xs++-- | Attempt to parse the parameter as various types+myread :: (Typeable a, Read a) => String -> a+myread s = let ret = case map reads [s,sq s,dq s,lq s] of+                       ([(x,"")]:_) -> x+                       (_:[(c,"")]:_) -> c+                       (_:_:[(str,"")]:_) -> str+                       (_:_:_:[(l,"")]:_) -> l+                       _ -> error ("Couldn't parse parameter "++show s++" as type "++show (typeOf ret))+           in ret+    where+      -- different types of quoting+      sq x = "'"++x++"'"+      dq x = "\""++x++"\""+      lq x = "["++x++"]"
+ simpleargs.cabal view
@@ -0,0 +1,24 @@+Name:         simpleargs+Version:      0.1+License:      LGPL++Author:       Ketil Malde <ketil@malde.org>+Stability:    Beta+Synopsis:     Provides a more flexible getArgs function with better error reporting.+Description:  The provided getArgs returns an arbitrary tuple of values instead of a +	      list of Strings.  This means that the number and type (i.e. parseability)+	      of parameters are checked, and reported to the user.  The module is not+	      a substitute for proper error handling (use System.Console.GetOpt for that),+	      but is useful for making quick and dirty command line tools a bit less dirty,+	      without sacrificing the quick part.+Homepage:     http://malde.org/~ketil/simpleargs++Build-Depends:  base+Build-Type:     Simple+Tested-With:    GHC==6.8.2++ghc-options:      -Wall+Include-Dirs:     .+Exposed-Modules:    System.SimpleArgs+Extra-Source-Files: Example.hs+Data-Files:         README