packages feed

hflags 0.2 → 0.3

raw patch · 2 files changed

+64/−24 lines, 2 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ HFlags: globalUndefinedOptions :: IORef (Maybe [String])
+ HFlags: instance FlagType Char
+ HFlags: undefinedOptions :: [String]

Files

HFlags.hs view
@@ -34,8 +34,8 @@ -- the toplevel @flags_name@ constants.  Those can be used purely -- throughout the program. ----- At the beginning of the @main@ function, @$initHFlags "program--- description"@ has to be called to initialize the flags.  All flags+-- At the beginning of the @main@ function, @$'initHFlags' \"program+-- description\"@ has to be called to initialize the flags.  All flags -- will be initialized that are transitively reachable via imports -- from @main@.  This means, that any Haskell package can easily -- define command line flags with @HFlags@.  This feature is@@ -62,10 +62,11 @@ -- >   where -- >     greet = putStrLn $ "Hello " ++ flags_name ++ ", very nice to meet you!" ----- At @initHFlags@ time, the library also tries to gather flags out of+-- At 'initHFlags' time, the library also tries to gather flags out of -- environment variables.  @HFLAGS_verbose=True@ is equivalent to--- specify --verbose=True.  This environment feature only works with--- long options and the user has to specify a value even for Bools.+-- specifying @--verbose=True@ on the command line.  This environment+-- feature only works with long options and the user has to specify a+-- value even for @Bool@s. -- -- /Since version 0.2, you mustn't put the initHFlags in a parentheses with the program description.  Just/ @$initHFlags@, /it's cleaner./ @@ -80,10 +81,12 @@   initHFlagsDependentDefaults,   -- * For easy access to arguments, after initHFlags has been called   arguments,+  undefinedOptions,   -- * For debugging, shouldn't be used in production code   Flag(..),   globalHFlags,-  globalArguments+  globalArguments,+  globalUndefinedOptions   ) where  -- TODOs:@@ -121,7 +124,7 @@             , fArgType :: String             , fDescription :: String             , fModuleName :: String-            , fCheck :: IO () -- ^ function to evaluate in 'initFlags'+            , fCheck :: IO () -- ^ function to evaluate in @initFlags@                               -- to force syntax check of the argument.             } @@ -242,6 +245,16 @@ instance FlagType Bool where   defineFlag n v = defineCustomFlag n [| v :: Bool |] "BOOL" [| boolRead |] [| boolShow |] +charShow :: Char -> String+charShow x = x:[]++charRead :: String -> Char+charRead [x] = x+charRead s = error $ "Unable to parse string as char: " ++ s++instance FlagType Char where+  defineFlag n v = defineCustomFlag n [| v :: Char |] "CHAR" [| charRead |] [| charShow |]+ instance FlagType Int where   defineFlag n v = defineEQFlag n [| v :: Int |] "INT" @@ -262,19 +275,19 @@     let s = Data.Text.unpack v     in defineCustomFlag n [| Data.Text.pack s :: Data.Text.Text |] "TEXT" [| Data.Text.pack |] [| Data.Text.unpack |] --- | A global "IORef" for the communication between @initHFlags@ and+-- | A global 'IORef' for the communication between 'initHFlags' and -- @flags_*@.  This is a map between flag name and current value. {-# NOINLINE globalHFlags #-} globalHFlags :: IORef (Maybe (Map String String)) globalHFlags = unsafePerformIO $ newIORef Nothing --- | A global "IORef" for the easy access to the arguments.+-- | A global 'IORef' for the easy access to the arguments. {-# NOINLINE globalArguments #-} globalArguments :: IORef (Maybe [String]) globalArguments = unsafePerformIO $ newIORef Nothing  -- | Contains the non-parsed, non-option parts of the command line,--- the arguments.  Can only be used after @initHFlags@ has been called.+-- the arguments.  Can only be used after 'initHFlags' has been called. {-# NOINLINE arguments #-} arguments :: [String] arguments = unsafePerformIO $ do@@ -283,6 +296,25 @@     Just args -> return $ args     Nothing -> error $ "HFlags.arguments used before calling initHFlags." +-- | A global 'IORef' for the easy access to the undefined options, if+-- @--undefok@ is used.  Useful, if you have to pass these options to+-- another library, e.g. @criterion@ or @GTK@.+{-# NOINLINE globalUndefinedOptions #-}+globalUndefinedOptions :: IORef (Maybe [String])+globalUndefinedOptions = unsafePerformIO $ newIORef Nothing++-- | Contains the non-parsed, option parts of the command line, if+-- @--undefok@ is in use.  This can be useful, when you have to pass+-- these options to other libraries, e.g. @criterion@ or @GTK@.  Can+-- only be used after 'initHFlags' has been called.+{-# NOINLINE undefinedOptions #-}+undefinedOptions :: [String]+undefinedOptions = unsafePerformIO $ do+  margs <- readIORef globalUndefinedOptions+  case margs of+    Just args -> return $ args+    Nothing -> error $ "HFlags.globalUndefOpts used before calling initHFlags."+ lookupFlag :: String -> String -> String lookupFlag fName fModuleName = unsafePerformIO $ do   flags <- readIORef globalHFlags@@ -296,12 +328,13 @@ -- | A function that gets three alists and returns a new one. type DependentDefaults = AList -> AList -> AList -> AList --- | Initializes @globalHFlags@ and returns the non-option arguments.+-- | Initializes 'globalHFlags' and returns the non-option arguments. initFlags :: DependentDefaults -> String -> [FlagData] -> [String] -> IO [String] initFlags dependentDefaults progDescription flags args = do   doHelp-  let (opts, nonopts, errs) | doUndefok = (\(a,b,_,c) -> (a,b,c)) $ getOpt' Permute getOptFlags args-                            | otherwise = getOpt Permute getOptFlags args+  let (opts, nonopts, undefopts, errs)+        | doUndefok = getOpt' Permute getOptFlags args+        | otherwise = (\(a,b,c) -> (a,b,[],c)) $ getOpt Permute getOptFlags args   when (not $ null errs) $ do     mapM_ (hPutStrLn stderr) errs     exitFailure@@ -311,6 +344,7 @@   let depdef = dependentDefaults defaults envDefaults opts   writeIORef globalHFlags $ Just $ Map.fromList $ defaults ++ depdef ++ envDefaults ++ opts   writeIORef globalArguments $ Just nonopts+  writeIORef globalUndefinedOptions $ Just undefopts   mapM_ forceFlag flags   return nonopts     where@@ -318,7 +352,7 @@       helpOption = Option "h" ["help", "usage", "version"] (NoArg ("", "")) "Display help and version information."       doHelp = case getOpt Permute [helpOption] args of         ([], _, _) -> return ()-        _ -> do putStrLn $ usageInfo (progDescription ++ "\n") (helpOption:undefokOption:getOptFlags)+        _ -> do putStrLn $ usageInfo (progDescription ++ "\n") (helpOption:getOptFlags)                 exitFailure        undefokOption = Option "" ["undefok"] (NoArg ("", "")) "Whether to fail on unrecognized command line options."@@ -331,9 +365,11 @@         | otherwise = ReqArg (\a -> (fName, a)) fArgType        -- compute GetOpt compatible [Option] structure from flags ([FlagData])-      getOptFlags = flip map flags $ \flagData@(FlagData { fName, fShort, fDefValue, fDescription, fModuleName }) ->-        Option (maybeToList fShort) [fName] (flagToGetOptArgDescr flagData)-               (fDescription ++ " (default: " ++ fDefValue ++ ", from module: " ++ fModuleName ++ ")")+      getOptFlags = undefokOption:+        (flip map flags $ \flagData@(FlagData { fName, fShort, fDefValue, fDescription, fModuleName }) ->+         Option (maybeToList fShort) [fName]+                (flagToGetOptArgDescr flagData)+                (fDescription ++ " (default: " ++ fDefValue ++ ", from module: " ++ fModuleName ++ ")"))        forceFlag FlagData { fName, fModuleName, fCheck } =         fCheck `catch`@@ -399,10 +435,8 @@  -- | Has to be called from the main before doing anything else: ----- @--- main = do args <- $initHFlags "Simple program v0.1"---           ...--- @+-- > main = do args <- $initHFlags "Simple program v0.1"+-- >           ... -- -- /Since version 0.2, you mustn't put the initHFlags in a parentheses with the program description.  Just/ @$initHFlags@, /it's cleaner./ --
hflags.cabal view
@@ -1,5 +1,5 @@ name: hflags-version: 0.2+version: 0.3 license: OtherLicense license-file: COPYING author: Mihaly Barasz <klao@google.com>, Gergely Risko <gergely@risko.hu>@@ -22,8 +22,8 @@   the toplevel @flags_name@ constants.  Those can be used purely   throughout the program.   .-  At the beginning of the @main@ function, @$initHFlags "program-  description"@ has to be called to initialize the flags.  All flags+  At the beginning of the @main@ function, @$initHFlags \"program+  description\"@ has to be called to initialize the flags.  All flags   will be initialized that are transitively reachable via imports from   @main@.  This means, that any Haskell package can easily define   command line flags with @HFlags@.  This feature is demonstrated by@@ -57,6 +57,12 @@   long options and the user has to specify a value even for Bools.   .   /Since version 0.2, you mustn't put the initHFlags in a parentheses with the program description.  Just/ @$initHFlags@, /it's cleaner./+  .+  Changes in version 0.3+  .+  * Added @undefinedOptions@+  .+  * Added support for @Char@   .   Changes in version 0.2   .