packages feed

hflags (empty) → 0.1

raw patch · 9 files changed

+710/−0 lines, 9 filesdep +basedep +containersdep +template-haskellsetup-changed

Dependencies added: base, containers, template-haskell

Files

+ COPYING view
@@ -0,0 +1,202 @@++                                 Apache License+                           Version 2.0, January 2004+                        http://www.apache.org/licenses/++   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION++   1. Definitions.++      "License" shall mean the terms and conditions for use, reproduction,+      and distribution as defined by Sections 1 through 9 of this document.++      "Licensor" shall mean the copyright owner or entity authorized by+      the copyright owner that is granting the License.++      "Legal Entity" shall mean the union of the acting entity and all+      other entities that control, are controlled by, or are under common+      control with that entity. For the purposes of this definition,+      "control" means (i) the power, direct or indirect, to cause the+      direction or management of such entity, whether by contract or+      otherwise, or (ii) ownership of fifty percent (50%) or more of the+      outstanding shares, or (iii) beneficial ownership of such entity.++      "You" (or "Your") shall mean an individual or Legal Entity+      exercising permissions granted by this License.++      "Source" form shall mean the preferred form for making modifications,+      including but not limited to software source code, documentation+      source, and configuration files.++      "Object" form shall mean any form resulting from mechanical+      transformation or translation of a Source form, including but+      not limited to compiled object code, generated documentation,+      and conversions to other media types.++      "Work" shall mean the work of authorship, whether in Source or+      Object form, made available under the License, as indicated by a+      copyright notice that is included in or attached to the work+      (an example is provided in the Appendix below).++      "Derivative Works" shall mean any work, whether in Source or Object+      form, that is based on (or derived from) the Work and for which the+      editorial revisions, annotations, elaborations, or other modifications+      represent, as a whole, an original work of authorship. For the purposes+      of this License, Derivative Works shall not include works that remain+      separable from, or merely link (or bind by name) to the interfaces of,+      the Work and Derivative Works thereof.++      "Contribution" shall mean any work of authorship, including+      the original version of the Work and any modifications or additions+      to that Work or Derivative Works thereof, that is intentionally+      submitted to Licensor for inclusion in the Work by the copyright owner+      or by an individual or Legal Entity authorized to submit on behalf of+      the copyright owner. For the purposes of this definition, "submitted"+      means any form of electronic, verbal, or written communication sent+      to the Licensor or its representatives, including but not limited to+      communication on electronic mailing lists, source code control systems,+      and issue tracking systems that are managed by, or on behalf of, the+      Licensor for the purpose of discussing and improving the Work, but+      excluding communication that is conspicuously marked or otherwise+      designated in writing by the copyright owner as "Not a Contribution."++      "Contributor" shall mean Licensor and any individual or Legal Entity+      on behalf of whom a Contribution has been received by Licensor and+      subsequently incorporated within the Work.++   2. Grant of Copyright License. Subject to the terms and conditions of+      this License, each Contributor hereby grants to You a perpetual,+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable+      copyright license to reproduce, prepare Derivative Works of,+      publicly display, publicly perform, sublicense, and distribute the+      Work and such Derivative Works in Source or Object form.++   3. Grant of Patent License. Subject to the terms and conditions of+      this License, each Contributor hereby grants to You a perpetual,+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable+      (except as stated in this section) patent license to make, have made,+      use, offer to sell, sell, import, and otherwise transfer the Work,+      where such license applies only to those patent claims licensable+      by such Contributor that are necessarily infringed by their+      Contribution(s) alone or by combination of their Contribution(s)+      with the Work to which such Contribution(s) was submitted. If You+      institute patent litigation against any entity (including a+      cross-claim or counterclaim in a lawsuit) alleging that the Work+      or a Contribution incorporated within the Work constitutes direct+      or contributory patent infringement, then any patent licenses+      granted to You under this License for that Work shall terminate+      as of the date such litigation is filed.++   4. Redistribution. You may reproduce and distribute copies of the+      Work or Derivative Works thereof in any medium, with or without+      modifications, and in Source or Object form, provided that You+      meet the following conditions:++      (a) You must give any other recipients of the Work or+          Derivative Works a copy of this License; and++      (b) You must cause any modified files to carry prominent notices+          stating that You changed the files; and++      (c) You must retain, in the Source form of any Derivative Works+          that You distribute, all copyright, patent, trademark, and+          attribution notices from the Source form of the Work,+          excluding those notices that do not pertain to any part of+          the Derivative Works; and++      (d) If the Work includes a "NOTICE" text file as part of its+          distribution, then any Derivative Works that You distribute must+          include a readable copy of the attribution notices contained+          within such NOTICE file, excluding those notices that do not+          pertain to any part of the Derivative Works, in at least one+          of the following places: within a NOTICE text file distributed+          as part of the Derivative Works; within the Source form or+          documentation, if provided along with the Derivative Works; or,+          within a display generated by the Derivative Works, if and+          wherever such third-party notices normally appear. The contents+          of the NOTICE file are for informational purposes only and+          do not modify the License. You may add Your own attribution+          notices within Derivative Works that You distribute, alongside+          or as an addendum to the NOTICE text from the Work, provided+          that such additional attribution notices cannot be construed+          as modifying the License.++      You may add Your own copyright statement to Your modifications and+      may provide additional or different license terms and conditions+      for use, reproduction, or distribution of Your modifications, or+      for any such Derivative Works as a whole, provided Your use,+      reproduction, and distribution of the Work otherwise complies with+      the conditions stated in this License.++   5. Submission of Contributions. Unless You explicitly state otherwise,+      any Contribution intentionally submitted for inclusion in the Work+      by You to the Licensor shall be under the terms and conditions of+      this License, without any additional terms or conditions.+      Notwithstanding the above, nothing herein shall supersede or modify+      the terms of any separate license agreement you may have executed+      with Licensor regarding such Contributions.++   6. Trademarks. This License does not grant permission to use the trade+      names, trademarks, service marks, or product names of the Licensor,+      except as required for reasonable and customary use in describing the+      origin of the Work and reproducing the content of the NOTICE file.++   7. Disclaimer of Warranty. Unless required by applicable law or+      agreed to in writing, Licensor provides the Work (and each+      Contributor provides its Contributions) on an "AS IS" BASIS,+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or+      implied, including, without limitation, any warranties or conditions+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A+      PARTICULAR PURPOSE. You are solely responsible for determining the+      appropriateness of using or redistributing the Work and assume any+      risks associated with Your exercise of permissions under this License.++   8. Limitation of Liability. In no event and under no legal theory,+      whether in tort (including negligence), contract, or otherwise,+      unless required by applicable law (such as deliberate and grossly+      negligent acts) or agreed to in writing, shall any Contributor be+      liable to You for damages, including any direct, indirect, special,+      incidental, or consequential damages of any character arising as a+      result of this License or out of the use or inability to use the+      Work (including but not limited to damages for loss of goodwill,+      work stoppage, computer failure or malfunction, or any and all+      other commercial damages or losses), even if such Contributor+      has been advised of the possibility of such damages.++   9. Accepting Warranty or Additional Liability. While redistributing+      the Work or Derivative Works thereof, You may choose to offer,+      and charge a fee for, acceptance of support, warranty, indemnity,+      or other liability obligations and/or rights consistent with this+      License. However, in accepting such obligations, You may act only+      on Your own behalf and on Your sole responsibility, not on behalf+      of any other Contributor, and only if You agree to indemnify,+      defend, and hold each Contributor harmless for any liability+      incurred by, or claims asserted against, such Contributor by reason+      of your accepting any such warranty or additional liability.++   END OF TERMS AND CONDITIONS++   APPENDIX: How to apply the Apache License to your work.++      To apply the Apache License to your work, attach the following+      boilerplate notice, with the fields enclosed by brackets "[]"+      replaced with your own identifying information. (Don't include+      the brackets!)  The text should be enclosed in the appropriate+      comment syntax for the file format. We also recommend that a+      file or class name and description of purpose be included on the+      same "printed page" as the copyright notice for easier+      identification within third-party archives.++   Copyright [yyyy] [name of copyright owner]++   Licensed under the Apache License, Version 2.0 (the "License");+   you may not use this file except in compliance with the License.+   You may obtain a copy of the License at++       http://www.apache.org/licenses/LICENSE-2.0++   Unless required by applicable law or agreed to in writing, software+   distributed under the License is distributed on an "AS IS" BASIS,+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+   See the License for the specific language governing permissions and+   limitations under the License.
+ HFlags.hs view
@@ -0,0 +1,320 @@+-- Copyright 2012 Google Inc. All Rights Reserved.+--+-- Licensed under the Apache License, Version 2.0 (the "License");+-- you may not use this file except in compliance with the License.+-- You may obtain a copy of the License at+--+--     http://www.apache.org/licenses/LICENSE-2.0+--+-- Unless required by applicable law or agreed to in writing, software+-- distributed under the License is distributed on an "AS IS" BASIS,+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+-- See the License for the specific language governing permissions and+-- limitations under the License.+--+-- Authors: Mihaly Barasz <klao@google.com>, Gergely Risko <errge@google.com>++{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE NamedFieldPuns #-}++-- |+-- Module: HFlags+-- License: Apache 2.0+--+-- The @HFlags@ library supports easy definition of command line flags,+-- reimplementing the ideas from Google's @gflags@+-- (<http://code.google.com/p/gflags>).+--+-- Command line flags can be declared in any file at the toplevel,+-- using 'defineFlag'.  At runtime, the actual values are assigned to+-- 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+-- 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+-- <http://github.com/errge/hflags/blob/master/examples/ImportExample.hs>.+--+-- A simple example (more in the+-- <http://github.com/errge/hflags/tree/master/examples> directory):+--+-- > #!/usr/bin/env runhaskell+-- >+-- > {-# LANGUAGE TemplateHaskell #-}+-- >+-- > import HFlags+-- >+-- > defineFlag "name" "Indiana Jones" "Who to greet."+-- > defineFlag "r:repeat" (3 + 4 :: Int) "Number of times to repeat the message."+-- >+-- > main = do s <- $(initHFlags "Simple program v0.1")+-- >           sequence_ $ replicate flags_repeat greet+-- >   where+-- >     greet = putStrLn $ "Hello " ++ flags_name ++ ", very nice to meet you!"+--+-- 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.++module HFlags (+  -- * Definition of flags+  defineCustomFlag,+  defineQQFlag,+  FlagType(..),+  -- * Initialization of flags at runtime+  initHFlags) where++-- TODOs:+-- ?--no* for bools?+-- --help should show the current value if it's different than the default value, so user can test command line args++import Control.Exception+import Control.Monad+import Data.Char+import Data.Function+import Data.List+import Data.IORef+import Data.Maybe+import qualified Data.Map as Map+import Data.Map (Map, (!))+import Language.Haskell.TH+import System.Console.GetOpt+import System.Environment+import System.IO+import System.IO.Unsafe+import System.Exit++import Prelude hiding (catch)++-- | Data type for storing every property of a flag.+data FlagData = FlagData+            { fName :: String+            , fShort :: Maybe Char+            , fDefValue :: String+            , fArgHelp :: String+            , fDescription :: String+            , fModuleName :: String+            , fCheck :: IO () -- ^ function to evaluate in 'initFlags'+                              -- to force syntax check of the argument.+            }++-- | Every flag the program supports has to be defined through a new+-- phantom datatype and the Flag instance of that datatype.+--+-- But users of the library shouldn't worry about this class or the+-- implementation details behind these functions, just use the+-- @defineFlag@ Template Haskell function for defining new flags.+class Flag a where+  getFlagData :: a -> FlagData++-- | The most flexible way of defining a flag.  For an example see+-- <http://github.com/errge/hflags/blob/master/examples/ComplexExample.hs>.+-- For most things 'defineFlag' should be enough instead.+--+-- The parameters:+--+--   * name of the flag (@l:long@ syntax if you want to have the short option @l@ for this flag),+--+--   * quasiquoted and type signed default value,+--+--   * help string for the argument,+--+--   * read function, quasiquoted,+--+--   * show function, quasiquoted,+--+--   * help string for the flag.+defineCustomFlag :: String -> ExpQ -> String -> ExpQ -> ExpQ -> String -> Q [Dec]+defineCustomFlag name' defQ argHelp readQ showQ description =+  do (name, short) <- case () of+       () | length name' == 0 -> fail "Flag's without names are not supported."+          | length name' == 1 -> return (name', Just $ head name')+          | length name' == 2 -> return (name', Nothing)+          | name' !! 1 == ':' -> return (drop 2 name', Just $ head name')+          | otherwise -> return (name', Nothing)+     defE <- defQ+     case defE of+       SigE _ _ -> return ()+       _ -> fail "Default value for defineCustomFlag has to be an explicitly typed expression, like (12 :: Int)"+     moduleName <- fmap loc_module location+     let accessorName = mkName $ "flags_" ++ name+     let dataName = mkName $ "HFlag_" ++ name+     dataDec <- return $ DataD [] dataName [] [] []+     instanceDec <- instanceD+                    (return [])+                    (appT (conT ''Flag) (conT dataName))+                      [funD 'getFlagData [clause [wildP]+                                          (normalB+                                           [| FlagData+                                              name+                                              short+                                              $(appE showQ defQ)+                                              argHelp+                                              description+                                              moduleName+                                              (evaluate $(varE accessorName) >> return ())+                                           |]) []]]+     flagPragmaDec <- return $ PragmaD $ InlineP accessorName $ InlineSpec False False Nothing+     flagDec <- funD accessorName [clause [] (normalB [| case True of+                                                           True -> $(appE readQ [| lookupFlag name moduleName |])+                                                           False -> $(defQ) |]) []]+     return [dataDec, instanceDec, flagPragmaDec, flagDec]++-- | This just forwards to 'defineCustomFlag' with @[| read |]@ and+-- @[| show |]@.  Useful for flags where the type is not an instance+-- of 'FlagType'.  For examples, see+-- <http://github.com/errge/hflags/blob/master/examples/ComplexExample.hs>.+--+-- The parameters:+--+--   * name of the flag (@l:long@ syntax if you want to have the short option @l@ for this flag),,+--+--   * quasiquoted and type signed default value,+--+--   * help string for the argument,+--+--   * help string for the flag.+defineQQFlag :: String -> ExpQ -> String -> String -> Q [Dec]+defineQQFlag name defQ argHelp description =+ defineCustomFlag name defQ argHelp [| read |] [| show |] description++-- | Class of types for which the easy 'defineFlag' syntax is supported.+class FlagType t where+  -- | The @defineFlag@ function defines a new flag.+  --+  -- The parameters:+  --+  --   * name of the flag (@l:long@ syntax if you want to have the short option @l@ for this flag),,+  --+  --   * default value,+  --+  --   * help string for the flag.+  defineFlag :: String -> t -> String -> Q [Dec]++boolShow :: Bool -> String+boolShow True = "true"+boolShow False = "false"++boolRead :: String -> Bool+boolRead = boolRead' . map toLower+  where+    boolRead' ('y':_) = True+    boolRead' ('t':_) = True+    boolRead' ('1':_) = True+    boolRead' ('n':_) = False+    boolRead' ('f':_) = False+    boolRead' ('0':_) = False+    boolRead' s = error $ "Unable to parse string as boolean: " ++ s++instance FlagType Bool where+  defineFlag n v = defineCustomFlag n [| v :: Bool |] "BOOL" [| boolRead |] [| boolShow |]++instance FlagType Int where+  defineFlag n v = defineQQFlag n [| v :: Int |] "INT"++instance FlagType Integer where+  defineFlag n v = defineQQFlag n [| v :: Integer |] "INTEGER"++instance FlagType String where+  defineFlag n v = defineCustomFlag n [| v :: String |] "STRING" [| id |] [| id |]++instance FlagType Double where+  defineFlag n v = defineQQFlag n (sigE (litE (RationalL (toRational v))) [t| Double |] ) "DOUBLE"++-- | A global "IORef" for the communication between @initHFlags@ and+-- @flag_*@.  This is a map between flag name and current value.+{-# NOINLINE globalHFlags #-}+globalHFlags :: IORef (Maybe (Map String String))+globalHFlags = unsafePerformIO $ newIORef Nothing++lookupFlag :: String -> String -> String+lookupFlag fName fModuleName = unsafePerformIO $ do+  flags <- readIORef globalHFlags+  case flags of+    Just flagmap -> return $ flagmap ! fName+    Nothing -> error $ "Flag " ++ fName ++ " (from module: " ++ fModuleName ++ ") used before calling initHFlags."++-- | Initializes @globalHFlags@ and returns the non-option arguments.+initFlags :: String -> [FlagData] -> [String] -> IO [String]+initFlags 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+  when (not $ null errs) $ do+    mapM_ (hPutStrLn stderr) errs+    exitFailure+  let defaults = map (\FlagData { fName, fDefValue } -> (fName, fDefValue)) flags+  env <- getEnvironment+  let envDefaults = map (mapFst (fromJust . stripPrefix "HFLAGS_")) $ filter ((isPrefixOf "HFLAGS_") . fst) env+  writeIORef globalHFlags $ Just $ Map.fromList $ defaults ++ envDefaults ++ opts+  mapM_ forceFlag flags+  return nonopts+    where+      mapFst f (a, b) = (f a, b)+      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)+                exitFailure++      undefokOption = Option "" ["undefok"] (NoArg ("", "")) "Whether to fail on unrecognized command line options."+      doUndefok = case getOpt Permute [undefokOption] args of+        ([], _, _) -> False+        _ -> True++      flagToGetOptArgDescr FlagData { fName, fArgHelp }+        | fArgHelp == "BOOL" = OptArg (\a -> (fName, maybe "True" id a)) fArgHelp+        | otherwise = ReqArg (\a -> (fName, a)) fArgHelp++      -- 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 ++ ")")++      forceFlag FlagData { fName, fModuleName, fCheck } =+        fCheck `catch`+        (\e -> error $+               "Error while parsing argument for flag: " ++ fName +++               ", value: " ++ lookupFlag fName fModuleName +++               ", error: " ++ show (e :: ErrorCall))++-- | Has to be called from the main before doing anything else:+--+-- @+-- main = do args <- $(initHFlags "Simple program v0.1")+--           ...+-- @+--+-- Internally, it uses Template Haskell trickery to gather all the+-- instances of the Flag class and then generates a call to+-- @initFlags@ with the appropriate data gathered together from those+-- instances to a list.+--+-- Type after splicing is @IO [String]@.+initHFlags :: String -> ExpQ -- IO [String]+initHFlags progDescription = do+  ClassI _ instances <- reify ''Flag+  case dupes instances of+    [] -> return ()+    (dupe:_) -> fail ("Multiple definition of flag " ++ (snd $ head dupe) +++                       ", modules: " ++ (show $ map fst dupe))+  [| getArgs >>= initFlags progDescription $(listE $ map instanceToOptTuple instances ) |]+    where+      instanceToOptTuple (InstanceD _ (AppT _ inst) _) = [| getFlagData (undefined :: $(return inst)) |]+      instanceToOptTuple _ = error "Shouldn't happen"+      instanceToModuleNamePair (InstanceD _ (AppT _ (ConT inst)) _) =+        let (flagrev, modrev) = span (/= '.') $ reverse $ show inst+            modName = reverse $ drop 1 modrev+            flag = drop 1 $ dropWhile (/= '_') $ reverse $ flagrev+        in (modName, flag)+      instanceToModuleNamePair _ = error "Shouldn't happen"+      dupes instances = filter ((>1) . length) $+                        groupBy ((==) `on` snd) $+                        sortBy (compare `on` snd) $+                        map instanceToModuleNamePair instances
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ examples/ComplexExample.hs view
@@ -0,0 +1,72 @@+#!/usr/bin/env runhaskell+  +{-# LANGUAGE TemplateHaskell #-}++import Control.Monad+import System.Exit++import HFlags++-- For flags with a simple type (technically speaking, for instances+-- of FlagType, see `:info FlagType' in GHCi), defining a new flag is+-- very straightforward:+defineFlag "name" "Indiana Jones" "Who to greet."+-- There is a special syntax to support short options, like `d' here.+-- Also, for the Bool options the argument is not mandatory, if the+-- user just runs the program with -d or --dry_run, flags_dru_run will+-- be set to True.+defineFlag "d:dry_run" False "Don't print anything, just exit."+-- For integral types you have to explicitly define Int or Integer.+defineFlag "repeat" (3 + 4 :: Int) "Number of times to repeat the message."++-- For flags with a more complex type, where the existing Read and+-- Show is suitable for parsing of the argument value, you can use the+-- defineQQFlag syntax.  Here, the QQ is mnemonic for QuasiQuoter,+-- because you have to quasiquote the default value, and type sign it+-- inside the quasiquote.  Also, you have to provide the name of the+-- type for --help generation.+defineQQFlag "numbers_to_sum" [| [1,2,3,4,5] :: [Int] |] "INT_LIST" "Print the sum of these numbers."++-- This works quite well for simple enums too!+data Color = Red | Yellow | Green deriving (Show, Read)+defineQQFlag "favorite_color" [| Yellow :: Color |] "COLOR" "Your favorite color."++-- Sometimes the default read or show instance is not good enough for+-- your needs.  In that case you can use defineCustomFlag to override+-- those functions.+data Language = English | Hungarian+defineCustomFlag "language" [| English :: Language |] "en|hu"+  [| \s -> case s of +      "en" -> English+      "hu" -> Hungarian+      _ -> error $ "Unknown language: " ++ s+   |]+  [| \l -> case l of +      English -> "en"+      Hungarian -> "hu"+   |]+  "Language of the greeting."++-- You can also do simple range checks with this.+defineCustomFlag "percent" [| 100 :: Double |] "PERCENTAGE"+  [| \s -> let p = read s+           in if 0.0 <= p && p <= 100.0+              then p+              else error "Percentage value has to be between 0 and 100."+   |]+  [| show |]+  "Print first percent percentage of the message."++main = do+  _ <- $(initHFlags "HFlags example program v0.1")+  when (flags_dry_run) $ exitSuccess+  forM_ [1..flags_repeat] (const greet)+  putStrLn $ "IIRC, your favorite color is " ++ show flags_favorite_color ++ "."+  where+    s = show (sum flags_numbers_to_sum)+    percentPutStrLn 0 _ = return ()+    percentPutStrLn p str = let n = ceiling $ fromIntegral (length str) * p / 100.0+                            in putStrLn $ take n str+    greet = percentPutStrLn flags_percent $ case flags_language of+      English -> "Hello " ++ flags_name ++ ", very nice to meet you, the sum is " ++ s ++ "!"+      Hungarian -> "Szia " ++ flags_name ++ ", orvendek a talalkozasnak, a szamok osszege " ++ s ++ "!"
+ examples/ImportExample.hs view
@@ -0,0 +1,9 @@+#!/usr/bin/env runhaskell+  +{-# LANGUAGE TemplateHaskell #-}++import HFlags+import X.B++main = do _ <- $(initHFlags "Importing example v0.1")+          print $ b
+ examples/SimpleExample.hs view
@@ -0,0 +1,13 @@+#!/usr/bin/env runhaskell+  +{-# LANGUAGE TemplateHaskell #-}++import HFlags++defineFlag "name" "Indiana Jones" "Who to greet."+defineFlag "repeat" (3 + 4 :: Int) "Number of times to repeat the message."++main = do s <- $(initHFlags "Simple program v0.1")+          sequence_ $ replicate flags_repeat greet+  where+    greet = putStrLn $ "Hello " ++ flags_name ++ ", very nice to meet you!"
+ examples/X/B.hs view
@@ -0,0 +1,9 @@+module X.B (b) where++import qualified X.Y_Y.A as A++-- to test collision detection+-- import HFlags+-- defineFlag "verbose" True "Whether debug output should be printed."++b = A.flags_verbose
+ examples/X/Y_Y/A.hs view
@@ -0,0 +1,7 @@+{-# LANGUAGE TemplateHaskell #-}++module X.Y_Y.A where++import HFlags++defineFlag "verbose" True "Whether debug output should be printed."
+ hflags.cabal view
@@ -0,0 +1,76 @@+name: hflags+version: 0.1+license: OtherLicense+license-file: COPYING+author: Mihaly Barasz <klao@google.com>, Gergely Risko <errge@google.com>+maintainer: Gergely Risko <errge@google.com>+build-type: Simple+cabal-version: >= 1.6+category: Console+stability: provisional+homepage: http://github.com/errge/hflags+bug-reports: mailto:errge@google.com++synopsis: Command line flag parser, very similar to Google's gflags+description:+  The @HFlags@ library supports easy definition of command line flags,+  reimplementing the ideas from Google's @gflags@+  (<http://code.google.com/p/gflags>).+  .+  Command line flags can be declared in any file at the toplevel,+  using 'defineFlag'.  At runtime, the actual values are assigned to+  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+  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+  <http://github.com/errge/hflags/blob/master/examples/ImportExample.hs>.+  .+  A simple example (more in the+  <http://github.com/errge/hflags/tree/master/examples> directory):+  .+  @+  \#!\/usr\/bin\/env runhaskell+  .+  &#x7b;-\# LANGUAGE TemplateHaskell \#-&#x7d;+  .+  import HFlags+  .+  'defineFlag' \"name\" \"Indiana Jones\" \"Who to greet.\"+  'defineFlag' \"r:repeat\" (3 + 4 :: Int) \"Number of times to repeat the message.\"+  .+  main = do s <- $(initHFlags \"Simple program v0.1\")+  &#x20;         sequence_ $ replicate flags_repeat greet+  &#x20; where+  &#x20;   greet = putStrLn $ \"Hello \" ++ flags_name ++ \", very nice to meet you!\"+  @+  .+  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.++extra-source-files:+  examples/ComplexExample.hs+  examples/ImportExample.hs+  examples/SimpleExample.hs+  examples/X/B.hs+  examples/X/Y_Y/A.hs++source-repository head+  type: git+  location: http://github.com/errge/hflags++library+  ghc-options: -Wall++  build-depends:+      base >= 4.5 && < 5+    , containers >= 0.4+    , template-haskell >= 2.7++  exposed-modules:+    HFlags