packages feed

configuration-tools 0.2.5 → 0.2.6

raw patch · 8 files changed

+360/−82 lines, 8 filesdep +case-insensitivesetup-changedPVP ok

version bump matches the API change (PVP)

Dependencies added: case-insensitive

API changes (from Hackage documentation)

+ Configuration.Utils: boolOption :: Mod OptionFields Bool -> Parser Bool
+ Configuration.Utils: boolReader :: (Eq a, Show a, FoldCase a, IsString a, IsString e, Monoid e) => a -> Either e Bool
+ Configuration.Utils: eitherReadP :: Text -> ReadP a -> Text -> Either Text a
+ Configuration.Utils: fileOption :: Mod OptionFields String -> Parser FilePath
+ Configuration.Utils: maybeOption :: a -> Bool -> (a -> a) -> Maybe a -> Maybe a

Files

CHANGELOG.md view
@@ -1,3 +1,17 @@+0.2.6+=====++*   For git repositories include also light-weight (non-annotated) tags+    in the version description.++*   Added new function `boolReader`, `boolOption`, `fileOption`, and+    `eitherReadP` to `Utils`.++*   Added new function `maybeOption` and improved documentation about+    `Maybe` config values.++*   Included optimisation level into long info.+ 0.2.5 ===== 
README.md view
@@ -281,7 +281,13 @@ Optional Configuration Values ----------------------------- -For configuration values of type `Maybe a`, though being sum types, we provide+For simple `Maybe` values the standard `FromJSON` instance from the aeson+package can be used along with the `..:` operator. When defining command line+option parsers with `.::` and `%::` all options are optional. When an option is+not present on the command line the default value is used. For `Maybe` values+it is therefore enough to wrap the parsed value into `Just`.++For configuration values of type `Maybe a` where `a` is a record type we provide an orphan[^1] `FromJSON` instance of the form  ~~~{.haskell}@@ -290,14 +296,18 @@  that has the following behavior: -If the parsed configuration value is 'Null' the resulting function constantly+If the parsed configuration value is `Null` the resulting function constantly returns `Nothing`. Otherwise -*   the function does an pointwise update using the `FromJSON` instance for-    `a -> a` when applied to `Just a` and-*   the function uses the `FromJSON` instance for `a` to return the parsed `a`-    value when applied to 'Nothing'.+*   If the parsed configuration value is `Null` the result is `Nothing`.+*   If the parsed configuration value is not `Null` then the result is+    an update function that +    *   updates the given default value if this value is `Just x` or+    *   is a constant function that returns the value that is parsed+        from the configuration using the `FromJSON` instance for the+        configuration type.+ The `FromJSON a` instance may either require that the parsed configuration fully specifies the value of `a` (and raise a failure otherwise) or the `FromJSON a` instance may do an pointwise update of a hardcoded default value based on@@ -317,6 +327,9 @@       is an issue for you, please let me know. In that case we can define a new       type for optional configuration values. +The function `maybeOption` is provided for defining command line parser for+`Maybe` record values.+ Package and Build Information ============================= @@ -411,7 +424,7 @@ `examples/Trivial.hs` from this package:  ~~~{.shell}-trivial-0.2.3 (package configuration-tools-0.2.3 revision 83634a3)+trivial-0.2.6 (package configuration-tools-0.2.6 revision 2cc860c) Copyright (c) 2014 AlephCloud, Inc.  Author: Lars Kuhtz <lars@alephcloud.com>@@ -419,11 +432,12 @@ Homepage: https://github.com/alephcloud/hs-configuration-tools Build with: ghc-7.8.3 (x86_64-osx) Build flags:+Optimisation: normal  Dependencies:-    Cabal-1.20.0.1 [BSD3, 2003-2006, Isaac Jones 2005-2011, Duncan Coutts]-    MonadRandom-0.1.13 [OtherLicense]-    aeson-0.7.0.6 [BSD3, (c) 2011-2014 Bryan O'Sullivan (c) 2011 MailRank, Inc.]+    Cabal-1.20.0.2 [BSD3, 2003-2006, Isaac Jones 2005-2011, Duncan Coutts]+    MonadRandom-0.3 [OtherLicense]+    aeson-0.8.0.0 [BSD3, (c) 2011-2014 Bryan O'Sullivan (c) 2011 MailRank, Inc.]     ansi-terminal-0.6.1.1 [BSD3]     ansi-wl-pprint-0.6.7.1 [BSD3]     array-0.5.0.0 [BSD3]@@ -433,15 +447,16 @@     bifunctors-4.1.1.1 [BSD3, Copyright (C) 2008-2013 Edward A. Kmett]     rts-1.0 [BSD3]     bytestring-0.10.4.0 [BSD3, Copyright (c) Don Stewart 2005-2009, (c) Duncan Coutts 2006-2013, (c) David Roundy 2003-2005, (c) Jasper Van der Jeugt 2010, (c) Simon Meier 2010-2013.]-    comonad-4.2 [BSD3, Copyright (C) 2008-2013 Edward A. Kmett, Copyright (C) 2004-2008 Dave Menendez]-    conduit-1.1.6 [MIT]+    case-insensitive-1.2.0.0 [BSD3, 2011 Bas van Dijk]+    comonad-4.2.2 [BSD3, Copyright (C) 2008-2014 Edward A. Kmett, Copyright (C) 2004-2008 Dave Menendez]+    conduit-1.2.0.2 [MIT]     containers-0.5.5.1 [BSD3]-    contravariant-0.6 [BSD3, Copyright (C) 2007-2014 Edward A. Kmett]+    contravariant-1.2 [BSD3, Copyright (C) 2007-2014 Edward A. Kmett]     deepseq-1.3.0.2 [BSD3]     directory-1.2.1.0 [BSD3]     distributive-0.4.4 [BSD3, Copyright (C) 2011-2014 Edward A. Kmett]     dlist-0.7.1 [BSD3, 2006-2009 Don Stewart, 2013 Sean Leather]-    either-4.3.0.1 [BSD3, Copyright (C) 2008-2014 Edward A. Kmett]+    either-4.3.1 [BSD3, Copyright (C) 2008-2014 Edward A. Kmett]     errors-1.4.7 [BSD3, 2012, 2013 Gabriel Gonzalez]     exceptions-0.6.1 [BSD3, Copyright (C) 2013-2014 Edward A. Kmett Copyright (C) 2012 Google Inc.]     filepath-1.3.0.2 [BSD3]@@ -450,36 +465,37 @@     hashable-1.2.2.0 [BSD3]     integer-gmp-0.5.1.0 [BSD3]     lifted-base-0.2.3.0 [BSD3, (c) 2011-2012 Bas van Dijk, Anders Kaseorg]-    mmorph-1.0.3 [BSD3, 2013 Gabriel Gonzalez]+    mmorph-1.0.4 [BSD3, 2013 Gabriel Gonzalez]     monad-control-0.3.3.0 [BSD3, (c) 2011 Bas van Dijk, Anders Kaseorg]-    mtl-2.1.3.1 [BSD3]+    mtl-2.2.1 [BSD3]     nats-0.2 [BSD3, Copyright (C) 2011-2014 Edward A. Kmett]     old-locale-1.0.0.6 [BSD3]-    optparse-applicative-0.9.0 [BSD3, (c) 2012 Paolo Capriotti <p.capriotti@gmail.com>]+    optparse-applicative-0.11.0.1 [BSD3, (c) 2012-2014 Paolo Capriotti <paolo@capriotti.io>]     prelude-extras-0.4 [BSD3, Copyright (C) 2011-2014 Edward A. Kmett]     pretty-1.1.1.1 [BSD3]     primitive-0.5.3.0 [BSD3, (c) Roman Leshchinskiy 2009-2012]     process-1.2.0.0 [BSD3]-    profunctors-4.0.4 [BSD3, Copyright (C) 2011-2014 Edward A. Kmett]+    profunctors-4.2.0.1 [BSD3, Copyright (C) 2011-2014 Edward A. Kmett]     random-1.0.1.1 [BSD3]-    resourcet-1.1.2.2 [BSD3]+    resourcet-1.1.2.3 [BSD3]     safe-0.3.6 [BSD3, Neil Mitchell 2007-2014]     scientific-0.3.3.0 [BSD3]-    semigroupoids-4.0.2.1 [BSD3, Copyright (C) 2011-2013 Edward A. Kmett]-    semigroups-0.15.1 [BSD3, Copyright (C) 2011-2014 Edward A. Kmett]+    semigroupoids-4.2 [BSD3, Copyright (C) 2011-2013 Edward A. Kmett]+    semigroups-0.15.3 [BSD3, Copyright (C) 2011-2014 Edward A. Kmett]+    stm-2.4.3 [BSD3]     syb-0.4.2 [BSD3]     tagged-0.7.2 [BSD3, 2009-2013 Edward A. Kmett]     template-haskell-2.9.0.0 [BSD3]     text-1.1.1.3 [BSD3, 2009-2011 Bryan O'Sullivan, 2008-2009 Tom Harper]     time-1.4.2 [BSD3]-    transformers-0.3.0.0 [BSD3]-    transformers-base-0.4.2 [BSD3, 2011 Mikhail Vorozhtsov <mikhail.vorozhtsov@gmail.com>, Bas van Dijk <v.dijk.bas@gmail.com>]+    transformers-0.4.1.0 [BSD3]+    transformers-base-0.4.3 [BSD3, 2011 Mikhail Vorozhtsov <mikhail.vorozhtsov@gmail.com>, Bas van Dijk <v.dijk.bas@gmail.com>]     transformers-compat-0.3.3.4 [BSD3, Copyright (C) 2012 Edward A. Kmett]     unix-2.7.0.1 [BSD3]     unordered-containers-0.2.5.0 [BSD3, 2010-2014 Johan Tibell 2010 Edward Z. Yang]     vector-0.10.11.0 [BSD3, (c) Roman Leshchinskiy 2008-2012]     void-0.6.1 [BSD3, Copyright (C) 2008-2013 Edward A. Kmett]-    yaml-0.8.8.4 [BSD3]+    yaml-0.8.9.1 [BSD3] ~~~  Configuration Types for HTTP Services and Clients@@ -540,3 +556,11 @@  *   Include default values in help message. +*   Use 'helpDoc' to highlight "meta-options", like options that enable+    optional configuration values through usage of the `maybeOption`+    function.++*   Add functionality optparse-applicative that allows to group options.++*   Raise parser error for sub-ordinate "maybe" options when not enabled+    the respective optional value is not enabled.
Setup.hs view
@@ -26,7 +26,7 @@ -- -- = Usage as Setup Script ----- There are two ways how this module can be used:+-- There are three ways how this module can be used: -- -- 1. Copy the code of this module into a file called @Setup.hs@ in the root --    directory of your package.@@ -38,7 +38,18 @@ --    > --    > import Configuration.Utils.Setup ----- With both methods the field @Build-Type@ in the package description (cabal) file+-- 3. For usage within a more complex @Setup.hs@ script you shall import this+--    module qualified and use the 'mkPkgInfoModules' function. For example:+--+--    > module Main (main) where+--    >+--    > import qualified Configuration.Utils.Setup as ConfTools+--    >+--    > main :: IO ()+--    > main = defaultMainWithHooks (ConfTools.mkPkgInfoModules simpleUserHooks)+--    >+--+-- With all methods the field @Build-Type@ in the package description (cabal) file -- must be set to @Custom@: -- -- > Build-Type: Custom@@ -90,7 +101,10 @@ -- [@--license@] --     prints the text of the lincense of the application and exits. ---module Main (main) where+module Main+( main+, mkPkgInfoModules+) where  import Distribution.PackageDescription import Distribution.Simple@@ -116,18 +130,52 @@ import System.Directory (doesFileExist, doesDirectoryExist, createDirectoryIfMissing) import System.Exit (ExitCode(ExitSuccess)) +-- | Include this function when your setup doesn't contain any+-- extra functionality.+-- main :: IO ()-main = defaultMainWithHooks simpleUserHooks-    { postConf = mkPkgInfoModules+main = defaultMainWithHooks (mkPkgInfoModules simpleUserHooks)++-- | Modifies the given record of hooks by adding functionality that+-- creates a package info module for each component of the cabal package.+--+-- This function is intended for usage in more complex @Setup.hs@ scripts.+-- If your setup doesn't contain any other function you can just import+-- the 'main' function from this module.+--+-- The modules are created in the /autogen/ build directory where also the+-- @Path_@ module is created by cabal's simple build setup. This is usually the+-- directory @.\/dist\/build\/autogen@.+--+-- For a library component the module is named just @PkgInfo@. For all other+-- components the module is named @PkgInfo_COMPONENT_NAME@ where+-- @COMPONENT_NAME@ is the name of the component with @-@ characters replaced by+-- @_@.+--+mkPkgInfoModules+    :: UserHooks+    -> UserHooks+mkPkgInfoModules hooks = hooks+    { postConf = mkPkgInfoModulesPostConf (postConf hooks)     }++mkPkgInfoModulesPostConf+    :: (Args -> ConfigFlags -> PackageDescription -> LocalBuildInfo -> IO ())+    -> Args+    -> ConfigFlags+    -> PackageDescription+    -> LocalBuildInfo+    -> IO ()+mkPkgInfoModulesPostConf hook args flags pkgDesc bInfo = do+    mkModules+    hook args flags pkgDesc bInfo   where-    mkPkgInfoModules _ _ pkgDesc bInfo = mapM_ f . map (\(a,_,_) -> a) $ componentsConfigs bInfo-      where-        f cname = case cname of-            CLibName -> updatePkgInfoModule Nothing pkgDesc bInfo-            CExeName s -> updatePkgInfoModule (Just s) pkgDesc bInfo-            CTestName s -> updatePkgInfoModule (Just s) pkgDesc bInfo-            CBenchName s -> updatePkgInfoModule (Just s) pkgDesc bInfo+    mkModules = mapM_ (f . \(a,_,_) -> a) $ componentsConfigs bInfo+    f cname = case cname of+        CLibName -> updatePkgInfoModule Nothing pkgDesc bInfo+        CExeName s -> updatePkgInfoModule (Just s) pkgDesc bInfo+        CTestName s -> updatePkgInfoModule (Just s) pkgDesc bInfo+        CBenchName s -> updatePkgInfoModule (Just s) pkgDesc bInfo  pkgInfoModuleName :: Maybe String -> String pkgInfoModuleName Nothing = "PkgInfo"@@ -144,13 +192,16 @@   where f = reverse . dropWhile isSpace  getVCS :: IO (Maybe RepoType)-getVCS = do+getVCS =     doesDirectoryExist ".hg" >>= \x0 -> if x0     then return (Just Mercurial)-    else doesDirectoryExist ".git" >>= \x1 -> if x1-    then return (Just Git)-    else return Nothing+    else doesDirectoryExist ".git" >>= \x1 -> return $ if x1+        then Just Git+        else Nothing +flagNameStr :: FlagName -> String+flagNameStr (FlagName s) = s+ pkgInfoModule :: Maybe String -> PackageDescription -> LocalBuildInfo -> IO B.ByteString pkgInfoModule cName pkgDesc bInfo = do     (tag, revision, branch) <- getVCS >>= \x -> case x of@@ -160,11 +211,11 @@      let vcsBranch = if branch == "default" || branch == "master" then "" else branch         vcsVersion = intercalate "-" . filter (/= "") $ [tag, revision, vcsBranch]-        flags = map fst . filter snd . configConfigurationsFlags . configFlags $ bInfo+        flags = map (flagNameStr . fst) . filter snd . configConfigurationsFlags . configFlags $ bInfo      licenseString <- licenseFilesText pkgDesc -    return $ B.intercalate "\n" $+    return $ B.intercalate "\n"             [ "{-# LANGUAGE OverloadedStrings #-}"             , "{-# LANGUAGE RankNTypes #-}"             , ""@@ -197,6 +248,9 @@             , "    flags :: IsString a => [a]"             , "    flags = " <> (pack . show) flags             , ""+            , "    optimisation :: IsString a => a"+            , "    optimisation = \"" <> (displayOptimisationLevel . withOptimization) bInfo <> "\""+            , ""             , "    arch :: IsString a => a"             , "    arch = \"" <> (pack . display . hostPlatform) bInfo <> "\""             , ""@@ -244,7 +298,8 @@             , "        <> \"License: \" <> license <> \"\\n\""             , "        <> \"Homepage: \" <> homepage <> \"\\n\""             , "        <> \"Build with: \" <> compiler <> \" (\" <> arch <> \")\" <> \"\\n\""-            , "        <> \"Build flags: \" <> mconcat (map (\\x -> \" \" <> x) flags) <> \"\\n\\n\""+            , "        <> \"Build flags: \" <> mconcat (map (\\x -> \" \" <> x) flags) <> \"\\n\""+            , "        <> \"Optimisation: \" <> optimisation <> \"\\n\\n\""             , "        <> \"Dependencies:\\n\" <> mconcat (map (\\x -> \"    \" <> x <> \"\\n\") dependenciesWithLicenses)"             , ""             , "    pkgInfo :: (Monoid a, IsString a) => (a, a, a, a)"@@ -256,6 +311,10 @@             , "        )"             , ""             ]+  where+    displayOptimisationLevel NoOptimisation = "none"+    displayOptimisationLevel NormalOptimisation = "normal"+    displayOptimisationLevel MaximumOptimisation = "maximum"  updatePkgInfoModule :: Maybe String -> PackageDescription -> LocalBuildInfo -> IO () updatePkgInfoModule cName pkgDesc bInfo = do@@ -281,20 +340,20 @@  hgInfo :: IO (String, String, String) hgInfo = do-    tag <- fmap trim $ readProcess "hg" ["id", "-r", "max(ancestors(\".\") and tag())", "-t"] ""-    rev <- fmap trim $ readProcess "hg" ["id", "-i"] ""-    branch <- fmap trim $ readProcess "hg" ["id", "-b"] ""+    tag <- trim <$> readProcess "hg" ["id", "-r", "max(ancestors(\".\") and tag())", "-t"] ""+    rev <- trim <$> readProcess "hg" ["id", "-i"] ""+    branch <- trim <$> readProcess "hg" ["id", "-b"] ""     return (tag, rev, branch)  gitInfo :: IO (String, String, String) gitInfo = do     tag <- do-        (exitCode, out, _err) <- readProcessWithExitCode "git" ["describe", "--exact-match", "--abbrev=0"] ""+        (exitCode, out, _err) <- readProcessWithExitCode "git" ["describe", "--exact-match", "--tags", "--abbrev=0"] ""         case exitCode of             ExitSuccess -> return $ trim out             _ -> return ""-    rev <- fmap trim $ readProcess "git" ["rev-parse", "--short", "HEAD"] ""-    branch <- fmap trim $ readProcess "git" ["rev-parse", "--abbrev-ref", "HEAD"] ""+    rev <- trim <$> readProcess "git" ["rev-parse", "--short", "HEAD"] ""+    branch <- trim <$> readProcess "git" ["rev-parse", "--abbrev-ref", "HEAD"] ""     return (tag, rev, branch)  noVcsInfo :: IO (String, String, String)
configuration-tools.cabal view
@@ -3,7 +3,7 @@ -- ------------------------------------------------------ --  Name:                configuration-tools-Version:             0.2.5+Version:             0.2.6 Synopsis:            Tools for specifying and parsing configurations description:     Tools for specifying and parsing configurations@@ -54,7 +54,7 @@ source-repository this     type: git     location: https://github.com/alephcloud/hs-configuration-tools.git-    tag: 0.2.5+    tag: 0.2.6  Library     hs-source-dirs: src@@ -76,6 +76,7 @@         base >= 4.6 && < 5.0,         base-unicode-symbols >= 0.2.2.4,         bytestring >= 0.10.0.2,+        case-insensitive >= 1.2,         directory >= 1.2.1.0,         errors >= 1.4.3,         optparse-applicative >= 0.8.1,
constraints view
@@ -1,6 +1,6 @@-constraints: Cabal ==1.20.0.1,-             MonadRandom ==0.1.13,-             aeson ==0.7.0.6,+constraints: Cabal ==1.20.0.2,+             MonadRandom ==0.3,+             aeson ==0.8.0.0,              ansi-terminal ==0.6.1.1,              ansi-wl-pprint ==0.6.7.1,              array ==0.5.0.0,@@ -9,16 +9,17 @@              base-unicode-symbols ==0.2.2.4,              bifunctors ==4.1.1.1,              bytestring ==0.10.4.0,-             comonad ==4.2,-             conduit ==1.1.6,-             configuration-tools ==0.2.5,+             case-insensitive ==1.2.0.0,+             comonad ==4.2.2,+             conduit ==1.2.0.2,+             configuration-tools ==0.2.6,              containers ==0.5.5.1,-             contravariant ==0.6,+             contravariant ==1.2,              deepseq ==1.3.0.2,              directory ==1.2.1.0,              distributive ==0.4.4,              dlist ==0.7.1,-             either ==4.3.0.1,+             either ==4.3.1,              errors ==1.4.7,              exceptions ==0.6.1,              filepath ==1.3.0.2,@@ -27,34 +28,35 @@              hashable ==1.2.2.0,              integer-gmp ==0.5.1.0,              lifted-base ==0.2.3.0,-             mmorph ==1.0.3,+             mmorph ==1.0.4,              monad-control ==0.3.3.0,-             mtl ==2.1.3.1,+             mtl ==2.2.1,              nats ==0.2,              old-locale ==1.0.0.6,-             optparse-applicative ==0.10.0,+             optparse-applicative ==0.11.0.1,              prelude-extras ==0.4,              pretty ==1.1.1.1,              primitive ==0.5.3.0,              process ==1.2.0.0,-             profunctors ==4.0.4,+             profunctors ==4.2.0.1,              random ==1.0.1.1,-             resourcet ==1.1.2.2,+             resourcet ==1.1.2.3,              rts ==1.0,              safe ==0.3.6,              scientific ==0.3.3.0,-             semigroupoids ==4.0.2.1,-             semigroups ==0.15.1,+             semigroupoids ==4.2,+             semigroups ==0.15.3,+             stm ==2.4.3,              syb ==0.4.2,              tagged ==0.7.2,              template-haskell ==2.9.0.0,              text ==1.1.1.3,              time ==1.4.2,-             transformers ==0.3.0.0,-             transformers-base ==0.4.2,+             transformers ==0.4.1.0,+             transformers-base ==0.4.3,              transformers-compat ==0.3.3.4,              unix ==2.7.0.1,              unordered-containers ==0.2.5.0,              vector ==0.10.11.0,              void ==0.6.1,-             yaml ==0.8.8.4+             yaml ==0.8.9.1
src/Configuration/Utils.hs view
@@ -67,12 +67,19 @@ , MParser , (.::) , (%::)+, boolReader+, boolOption+, fileOption+, eitherReadP+, module Options.Applicative  -- * Parsing of Configuration Files with Default Values , setProperty , (..:) , (%.:)+, module Data.Aeson +-- * Command Line Option Parsing -- * Misc Utils , (%) , (×)@@ -87,11 +94,13 @@ , Lens  -- * Configuration of Optional Values--- $maybe --- * Reexports-, module Data.Aeson-, module Options.Applicative+-- * Simple Maybe Values+-- $simplemaybe++-- **  Record Maybe Values+-- $recordmaybe+, maybeOption ) where  import Configuration.Utils.Internal@@ -102,10 +111,12 @@ import Data.Aeson.Types (Parser) import qualified Data.ByteString.Char8 as B8 import Data.Char+import qualified Data.CaseInsensitive as CI import qualified Data.HashMap.Strict as H import Data.Maybe import Data.Monoid import Data.Monoid.Unicode+import Data.String import qualified Data.Text as T import qualified Data.Yaml as Yaml @@ -121,6 +132,8 @@  import System.IO.Unsafe (unsafePerformIO) +import qualified Text.ParserCombinators.ReadP as P+ -- -------------------------------------------------------------------------- -- -- Useful Operators @@ -390,6 +403,54 @@ {-# INLINE (%.:) #-}  -- -------------------------------------------------------------------------- --+-- Command Line Option Parsing++boolReader+    ∷ (Eq a, Show a, CI.FoldCase a, IsString a, IsString e, Monoid e)+    ⇒ a+    → Either e Bool+boolReader x = case CI.mk x of+    "true" → Right True+    "false" → Right False+    _ → Left $ "failed to read Boolean value " <> fromString (show x)+        <> ". Expected either \"true\" or \"false\""++boolOption+    ∷ O.Mod O.OptionFields Bool+    → O.Parser Bool+#if MIN_VERSION_optparse_applicative(0,10,0)+boolOption mods = O.option (O.eitherReader boolReader)+    % O.metavar "TRUE|FALSE"+    <> O.completeWith ["true", "false", "TRUE", "FALSE", "True", "False"]+    <> mods+#else+boolOption mods = O.nullOption+    % metavar "TRUE|FALSE"+    <> O.completeWith ["true", "false", "TRUE", "FALSE", "True", "False"]+    <> O.eitherReader boolReader+    <> mods+#endif++fileOption+    ∷ O.Mod O.OptionFields String+    → O.Parser FilePath+fileOption mods = O.strOption+    % O.metavar "FILE"+    <> O.action "file"+    <> mods++eitherReadP+    ∷ T.Text+    → P.ReadP a+    → T.Text+    → Either T.Text a+eitherReadP label p s =+    case [ x | (x,"") ← P.readP_to_S p (T.unpack s) ] of+        [x] → Right x+        []  → Left $ "eitherReadP: no parse for " <> label <> " of " <> s+        _  → Left $ "eitherReadP: ambigous parse for " <> label <> " of " <> s++-- -------------------------------------------------------------------------- -- -- Main Configuration  data ProgramInfo α = ProgramInfo@@ -653,17 +714,12 @@ -- -------------------------------------------------------------------------- -- -- Configuration of Optional Values --- $maybe+-- $simplemaybe -- Optional configuration values are supposed to be encoded by wrapping -- the respective type with 'Maybe'. -- -- For simple values the standard 'FromJSON' instance from the aeson--- package can be used with the along with  the '..:' operator.------ When defining command line option parsers with '.::' and '%::' all--- options are optional. When an option is not present on the command--- line the default value is used. For 'Maybe' values it is therefore--- enough to wrap the parsed value into 'Just'.+-- package can be used along with the '..:' operator. -- -- > data LogConfig = LogConfig -- >    { _logLevel ∷ !Int@@ -689,6 +745,12 @@ -- >         , "LogConfig" .= _logFile config -- >         ] -- >+--+-- When defining command line option parsers with '.::' and '%::' all+-- options are optional. When an option is not present on the command+-- line the default value is used. For 'Maybe' values it is therefore+-- enough to wrap the parsed value into 'Just'.+-- -- > pLogConfig ∷ MParser LogConfig -- > pLogConfig = id -- > #if MIN_VERSION_optparse-applicative(0,10,0)@@ -704,6 +766,9 @@ -- >         % metavar "FILENAME" -- >         % help "log file name" --++-- $recordmaybe+-- -- For product-type (record) 'Maybe' values the following orphan 'FromJSON' -- instance is provided: --@@ -761,4 +826,95 @@       where         f g _ Nothing = Just g         f _ g (Just x) = Just (g x)++-- | Commandline parser for record 'Maybe' values+--+-- == Example:+--+-- > data Setting = Setting+-- >     { _setA :: !Int+-- >     , _setB :: !String+-- >     }+-- >     deriving (Show, Read, Eq, Ord, Typeable)+-- >+-- > $(makeLenses ''Setting)+-- >+-- > defaultSetting :: Setting+-- > defaultSetting = Setting+-- >     { _setA = 0+-- >     , _setB = 1+-- >     }+-- >+-- > instance ToJSON Setting where+-- >     toJSON setting = object+-- >        [ "a" .= _setA setting+-- >        , "b" .= _setB setting+-- >        ]+-- >+-- > instance FromJSON (Setting -> Setting) where+-- >     parseJSON = withObject "Setting" $ \o -> id+-- >         <$< setA ..: "a" % o+-- >         <*< setB ..: "b" % o+-- >+-- > instance FromJSON Setting where+-- >    parseJSON v = parseJSON v <*> pure defaultSetting+-- >+-- > pSetting :: MParser Setting+-- > pSetting = id+-- >     <$< setA .:: option auto+-- >         % short 'a'+-- >         <> metavar "INT"+-- >         <> help "set a"+-- >     <*< setB .:: option auto+-- >         % short 'b'+-- >         <> metavar "INT"+-- >         <> help "set b"+-- >+-- > -- | Use 'Setting' as 'Maybe' in a configuration:+-- > --+-- > data Config = Config+-- >     { _maybeSetting :: !(Maybe Setting)+-- >     }+-- >     deriving (Show, Read, Eq, Ord, Typeable)+-- >+-- > $(makeLenses ''Config)+-- >+-- > defaultConfig :: Config+-- > defaultConfig = Config+-- >     { _maybeSetting = defaultSetting+-- >     }+-- >+-- > instance ToJSON Config where+-- >     toJSON config = object+-- >         [ "setting" .= maybeSetting+-- >         ]+-- >+-- > instance FromJSON (Config -> Config) where+-- >     parseJSON = withObject "Config" $ \o -> id+-- >         <$< maybeSetting %.: "setting" % o+-- >+-- > pConfig :: MParser Config+-- > pConfig = id+-- >     <$< maybeSetting %:: (maybeOption defaultSetting+-- >         <$> pEnableSetting+-- >         <*> pSetting)+-- >   where+-- >     pEnableSetting = boolOption+-- >         % long "setting-enable"+-- >         <> value False+-- >         <> help "Enable configuration flags for setting"+--+maybeOption+    :: a+        -- ^ default value that is used if base configuration is 'Nothing'+    -> Bool+        -- ^ whether to enable this parser or not (usually is a boolean option parser)+    -> (a -> a)+        -- ^ update function (usually given as applicative 'MParser a')+    -> Maybe a+        -- ^ the base value that is updated (usually the result of parsing the configuraton file)+    -> Maybe a+maybeOption _ False _ Nothing = Nothing -- not enabled+maybeOption defA True update Nothing = Just $ update defA -- disabled in config file but enabled by command line+maybeOption _ _ update (Just val) = Just $ update val -- enabled by config file and possibly by command line 
src/Configuration/Utils/Internal.hs view
@@ -28,24 +28,38 @@  -- | This is the same type as the type from the lens library with the same name. --+-- In case it is already import from the lens package this should be hidden+-- from the import.+-- type Lens σ τ α β = Functor φ ⇒ (α → φ β) → σ → φ τ  -- | This is the same type as the type from the lens library with the same name. --+-- In case it is already import from the lens package this should be hidden+-- from the import.+-- type Lens' σ α = Lens σ σ α α  lens ∷ (σ → α) → (σ → β → τ) → Lens σ τ α β lens getter setter lGetter s = setter s `fmap` lGetter (getter s)+{-# INLINE lens #-}  over ∷ ((α → Identity α) → β → Identity β) → (α → α) → β → β over s f = runIdentity . s (Identity . f)+{-# INLINE over #-}  set ∷ ((α → Identity α) → β → Identity β) → α → β → β set s a = runIdentity . s (const $ Identity a)+{-# INLINE set #-}  -- | This is the same type as the type from the lens library with the same name. --+-- In case it is already import from the lens package this should be hidden+-- from the import.+-- type Iso' β α = (Profunctor π, Functor φ) ⇒ π α (φ α) → π β (φ β)  iso ∷ (β → α) → (α → β) → Iso' β α iso f g = dimap f (fmap g)+{-# INLINE iso #-}+
src/Configuration/Utils/Setup.hs view
@@ -248,6 +248,9 @@             , "    flags :: IsString a => [a]"             , "    flags = " <> (pack . show) flags             , ""+            , "    optimisation :: IsString a => a"+            , "    optimisation = \"" <> (displayOptimisationLevel . withOptimization) bInfo <> "\""+            , ""             , "    arch :: IsString a => a"             , "    arch = \"" <> (pack . display . hostPlatform) bInfo <> "\""             , ""@@ -295,7 +298,8 @@             , "        <> \"License: \" <> license <> \"\\n\""             , "        <> \"Homepage: \" <> homepage <> \"\\n\""             , "        <> \"Build with: \" <> compiler <> \" (\" <> arch <> \")\" <> \"\\n\""-            , "        <> \"Build flags: \" <> mconcat (map (\\x -> \" \" <> x) flags) <> \"\\n\\n\""+            , "        <> \"Build flags: \" <> mconcat (map (\\x -> \" \" <> x) flags) <> \"\\n\""+            , "        <> \"Optimisation: \" <> optimisation <> \"\\n\\n\""             , "        <> \"Dependencies:\\n\" <> mconcat (map (\\x -> \"    \" <> x <> \"\\n\") dependenciesWithLicenses)"             , ""             , "    pkgInfo :: (Monoid a, IsString a) => (a, a, a, a)"@@ -307,6 +311,10 @@             , "        )"             , ""             ]+  where+    displayOptimisationLevel NoOptimisation = "none"+    displayOptimisationLevel NormalOptimisation = "normal"+    displayOptimisationLevel MaximumOptimisation = "maximum"  updatePkgInfoModule :: Maybe String -> PackageDescription -> LocalBuildInfo -> IO () updatePkgInfoModule cName pkgDesc bInfo = do@@ -340,7 +348,7 @@ gitInfo :: IO (String, String, String) gitInfo = do     tag <- do-        (exitCode, out, _err) <- readProcessWithExitCode "git" ["describe", "--exact-match", "--abbrev=0"] ""+        (exitCode, out, _err) <- readProcessWithExitCode "git" ["describe", "--exact-match", "--tags", "--abbrev=0"] ""         case exitCode of             ExitSuccess -> return $ trim out             _ -> return ""