configurator-0.3.0.0: Configuration management

Portabilityportable
Stabilityexperimental
MaintainerBryan O'Sullivan <bos@serpentine.com>
Safe HaskellNone

Data.Configurator

Contents

Description

A simple (yet powerful) library for working with configuration files.

Synopsis

Configuration file format

A configuration file consists of a series of directives and comments, encoded in UTF-8. A comment begins with a "#" character, and continues to the end of a line.

Files and directives are processed from first to last, top to bottom.

Binding a name to a value

A binding associates a name with a value.

 my_string = "hi mom! \u2603"
 your-int-33 = 33
 his_bool = on
 HerList = [1, "foo", off]

A name must begin with a Unicode letter, which is followed by zero or more of a Unicode alphanumeric code point, hyphen "-", or underscore "_".

Bindings are created or overwritten in the order in which they are encountered. It is legitimate for a name to be bound multiple times, in which case the last value wins.

 a = 1
 a = true
 # value of a is now true, not 1

Value types

The configuration file format supports the following data types:

  • Booleans, represented as on or off, true or false. These are case sensitive, so do not try to use True instead of true!
  • Integers, represented in base 10.
  • Unicode strings, represented as text (possibly containing escape sequences) surrounded by double quotes.
  • Heterogeneous lists of values, represented as an opening square bracket "[", followed by a series of comma-separated values, ending with a closing square bracket "]".

The following escape sequences are recognised in a text string:

  • \n - newline
  • \r - carriage return
  • \t - horizontal tab
  • \\ - backslash
  • \" - double quote
  • \uxxxx - Unicode character from the basic multilingual plane, encoded as four hexadecimal digits
  • \uxxxx\uxxxx - Unicode character from an astral plane, as two hexadecimal-encoded UTF-16 surrogates

String interpolation

Strings support interpolation, so that you can dynamically construct a string based on data in your configuration or the OS environment.

If a string value contains the special sequence "$(foo)" (for any name foo), then the name foo will be looked up in the configuration data and its value substituted. If that name cannot be found, it will be looked up in the OS environment.

For security reasons, it is an error for a string interpolation fragment to contain a name that cannot be found in either the current configuration or the environment.

To represent a single literal "$" character in a string, double it: "$$".

Grouping directives

It is possible to group a number of directives together under a single prefix:

 my-group
 {
   a = 1

   # groups support nesting
   nested {
     b = "yay!"
   }
 }

The name of a group is used as a prefix for the items in the group. For instance, the value of "a" above can be retrieved using lookup by supplying the name "my-group.a", and "b" will be named "my-group.nested.b".

Importing files

To import the contents of another configuration file, use the import directive.

 import "$(HOME)/etc/myapp.cfg"

Absolute paths are imported as is. Relative paths are resolved with respect to the file they are imported from. It is an error for an import directive to name a file that does not exist, cannot be read, or contains errors.

If an import appears inside a group, the group's naming prefix will be applied to all of the names imported from the given configuration file.

Supposing we have a file named "foo.cfg":

 bar = 1

And another file that imports it into a group:

 hi {
   import "foo.cfg"
 }

This will result in a value named "hi.bar".

Types

data Worth a Source

Constructors

Required 

Fields

worth :: a
 
Optional 

Fields

worth :: a
 

Instances

Loading configuration data

autoReloadSource

Arguments

:: AutoConfig

Directions for when to reload and how to handle errors.

-> [Worth FilePath]

Configuration files to load.

-> IO (Config, ThreadId) 

Load a Config from the given FilePaths, and start a reload thread.

At intervals, a thread checks for modifications to both the original files and any files they refer to in import directives, and reloads the Config if any files have been modified.

If the initial attempt to load the configuration files fails, an exception is thrown. If the initial load succeeds, but a subsequent attempt fails, the onError handler is invoked.

File names have any environment variables expanded prior to the first time they are opened, so you can specify a file name such as "$(HOME)/myapp.cfg".

autoConfig :: AutoConfigSource

Defaults for automatic Config reloading when using autoReload. The interval is one second, while the onError action ignores its argument and does nothing.

empty :: ConfigSource

A completely empty configuration.

Lookup functions

lookup :: Configured a => Config -> Name -> IO (Maybe a)Source

Look up a name in the given Config. If a binding exists, and the value can be converted to the desired type, return the converted value, otherwise Nothing.

lookupDefaultSource

Arguments

:: Configured a 
=> a

Default value to return if lookup or convert fails.

-> Config 
-> Name 
-> IO a 

Look up a name in the given Config. If a binding exists, and the value can be converted to the desired type, return it, otherwise return the default value.

require :: Configured a => Config -> Name -> IO aSource

Look up a name in the given Config. If a binding exists, and the value can be converted to the desired type, return the converted value, otherwise throw a KeyError.

Notification of configuration changes

To more efficiently support an application's need to dynamically reconfigure, a subsystem may ask to be notified when a configuration property is changed as a result of a reload, using the subscribe action.

prefix :: Text -> PatternSource

A pattern that matches on a prefix of a property name. Given "foo", this will match "foo.bar", but not "foo" or "foobar".

exact :: Text -> PatternSource

A pattern that must match exactly.

subscribe :: Config -> Pattern -> ChangeHandler -> IO ()Source

Subscribe for notifications. The given action will be invoked when any change occurs to a configuration property matching the supplied pattern.

Low-level loading functions

load :: [Worth FilePath] -> IO ConfigSource

Create a Config from the contents of the named files. Throws an exception on error, such as if files do not exist or contain errors.

File names have any environment variables expanded prior to the first time they are opened, so you can specify a file name such as "$(HOME)/myapp.cfg".

loadGroups :: [(Name, Worth FilePath)] -> IO ConfigSource

Create a Config from the contents of the named files, placing them into named prefixes. If a prefix is non-empty, it should end in a dot.

reload :: Config -> IO ()Source

Forcibly reload a Config. Throws an exception on error, such as if files no longer exist or contain errors. If the provided Config is a subconfig, this will reload the entire top-level configuration, not just the local section.

subconfig :: Name -> Config -> ConfigSource

Gives a Config corresponding to just a single group of the original Config. The subconfig can be used just like the original Config, but see the documentation for reload.

addToConfig :: [Worth FilePath] -> Config -> IO ()Source

Add additional files to a Config, causing it to be reloaded to add their contents.

addGroupsToConfig :: [(Name, Worth FilePath)] -> Config -> IO ()Source

Add additional files to named groups in a Config, causing it to be reloaded to add their contents. If the prefixes are non-empty, they should end in dots.

Helper functions

display :: Config -> IO ()Source

Perform a simple dump of a Config to stdout.

getMap :: Config -> IO (HashMap Name Value)Source

Fetch the HashMap that maps names to values.