config-value-0.8: Simple, layout-based value language similar to YAML or JSON

Copyright(c) Eric Mertens 2020
LicenseISC
Maintaineremertens@gmail.com
Safe HaskellSafe
LanguageHaskell2010

Config.Macro

Contents

Description

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 there 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 @spilce 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

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).

Constructors

UndeclaredVariable a Text

Variable used before its defintion

UnknownDirective a Text

Unknown directive

BadSplice a

Incorrect use of @splice

BadLoad a

Incorrect use of @load

Instances
Functor MacroError Source # 
Instance details

Defined in Config.Macro

Methods

fmap :: (a -> b) -> MacroError a -> MacroError b #

(<$) :: a -> MacroError b -> MacroError a #

Foldable MacroError Source # 
Instance details

Defined in Config.Macro

Methods

fold :: Monoid m => MacroError m -> m #

foldMap :: Monoid m => (a -> m) -> MacroError a -> m #

foldr :: (a -> b -> b) -> b -> MacroError a -> b #

foldr' :: (a -> b -> b) -> b -> MacroError a -> b #

foldl :: (b -> a -> b) -> b -> MacroError a -> b #

foldl' :: (b -> a -> b) -> b -> MacroError a -> b #

foldr1 :: (a -> a -> a) -> MacroError a -> a #

foldl1 :: (a -> a -> a) -> MacroError a -> a #

toList :: MacroError a -> [a] #

null :: MacroError a -> Bool #

length :: MacroError a -> Int #

elem :: Eq a => a -> MacroError a -> Bool #

maximum :: Ord a => MacroError a -> a #

minimum :: Ord a => MacroError a -> a #

sum :: Num a => MacroError a -> a #

product :: Num a => MacroError a -> a #

Traversable MacroError Source # 
Instance details

Defined in Config.Macro

Methods

traverse :: Applicative f => (a -> f b) -> MacroError a -> f (MacroError b) #

sequenceA :: Applicative f => MacroError (f a) -> f (MacroError a) #

mapM :: Monad m => (a -> m b) -> MacroError a -> m (MacroError b) #

sequence :: Monad m => MacroError (m a) -> m (MacroError a) #

Eq a => Eq (MacroError a) Source # 
Instance details

Defined in Config.Macro

Methods

(==) :: MacroError a -> MacroError a -> Bool #

(/=) :: MacroError a -> MacroError a -> Bool #

Read a => Read (MacroError a) Source # 
Instance details

Defined in Config.Macro

Show a => Show (MacroError a) Source # 
Instance details

Defined in Config.Macro

(Typeable a, Show a) => Exception (MacroError a) Source # 
Instance details

Defined in Config.Macro

expandMacros :: Value a -> Either (MacroError a) (Value a) Source #

Expand macros in a configuration value.

@load not supported and results in a BadLoad error.

expandMacros' Source #

Arguments

:: Monad m 
=> (forall b. MacroError a -> m b)

failure

-> (Value a -> m (Value a))

@load implementation

-> 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

loadFileWithMacros Source #

Arguments

:: (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