packages feed

env-guard 0.1 → 0.1.1

raw patch · 5 files changed

+247/−30 lines, 5 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ System.Environment.Guard: ExpectEnvEquals :: String -> ExpectEnv
+ System.Environment.Guard: ExpectEnvPredicate :: (String -> Bool) -> ExpectEnv
+ System.Environment.Guard: ExpectEnvSet :: ExpectEnv
+ System.Environment.Guard: data ExpectEnv
+ System.Environment.Guard: guardOrElse :: String -> ExpectEnv -> IO a -> IO e -> IO (Either e a)
+ System.Environment.Guard: guardOrElse' :: String -> ExpectEnv -> IO a -> IO a -> IO a
+ System.Environment.Guard: withGuard :: String -> ExpectEnv -> IO a -> IO (Maybe a)
+ System.Environment.Guard: withGuard_ :: String -> ExpectEnv -> IO a -> IO ()
+ System.Environment.Guard.Lifted: ExpectEnvEquals :: String -> ExpectEnv
+ System.Environment.Guard.Lifted: ExpectEnvPredicate :: (String -> Bool) -> ExpectEnv
+ System.Environment.Guard.Lifted: ExpectEnvSet :: ExpectEnv
+ System.Environment.Guard.Lifted: data ExpectEnv
+ System.Environment.Guard.Lifted: guardOrElse :: MonadIO m => String -> ExpectEnv -> m a -> m e -> m (Either e a)
+ System.Environment.Guard.Lifted: guardOrElse' :: MonadIO m => String -> ExpectEnv -> m a -> m a -> m a
+ System.Environment.Guard.Lifted: instance GHC.Show.Show System.Environment.Guard.Lifted.ExpectEnv
+ System.Environment.Guard.Lifted: withGuard :: MonadIO m => String -> ExpectEnv -> m a -> m (Maybe a)
+ System.Environment.Guard.Lifted: withGuard_ :: MonadIO m => String -> ExpectEnv -> m a -> m ()

Files

