Copyright | (c) Eric Mertens 2020 |
---|---|
License | ISC |
Maintainer | emertens@gmail.com |
Safe Haskell | Safe |
Language | Haskell2010 |
This module provides assigns meaning to atoms and section names that start with @
and $
. It provides processing pass for configuration to use local variables and
inclusion to better structure configuration.
Sigils
$
starts a variable.@
starts a directive.
Merge key-value mappings using @splice
.
Load external configuration with @load
.
Variables
Variables are atoms that start with a $
sigil. Variables are defined by
setting a variable as a section name. This variable will remain in
scope for the remainder of the sections being defined.
Variables used in a value position will be replaced with their previously defined values.
$example: 42 field1: $example field2: [0, $example]
expands to
field1: 42 field2: [0, 42]
Later variable definitions will shadow earlier definitions.
{ $x: 1, $x: 2, k: $x }
expands to
{ k: 2 }
Scoping examples:
top1: a: $x -- BAD: $x not defined yet $x: 42 -- $x is now defined to be 42 b: $x -- OK: $x was defined above c: {sub1: $x, sub2: [$x]} -- OK: $x in scope in subsections -- note: $x now goes out of scope top2: $x -- BAD: $x no longer in scope
Macros are expanded at their definition site. All variables are resolved before adding the new variable into the environment. Variables are lexically scoped rather than dynamically scoped.
Allowed:
$x: 1 $y: $x -- OK, y is now 1
Not allowed:
$y: $x -- BAD: $x was not in scope $x: 1 z: $y
Sections splicing
One sections value can be spliced into another sections value using the @splice
directive. It is an error to splice a value that is not a key-value sections.
$xy: { x: 0, y: 1 } example: @splice: $xy z: 2
expands to
example: x: 0 y: 1 z: 2
File loading
The @load
directive is intended including configuration from other sources.
loadFileWithMacros
provides an interpretation of this directive that loads
other files. An arbitrary interpretation can be defined with expandMacros'
To load a value define a key-value mapping with a single @load
key with a
value specifying the location to load from.
x: @load: "fourty-two.cfg"
could expand to
x: 42
Synopsis
- data MacroError a
- = UndeclaredVariable a Text
- | UnknownDirective a Text
- | BadSplice a
- | BadLoad a
- expandMacros :: Value a -> Either (MacroError a) (Value a)
- expandMacros' :: Monad m => (forall b. MacroError a -> m b) -> (Value a -> m (Value a)) -> Map Text (Value a) -> Value a -> m (Value a)
- data LoadFileError
- data FilePosition = FilePosition FilePath Position
- loadFileWithMacros :: (Text -> FilePath -> IO FilePath) -> FilePath -> IO (Value FilePosition)
Macro expansion primitives
data MacroError a Source #
Errors from macro expansion annotated with the valueAnn
from
the Value
nearest to the problem (typically a file position).
UndeclaredVariable a Text | Variable used before its defintion |
UnknownDirective a Text | Unknown directive |
BadSplice a | Incorrect use of |
BadLoad a | Incorrect use of |
Instances
expandMacros :: Value a -> Either (MacroError a) (Value a) Source #
Expand macros in a configuration value.
@load
not supported and results in a BadLoad
error.
:: Monad m | |
=> (forall b. MacroError a -> m b) | failure |
-> (Value a -> m (Value a)) |
|
-> Map Text (Value a) | variable environment |
-> Value a | value to expand |
-> m (Value a) | expanded value |
Expand macros in a configuration value using a pre-populated environment.
File loader with inclusion
data LoadFileError Source #
Errors thrown by loadFileWithMacros
LoadFileParseError FilePath ParseError | failure to parse a file |
LoadFileMacroError (MacroError FilePosition) | failure to expand macros |
Instances
Eq LoadFileError Source # | |
Defined in Config.Macro (==) :: LoadFileError -> LoadFileError -> Bool # (/=) :: LoadFileError -> LoadFileError -> Bool # | |
Read LoadFileError Source # | |
Defined in Config.Macro readsPrec :: Int -> ReadS LoadFileError # readList :: ReadS [LoadFileError] # | |
Show LoadFileError Source # | |
Defined in Config.Macro showsPrec :: Int -> LoadFileError -> ShowS # show :: LoadFileError -> String # showList :: [LoadFileError] -> ShowS # | |
Exception LoadFileError Source # | |
Defined in Config.Macro |
data FilePosition Source #
A pair of filepath and position
Instances
Eq FilePosition Source # | |
Defined in Config.Macro (==) :: FilePosition -> FilePosition -> Bool # (/=) :: FilePosition -> FilePosition -> Bool # | |
Ord FilePosition Source # | |
Defined in Config.Macro compare :: FilePosition -> FilePosition -> Ordering # (<) :: FilePosition -> FilePosition -> Bool # (<=) :: FilePosition -> FilePosition -> Bool # (>) :: FilePosition -> FilePosition -> Bool # (>=) :: FilePosition -> FilePosition -> Bool # max :: FilePosition -> FilePosition -> FilePosition # min :: FilePosition -> FilePosition -> FilePosition # | |
Read FilePosition Source # | |
Defined in Config.Macro readsPrec :: Int -> ReadS FilePosition # readList :: ReadS [FilePosition] # | |
Show FilePosition Source # | |
Defined in Config.Macro showsPrec :: Int -> FilePosition -> ShowS # show :: FilePosition -> String # showList :: [FilePosition] -> ShowS # |
:: (Text -> FilePath -> IO FilePath) | inclusion path resolution |
-> FilePath | starting file path |
-> IO (Value FilePosition) | macro-expanded config value |
Load a configuration value from a given file path.
@load
will compute included file path from the given function given the
load argument and current configuration file path.
Valid @load
arguments are string literals use as arguments to
the path resolution function.
Throws IOError
from file loads and LoadFileError