Safe Haskell | Safe-Inferred |
---|---|
Language | Haskell2010 |
Parse the shell environment for configuration
A minor extension of envparse.
Usage:
import Freckle.App.Env data Config = Config -- Example { cBatchSize :: Natural , cDryRun :: Bool , cLogLevel :: LogLevel } loadConfig :: IO Config loadConfig = parse $ Config <$> var auto "BATCH_SIZE" (def 1) <*> switch "DRY_RUN" mempty <*> flag (Off LevelInfo) (On LevelDebug) "DEBUG" mempty
Synopsis
- (<>) :: Semigroup a => a -> a -> a
- (<=<) :: Monad m => (b -> m c) -> (a -> m b) -> a -> m c
- (>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c
- optional :: Alternative f => f a -> f (Maybe a)
- asum :: (Foldable t, Alternative f) => t (f a) -> f a
- parseOr :: AsUnset e => (String -> IO a) -> (Info Error -> Info e) -> Parser e b -> IO (Either a b)
- parse :: AsUnset e => (Info Error -> Info e) -> Parser e a -> IO a
- defaultErrorHandler :: (AsUnset e, AsEmpty e, AsUnread e) => ErrorHandler e
- handleError :: ErrorHandler e -> Info x -> Info e
- footer :: String -> Info e -> Info e
- desc :: String -> Info e -> Info e
- header :: String -> Info e -> Info e
- helpDoc :: Parser e a -> String
- data Info e
- type ErrorHandler e = String -> e -> Maybe String
- help :: forall (t :: Type -> Type) a. HasHelp t => String -> Mod t a
- helpDef :: (a -> String) -> Mod Var a
- def :: a -> Mod Var a
- splitOn :: Char -> Reader e [String]
- char :: AsUnread e => Reader e Char
- auto :: (AsUnread e, Read a) => Reader e a
- nonempty :: (AsEmpty e, IsString s) => Reader e s
- str :: IsString s => Reader e s
- switch :: String -> Mod Flag Bool -> Parser e Bool
- var :: AsUnset e => Reader e a -> String -> Mod Var a -> Parser e a
- sensitive :: Parser e a -> Parser e a
- prefixed :: String -> Parser e a -> Parser e a
- parsePure :: AsUnset e => Parser e a -> [(String, String)] -> Either [(String, e)] a
- data Parser e a
- type Reader e a = String -> Either e a
- data Mod (t :: Type -> Type) a
- data Var a
- data Flag a
- class HasHelp (t :: Type -> Type)
- data Error
- class AsUnset e where
- class AsEmpty e where
- class AsUnread e where
- newtype Off a = Off a
- newtype On a = On a
- flag :: Off a -> On a -> String -> Mod Flag a -> Parser Error a
- kept :: Parser e a -> Parser e a
- eitherReader :: (String -> Either String a) -> Reader Error a
- time :: String -> Reader Error UTCTime
- keyValues :: Reader Error [(Text, Text)]
Documentation
(<>) :: Semigroup a => a -> a -> a infixr 6 #
An associative operation.
>>>
[1,2,3] <> [4,5,6]
[1,2,3,4,5,6]
(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c infixr 1 #
Left-to-right composition of Kleisli arrows.
'(bs
' can be understood as the >=>
cs) ado
expression
do b <- bs a cs b
optional :: Alternative f => f a -> f (Maybe a) #
One or none.
It is useful for modelling any computation that is allowed to fail.
Examples
Using the Alternative
instance of Control.Monad.Except, the following functions:
>>>
import Control.Monad.Except
>>>
canFail = throwError "it failed" :: Except String Int
>>>
final = return 42 :: Except String Int
Can be combined by allowing the first function to fail:
>>>
runExcept $ canFail *> final
Left "it failed">>>
runExcept $ optional canFail *> final
Right 42
asum :: (Foldable t, Alternative f) => t (f a) -> f a #
The sum of a collection of actions, generalizing concat
.
asum
is just like msum
, but generalised to Alternative
.
Examples
Basic usage:
>>>
asum [Just "Hello", Nothing, Just "World"]
Just "Hello"
parseOr :: AsUnset e => (String -> IO a) -> (Info Error -> Info e) -> Parser e b -> IO (Either a b) #
Try to parse the environment
Use this if simply dying on failure (the behavior of parse
) is inadequate for your needs.
defaultErrorHandler :: (AsUnset e, AsEmpty e, AsUnread e) => ErrorHandler e #
The default error handler
handleError :: ErrorHandler e -> Info x -> Info e #
An error handler
header :: String -> Info e -> Info e #
Set the help text header (it usually includes the application's name and version)
helpDoc :: Parser e a -> String #
A pretty-printed list of recognized environment variables suitable for usage messages
type ErrorHandler e = String -> e -> Maybe String #
Given a variable name and an error value, try to produce a useful error message
help :: forall (t :: Type -> Type) a. HasHelp t => String -> Mod t a #
Attach help text to the variable
The default value of the variable
Note: specifying it means the parser won't ever fail.
splitOn :: Char -> Reader e [String] #
The reader that splits a string into a list of strings consuming the separator.
switch :: String -> Mod Flag Bool -> Parser e Bool #
A simple boolean flag
Note: this parser never fails.
sensitive :: Parser e a -> Parser e a #
Mark the enclosed variables as sensitive to remove them from the environment once they've been parsed successfully.
prefixed :: String -> Parser e a -> Parser e a #
The string to prepend to the name of every declared environment variable
parsePure :: AsUnset e => Parser e a -> [(String, String)] -> Either [(String, e)] a #
Try to parse a pure environment
An environment parser
Instances
Alternative (Parser e) | |
Applicative (Parser e) | |
Functor (Parser e) | |
type Reader e a = String -> Either e a #
An environment variable's value parser. Use (<=<)
and (>=>)
to combine these
data Mod (t :: Type -> Type) a #
This represents a modification of the properties of a particular Parser
.
Combine them using the Monoid
instance.
Environment variable metadata
Flag metadata
class HasHelp (t :: Type -> Type) #
A class of things that can have a help message attached to them
setHelp
The type of errors returned by envparse
's Reader
s. These fall into 3
categories:
- Variables that are unset in the environment.
- Variables whose value is empty.
- Variables whose value cannot be parsed.
The class of types that contain and can be constructed from the error returned from parsing unset variables.
The class of types that contain and can be constructed from the error returned from parsing variables whose value is empty.
The class of types that contain and can be constructed from the error returned from parsing variable whose value cannot be parsed.
Replacements
flag :: Off a -> On a -> String -> Mod Flag a -> Parser Error a Source #
Parse a simple flag
If the variable is present and non-empty in the environment, the active value is returned, otherwise the default is used.
>>>
import Blammo.Logging (LogLevel(..))
>>>
flag (Off LevelInfo) (On LevelDebug) "DEBUG" mempty `parsePure` [("DEBUG", "1")]
Right LevelDebug
>>>
flag (Off LevelInfo) (On LevelDebug) "DEBUG" mempty `parsePure` [("DEBUG", "")]
Right LevelInfo
>>>
flag (Off LevelInfo) (On LevelDebug) "DEBUG" mempty `parsePure` []
Right LevelInfo
N.B. only the empty string is falsey:
>>>
flag (Off LevelInfo) (On LevelDebug) "DEBUG" mempty `parsePure` [("DEBUG", "false")]
Right LevelDebug
>>>
flag (Off LevelInfo) (On LevelDebug) "DEBUG" mempty `parsePure` [("DEBUG", "no")]
Right LevelDebug
Extensions
kept :: Parser e a -> Parser e a Source #
Modify a Parser
so variables are never removed after reading
In envparse-0.4
, read variables are removed from the environment by
default. This is often problematic (e.g. in tests that repeatedly load an app
and re-read the environment), and the security benefits are minor. This
function will make them all behave as if keep
was used.
In envparse-0.5
, the default is reversed and sensitive
can be used to
explicitly unset read variables, and so this function will instead make them
all behave as if sensitive
was not used.
time :: String -> Reader Error UTCTime Source #
Read a time value using the given format
>>>
var (time "%Y-%m-%d") "TIME" mempty `parsePure` [("TIME", "1985-02-12")]
Right 1985-02-12 00:00:00 UTC
>>>
var (time "%Y-%m-%d") "TIME" mempty `parsePure` [("TIME", "10:00PM")]
Left [("TIME",UnreadError "unable to parse time as %Y-%m-%d: \"10:00PM\"")]
keyValues :: Reader Error [(Text, Text)] Source #
Read key-value pairs
>>>
var keyValues "TAGS" mempty `parsePure` [("TAGS", "foo:bar,baz:bat")]
Right [("foo","bar"),("baz","bat")]
Value-less keys are not supported:
>>>
var keyValues "TAGS" mempty `parsePure` [("TAGS", "foo,baz:bat")]
Left [("TAGS",UnreadError "Key foo has no value: \"foo,baz:bat\"")]
Nor are key-less values:
>>>
var keyValues "TAGS" mempty `parsePure` [("TAGS", "foo:bar,:bat")]
Left [("TAGS",UnreadError "Value bat has no key: \"foo:bar,:bat\"")]