CHANGELOG.md view
@@ -1,5 +1,10 @@ # Revision history for env-guard +## 0.1.1 -- 2022-07-01++* Add higher-level `withGuard` combinator.+* Add "OrElse" pattern.+ ## 0.1 -- 2022-06-29  * First version. Released on an unsuspecting world.
README.md view
@@ -5,12 +5,12 @@ [![Hackage](https://img.shields.io/hackage/v/env-guard)](https://hackage.haskell.org/package/env-guard) [![MIT](https://img.shields.io/github/license/tbidne/env-guard?color=blue)](https://opensource.org/licenses/MIT) -[![nix](https://img.shields.io/github/workflow/status/tbidne/env-guard/nix/main?label=nix%209.2.3&&logo=nixos&logoColor=85c5e7&labelColor=2f353c)](https://github.com/tbidne/env-guard/actions/workflows/nix_ci.yaml)-[![stack](https://img.shields.io/github/workflow/status/tbidne/env-guard/stack/main?label=stack%2019.4&logoColor=white&labelColor=2f353c)](https://github.com/tbidne/env-guard/actions/workflows/stack_ci.yaml)+[![nix](https://img.shields.io/github/workflow/status/tbidne/env-guard/nix/main?label=nix%209.2&&logo=nixos&logoColor=85c5e7&labelColor=2f353c)](https://github.com/tbidne/env-guard/actions/workflows/nix_ci.yaml)+[![stack](https://img.shields.io/github/workflow/status/tbidne/env-guard/stack/main?label=stack%2019&logoColor=white&labelColor=2f353c)](https://github.com/tbidne/env-guard/actions/workflows/stack_ci.yaml) [![style](https://img.shields.io/github/workflow/status/tbidne/env-guard/style/main?label=style&logoColor=white&labelColor=2f353c)](https://github.com/tbidne/env-guard/actions/workflows/style_ci.yaml) -[![8.10.7](https://img.shields.io/github/workflow/status/tbidne/env-guard/8.10.7/main?label=8.10.7&logo=haskell&logoColor=904d8c&labelColor=2f353c)](https://github.com/tbidne/env-guard/actions/workflows/ghc_8-10.yaml)-[![9.0.2](https://img.shields.io/github/workflow/status/tbidne/env-guard/9.0.2/main?label=9.0.2&logo=haskell&logoColor=904d8c&labelColor=2f353c)](https://github.com/tbidne/env-guard/actions/workflows/ghc_9-0.yaml)-[![9.2.3](https://img.shields.io/github/workflow/status/tbidne/env-guard/9.2.3/main?label=9.2.3&logo=haskell&logoColor=904d8c&labelColor=2f353c)](https://github.com/tbidne/env-guard/actions/workflows/ghc_9-2.yaml)+[![8.10](https://img.shields.io/github/workflow/status/tbidne/env-guard/8.10/main?label=8.10&logo=haskell&logoColor=904d8c&labelColor=2f353c)](https://github.com/tbidne/env-guard/actions/workflows/ghc_8-10.yaml)+[![9.0](https://img.shields.io/github/workflow/status/tbidne/env-guard/9.0/main?label=9.0&logo=haskell&logoColor=904d8c&labelColor=2f353c)](https://github.com/tbidne/env-guard/actions/workflows/ghc_9-0.yaml)+[![9.2](https://img.shields.io/github/workflow/status/tbidne/env-guard/9.2/main?label=9.2&logo=haskell&logoColor=904d8c&labelColor=2f353c)](https://github.com/tbidne/env-guard/actions/workflows/ghc_9-2.yaml)  </div>
env-guard.cabal view
@@ -1,6 +1,6 @@ cabal-version:      2.4 name:               env-guard-version:            0.1+version:            0.1.1 license:            MIT license-file:       LICENSE tested-with:        GHC ==8.10.7 || ==9.0.2 || ==9.2.3
src/System/Environment/Guard.hs view
@@ -1,32 +1,121 @@-{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE ImportQualifiedPost #-}  -- | Functions for conditionally running 'IO' actions based on an environment -- variable. -- -- @since 0.1 module System.Environment.Guard-  ( -- * Checking environment variable is set+  ( -- * High level combinators+    ExpectEnv (..),+    withGuard,+    withGuard_,+    guardOrElse,+    guardOrElse',++    -- * Low level functions++    -- ** Checking environment variable is set     guardSet,     guardSet_, -    -- * Checking environment variable match+    -- ** Checking environment variable match     guardExpected,     guardExpected_, -    -- * Checking environment variable predicate+    -- ** Checking environment variable predicate     guardPredicate,     guardPredicate_,   ) where -import Control.Monad (void)-import Data.Char (toLower)-import System.Environment (lookupEnv)+import System.Environment.Guard.Lifted (ExpectEnv)+import System.Environment.Guard.Lifted qualified as Lifted  -- $setup+-- >>> import Control.Monad (void) -- >>> import Data.Functor (($>)) -- >>> import System.Environment (setEnv)+-- >>> import System.Environment.Guard.Lifted (ExpectEnv (..)) +-- | Guards an action behind an environment variable according to+-- the given expectation.+--+-- ==== __Examples__+-- >>> setEnv "FOO" "bar"+-- >>> withGuard "FOO" (ExpectEnvEquals "baz") (putStrLn "succeeded")+-- Nothing+--+-- >>> withGuard "FOO" ExpectEnvSet (putStrLn "succeeded")+-- succeeded+-- Just ()+--+-- @since 0.1.1+withGuard :: String -> ExpectEnv -> IO a -> IO (Maybe a)+withGuard = Lifted.withGuard++-- | Variant of 'withGuard' that ignores the return value.+--+-- @since 0.1.1+withGuard_ :: String -> ExpectEnv -> IO a -> IO ()+withGuard_ = Lifted.withGuard_++-- | @guardOrElse var expect io1 io2@ is equivalent to+-- @withGuard var expect io1@ except that it runs @io2@ if @io1@ is not run.+--+-- ==== __Examples__+-- >>> setEnv "FOO" "bar"+-- >>> guardOrElse "FOO" ExpectEnvSet (pure True) (pure "not found")+-- Right True+--+-- >>> guardOrElse "BAR" ExpectEnvSet (pure True) (pure "not found")+-- Left "not found"+--+-- @since 0.1.1+guardOrElse ::+  -- | The environment variable.+  String ->+  -- | The expectation.+  ExpectEnv ->+  -- | The action to run if the expectation succeeds.+  IO a ->+  -- | The action to run if the expectation fails.+  IO e ->+  -- | The result.+  IO (Either e a)+guardOrElse = Lifted.guardOrElse++-- | 'guardOrElse' specialized to the same type so that we always return an+-- @a@. This can also be used to ignore the return value i.e.+--+-- @+-- guardOrElse' var expect (void io1) io2+-- @+--+-- ==== __Examples__+-- >>> setEnv "FOO" "bar"+-- >>> guardOrElse' "FOO" ExpectEnvSet (pure True) (pure False)+-- True+--+-- >>> guardOrElse' "BAR" ExpectEnvSet (pure True) (pure False)+-- False+--+-- >>> guardOrElse' "BAR" ExpectEnvSet (void $ pure True) (putStrLn "not found")+-- not found+--+-- @since 0.1.1+guardOrElse' ::+  -- | The environment variable.+  String ->+  -- | The expectation.+  ExpectEnv ->+  -- | The action to run if the expectation succeeds.+  IO a ->+  -- | The action to run if the expectation fails.+  IO a ->+  -- | The result.+  IO a+guardOrElse' = Lifted.guardOrElse'+ -- | @'guardSet' var io@ runs @io@ iff -- -- 1. The environment variable @var@ is set.@@ -47,13 +136,13 @@ -- -- @since 0.1 guardSet :: String -> IO a -> IO (Maybe a)-guardSet var = guardPredicate var (const True)+guardSet = Lifted.guardSet  -- | Variant of 'guardSet' that ignores the return value. -- -- @since 0.1 guardSet_ :: String -> IO a -> IO ()-guardSet_ var = void . guardSet var+guardSet_ = Lifted.guardSet_  -- | @'guardExpected' var expected io@ runs @io@ iff --@@ -61,7 +150,7 @@ -- 2. @var@'s value equals @expected@. This is __case-insensitive__. -- -- @--- 'guardExpected' var expected === 'guardPredicate' var (\\a b -> 'fmap' 'toLower' a == 'fmap' 'toLower' b)+-- 'guardExpected' var expected === 'guardPredicate' var (\\a b -> 'fmap' 'Data.Char.toLower' a == 'fmap' 'Data.Char.toLower' b) -- @ -- -- ==== __Examples__@@ -80,19 +169,19 @@ -- -- @since 0.1 guardExpected :: String -> String -> IO a -> IO (Maybe a)-guardExpected var expected = guardPredicate var (eqCaseInsensitive expected)+guardExpected = Lifted.guardExpected  -- | Variant of 'guardExpected_' that ignores the return value. -- -- @since 0.1 guardExpected_ :: String -> String -> IO a -> IO ()-guardExpected_ var expected = void . guardExpected var expected+guardExpected_ = Lifted.guardExpected_  -- | Variant of 'guardPredicate' that ignores the return value. -- -- @since 0.1 guardPredicate_ :: String -> (String -> Bool) -> IO a -> IO ()-guardPredicate_ var p = void . guardPredicate var p+guardPredicate_ = Lifted.guardPredicate_  -- | This is the most general way to check an environment variable. -- @'guardPredicate' var p io@ runs @io@ iff@@ -116,11 +205,4 @@ -- -- @since 0.1 guardPredicate :: String -> (String -> Bool) -> IO a -> IO (Maybe a)-guardPredicate var p io =-  lookupEnv var-    >>= \case-      Just result | p result -> Just <$> io-      _ -> pure Nothing--eqCaseInsensitive :: String -> String -> Bool-eqCaseInsensitive a b = fmap toLower a == fmap toLower b+guardPredicate = Lifted.guardPredicate
src/System/Environment/Guard/Lifted.hs view
@@ -4,15 +4,24 @@ -- -- @since 0.1 module System.Environment.Guard.Lifted-  ( -- * Checking environment variable is set+  ( -- * High level combinators+    ExpectEnv (..),+    withGuard,+    withGuard_,+    guardOrElse,+    guardOrElse',++    -- * Low level functions++    -- ** Checking environment variable is set     guardSet,     guardSet_, -    -- * Checking environment variable match+    -- ** Checking environment variable match     guardExpected,     guardExpected_, -    -- * Checking environment variable predicate+    -- ** Checking environment variable predicate     guardPredicate,     guardPredicate_,   )@@ -26,6 +35,127 @@ -- $setup -- >>> import Data.Functor (($>)) -- >>> import System.Environment (setEnv)++-- | The expectation for an environment variable lookup.+--+-- @since 0.1.1+data ExpectEnv+  = -- | Expect that the environment variable is set+    -- (i.e. contents can be anything).+    --+    -- @since 0.1.1+    ExpectEnvSet+  | -- | Expect that the environment variable is set and the contents equals+    -- the string. This is __case-insensitive__.+    --+    -- @since 0.1.1+    ExpectEnvEquals String+  | -- | Expect that the environment variable is set and its contents+    -- satisfies the predicate.+    --+    -- @since 0.1.1+    ExpectEnvPredicate (String -> Bool)++-- | @since 0.1.1+instance Show ExpectEnv where+  showsPrec _ ExpectEnvSet = showString "ExpectEnvSet"+  showsPrec i (ExpectEnvEquals s) =+    showParen+      (i >= 11)+      (showString "ExpectEnvEquals " . showsPrec 11 s)+  showsPrec i (ExpectEnvPredicate _) =+    showParen+      (i >= 11)+      (showString "ExpectEnvEquals " . showString "_")++-- | Guards an action behind an environment variable according to+-- the given expectation.+--+-- ==== __Examples__+-- >>> setEnv "FOO" "bar"+-- >>> withGuard "FOO" (ExpectEnvEquals "baz") (putStrLn "succeeded")+-- Nothing+--+-- >>> withGuard "FOO" ExpectEnvSet (putStrLn "succeeded")+-- succeeded+-- Just ()+--+-- @since 0.1.1+withGuard :: MonadIO m => String -> ExpectEnv -> m a -> m (Maybe a)+withGuard var expect m =+  case expect of+    ExpectEnvSet -> guardSet var m+    ExpectEnvEquals str -> guardExpected var str m+    ExpectEnvPredicate p -> guardPredicate var p m++-- | Variant of 'withGuard' that ignores the return value.+--+-- @since 0.1.1+withGuard_ :: MonadIO m => String -> ExpectEnv -> m a -> m ()+withGuard_ var expect = void . withGuard var expect++-- | @guardOrElse var expect m1 m2@ is equivalent to+-- @withGuard var expect m1@ except that it runs @m2@ if @m1@ is not run.+--+-- ==== __Examples__+-- >>> setEnv "FOO" "bar"+-- >>> guardOrElse "FOO" ExpectEnvSet (pure True) (pure "not found")+-- Right True+--+-- >>> guardOrElse "BAR" ExpectEnvSet (pure True) (pure "not found")+-- Left "not found"+--+-- @since 0.1.1+guardOrElse ::+  MonadIO m =>+  -- | The environment variable.+  String ->+  -- | The expectation.+  ExpectEnv ->+  -- | The action to run if the expectation succeeds.+  m a ->+  -- | The action to run if the expectation fails.+  m e ->+  -- | The result.+  m (Either e a)+guardOrElse var expect m1 m2 =+  withGuard var expect m1+    >>= \case+      Just x -> pure $ Right x+      Nothing -> Left <$> m2++-- | 'guardOrElse' specialized to the same type so that we always return an+-- @a@. This can also be used to ignore the return value i.e.+--+-- @+-- guardOrElse' var expect (void m1) m2+-- @+--+-- ==== __Examples__+-- >>> setEnv "FOO" "bar"+-- >>> guardOrElse' "FOO" ExpectEnvSet (pure True) (pure False)+-- True+--+-- >>> guardOrElse' "BAR" ExpectEnvSet (pure True) (pure False)+-- False+--+-- >>> guardOrElse' "BAR" ExpectEnvSet (void $ pure True) (putStrLn "not found")+-- not found+--+-- @since 0.1.1+guardOrElse' ::+  MonadIO m =>+  -- | The environment variable.+  String ->+  -- | The expectation.+  ExpectEnv ->+  -- | The action to run if the expectation succeeds.+  m a ->+  -- | The action to run if the expectation fails.+  m a ->+  -- | The result.+  m a+guardOrElse' var expect m = fmap (either id id) . guardOrElse var expect m  -- | @'guardSet' var io@ runs @io@ iff --