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 +5/−0
- README.md +5/−5
- env-guard.cabal +1/−1
- src/System/Environment/Guard.hs +103/−21
- src/System/Environment/Guard/Lifted.hs +133/−3
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 @@ [](https://hackage.haskell.org/package/env-guard) [](https://opensource.org/licenses/MIT) -[](https://github.com/tbidne/env-guard/actions/workflows/nix_ci.yaml)-[](https://github.com/tbidne/env-guard/actions/workflows/stack_ci.yaml)+[](https://github.com/tbidne/env-guard/actions/workflows/nix_ci.yaml)+[](https://github.com/tbidne/env-guard/actions/workflows/stack_ci.yaml) [](https://github.com/tbidne/env-guard/actions/workflows/style_ci.yaml) -[](https://github.com/tbidne/env-guard/actions/workflows/ghc_8-10.yaml)-[](https://github.com/tbidne/env-guard/actions/workflows/ghc_9-0.yaml)-[](https://github.com/tbidne/env-guard/actions/workflows/ghc_9-2.yaml)+[](https://github.com/tbidne/env-guard/actions/workflows/ghc_8-10.yaml)+[](https://github.com/tbidne/env-guard/actions/workflows/ghc_9-0.yaml)+[](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 --