169 changes: 119 additions & 50 deletions doc/econfig.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@


#Module econfig#
# Module econfig #
* [Description](#description)
* [Function Index](#index)
* [Function Details](#functions)
Expand All @@ -10,77 +10,119 @@ Public API of econfig.

<a name="index"></a>

##Function Index##
## Function Index ##


<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#all-1">all/1</a></td><td>get all values of a configuration.</td></tr><tr><td valign="top"><a href="#delete_value-3">delete_value/3</a></td><td>delete a value.</td></tr><tr><td valign="top"><a href="#delete_value-4">delete_value/4</a></td><td>delete a value.</td></tr><tr><td valign="top"><a href="#get_value-2">get_value/2</a></td><td>get values of a section.</td></tr><tr><td valign="top"><a href="#get_value-3">get_value/3</a></td><td>get value for a key in a section.</td></tr><tr><td valign="top"><a href="#get_value-4">get_value/4</a></td><td></td></tr><tr><td valign="top"><a href="#register_config-2">register_config/2</a></td><td>register inifiles or config dirs.</td></tr><tr><td valign="top"><a href="#register_config-3">register_config/3</a></td><td>register inifiles of config dirs with options
<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#all-1">all/1</a></td><td>get all values of a configuration.</td></tr><tr><td valign="top"><a href="#cfg2list-1">cfg2list/1</a></td><td>retrive config as a proplist.</td></tr><tr><td valign="top"><a href="#cfg2list-2">cfg2list/2</a></td><td>retrieve config as a proplist.</td></tr><tr><td valign="top"><a href="#delete_value-3">delete_value/3</a></td><td>delete a value.</td></tr><tr><td valign="top"><a href="#delete_value-4">delete_value/4</a></td><td>delete a value.</td></tr><tr><td valign="top"><a href="#get_value-2">get_value/2</a></td><td>get values of a section.</td></tr><tr><td valign="top"><a href="#get_value-3">get_value/3</a></td><td>get value for a key in a section.</td></tr><tr><td valign="top"><a href="#get_value-4">get_value/4</a></td><td></td></tr><tr><td valign="top"><a href="#open_config-2">open_config/2</a></td><td>open or create an ini file an register it.</td></tr><tr><td valign="top"><a href="#open_config-3">open_config/3</a></td><td>open or create an ini file an register it.</td></tr><tr><td valign="top"><a href="#prefix-2">prefix/2</a></td><td>get all sections starting by Prefix.</td></tr><tr><td valign="top"><a href="#register_config-2">register_config/2</a></td><td>register inifiles or config dirs.</td></tr><tr><td valign="top"><a href="#register_config-3">register_config/3</a></td><td>register inifiles of config dirs with options
For now the only option is<code>autoreload</code> to auto reload the config on
files or dirs changes.</td></tr><tr><td valign="top"><a href="#reload-1">reload/1</a></td><td>reload the configuration.</td></tr><tr><td valign="top"><a href="#reload-2">reload/2</a></td><td>reload the configuration.</td></tr><tr><td valign="top"><a href="#set_value-4">set_value/4</a></td><td>set a value.</td></tr><tr><td valign="top"><a href="#set_value-5">set_value/5</a></td><td></td></tr><tr><td valign="top"><a href="#start_autoreload-1">start_autoreload/1</a></td><td></td></tr><tr><td valign="top"><a href="#stop_autoreload-1">stop_autoreload/1</a></td><td></td></tr><tr><td valign="top"><a href="#subscribe-1">subscribe/1</a></td><td>Subscribe to config events for a config named <code>ConfigName</code></td></tr><tr><td valign="top"><a href="#unregister_config-1">unregister_config/1</a></td><td>unregister a conf.</td></tr><tr><td valign="top"><a href="#unsubscribe-1">unsubscribe/1</a></td><td>Remove subscribtion created using <code>subscribe(ConfigName)</code>.</td></tr></table>
files or dirs changes.</td></tr><tr><td valign="top"><a href="#reload-1">reload/1</a></td><td>reload the configuration.</td></tr><tr><td valign="top"><a href="#reload-2">reload/2</a></td><td>reload the configuration.</td></tr><tr><td valign="top"><a href="#sections-1">sections/1</a></td><td>get all sections of a configuration.</td></tr><tr><td valign="top"><a href="#set_value-4">set_value/4</a></td><td>set a value.</td></tr><tr><td valign="top"><a href="#set_value-5">set_value/5</a></td><td></td></tr><tr><td valign="top"><a href="#start-0">start/0</a></td><td>Start the couchbeam process.</td></tr><tr><td valign="top"><a href="#start_autoreload-1">start_autoreload/1</a></td><td></td></tr><tr><td valign="top"><a href="#stop-0">stop/0</a></td><td>Stop the couchbeam process.</td></tr><tr><td valign="top"><a href="#stop_autoreload-1">stop_autoreload/1</a></td><td></td></tr><tr><td valign="top"><a href="#subscribe-1">subscribe/1</a></td><td>Subscribe to config events for a config named <code>ConfigName</code></td></tr><tr><td valign="top"><a href="#unregister_config-1">unregister_config/1</a></td><td>unregister a conf.</td></tr><tr><td valign="top"><a href="#unsubscribe-1">unsubscribe/1</a></td><td>Remove subscribtion created using <code>subscribe(ConfigName)</code>.</td></tr></table>


<a name="functions"></a>

##Function Details##
## Function Details ##

<a name="all-1"></a>

###all/1##

### all/1 ###

`all(ConfigName) -> any()`

get all values of a configuration<a name="delete_value-3"></a>
get all values of a configuration
<a name="cfg2list-1"></a>

###delete_value/3##
### cfg2list/1 ###

`cfg2list(ConfigName) -> any()`

`delete_value(ConfigName, Section, Key) -> any()`
retrive config as a proplist
<a name="cfg2list-2"></a>

delete a value<a name="delete_value-4"></a>
### cfg2list/2 ###

###delete_value/4##
`cfg2list(ConfigName, GroupKey) -> any()`

retrieve config as a proplist
<a name="delete_value-3"></a>

`delete_value(ConfigName, Section, Key, Persist) -> any()`
### delete_value/3 ###

delete a value<a name="get_value-2"></a>
`delete_value(ConfigName, Section, Key) -> any()`

###get_value/2##
delete a value
<a name="delete_value-4"></a>

### delete_value/4 ###

`get_value(ConfigName, Section) -> any()`
`delete_value(ConfigName, Section, Key, Persist) -> any()`

get values of a section<a name="get_value-3"></a>
delete a value
<a name="get_value-2"></a>

###get_value/3##
### get_value/2 ###

`get_value(ConfigName, Section) -> any()`

`get_value(ConfigName, Section, Key) -> any()`
get values of a section
<a name="get_value-3"></a>

### get_value/3 ###

get value for a key in a section<a name="get_value-4"></a>
`get_value(ConfigName, Section, Key) -> any()`

###get_value/4##
get value for a key in a section
<a name="get_value-4"></a>

### get_value/4 ###

`get_value(ConfigName, Section, Key, Default) -> any()`


<a name="open_config-2"></a>

### open_config/2 ###

`open_config(ConfigName, IniFile) -> any()`

open or create an ini file an register it
<a name="open_config-3"></a>

### open_config/3 ###

`open_config(ConfigName, IniFile, Options) -> any()`

open or create an ini file an register it. See the
register_config function for a list of available functions.
<a name="prefix-2"></a>

### prefix/2 ###

`prefix(ConfigName, Prefix) -> any()`

get all sections starting by Prefix
<a name="register_config-2"></a>

###register_config/2##
### register_config/2 ###


<pre><code>
register_config(ConfigName::term(), IniFiles::<a href="econfig.md#type-inifiles">econfig:inifiles()</a>) -&gt; ok | {error, any()}
</code></pre>

<pre>register_config(ConfigName::term(), IniFiles::<a href="econfig.md#type-inifiles">econfig:inifiles()</a>) -> ok | {error, any()}</pre>
<br></br>


register inifiles or config dirs<a name="register_config-3"></a>
register inifiles or config dirs
<a name="register_config-3"></a>

###register_config/3##
### register_config/3 ###


<pre>register_config(ConfigName::term(), IniFiles::<a href="econfig.md#type-inifiles">econfig:inifiles()</a>, Options::<a href="econfig.md#type-options">econfig:options()</a>) -> ok | {error, any()}</pre>
<br></br>
<pre><code>
register_config(ConfigName::term(), IniFiles::<a href="econfig.md#type-inifiles">econfig:inifiles()</a>, Options::<a href="econfig.md#type-options">econfig:options()</a>) -&gt; ok | {error, any()}
</code></pre>

<br></br>



Expand All @@ -98,82 +140,109 @@ Configs can also be registererd in the app configuration at startup:

Options:


- `autoreload`: auto reload the config on files or dirs changes
- `{autoreload, Delay}`: autoreload the config file or dir
changes. Delay set the time between each scan. Default is 5000
and can be set using the `scan_delay` application environement
for econfig.<a name="reload-1"></a>

###reload/1##
for econfig.
<a name="reload-1"></a>

### reload/1 ###

`reload(ConfigName) -> any()`

reload the configuration<a name="reload-2"></a>

###reload/2##
reload the configuration
<a name="reload-2"></a>

### reload/2 ###

`reload(ConfigName, IniFiles) -> any()`

reload the configuration<a name="set_value-4"></a>
reload the configuration
<a name="sections-1"></a>

###set_value/4##
### sections/1 ###

`sections(ConfigName) -> any()`

`set_value(ConfigName, Section, Key, Value) -> any()`
get all sections of a configuration
<a name="set_value-4"></a>

set a value<a name="set_value-5"></a>
### set_value/4 ###

###set_value/5##
`set_value(ConfigName, Section, Key, Value) -> any()`

set a value
<a name="set_value-5"></a>

### set_value/5 ###

`set_value(ConfigName, Section, Key, Value, Persist) -> any()`

<a name="start_autoreload-1"></a>

###start_autoreload/1##
<a name="start-0"></a>

### start/0 ###

`start() -> any()`

Start the couchbeam process. Useful when testing using the shell.
<a name="start_autoreload-1"></a>

### start_autoreload/1 ###

`start_autoreload(ConfigName) -> any()`

<a name="stop_autoreload-1"></a>

###stop_autoreload/1##
<a name="stop-0"></a>

### stop/0 ###

`stop() -> any()`

Stop the couchbeam process. Useful when testing using the shell.
<a name="stop_autoreload-1"></a>

### stop_autoreload/1 ###

`stop_autoreload(ConfigName) -> any()`

<a name="subscribe-1"></a>

###subscribe/1##
<a name="subscribe-1"></a>

### subscribe/1 ###

`subscribe(ConfigName) -> any()`



Subscribe to config events for a config named `ConfigName`



The message received to each subscriber will be of the form:


`{config_updated, ConfigName, {Section, Key}}`

<a name="unregister_config-1"></a>

###unregister_config/1##
### unregister_config/1 ###


<pre>unregister_config(ConfigName::term()) -&gt; ok</pre>
<br></br>
<pre><code>
unregister_config(ConfigName::term()) -&gt; ok
</code></pre>

<br></br>

unregister a conf<a name="unsubscribe-1"></a>

###unsubscribe/1##
unregister a conf
<a name="unsubscribe-1"></a>

### unsubscribe/1 ###

`unsubscribe(ConfigName) -> any()`

Remove subscribtion created using `subscribe(ConfigName)`

27 changes: 17 additions & 10 deletions doc/econfig_app.md
Original file line number Diff line number Diff line change
@@ -1,33 +1,40 @@


#Module econfig_app#
# Module econfig_app #
* [Function Index](#index)
* [Function Details](#functions)

__Behaviours:__ [`application`](application.md).
<a name="index"></a>

__Behaviours:__ [`application`](application.md).<a name="index"></a>
## Function Index ##

##Function Index##


<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#start-2">start/2</a></td><td></td></tr><tr><td valign="top"><a href="#stop-1">stop/1</a></td><td></td></tr></table>
<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#ensure_deps_started-0">ensure_deps_started/0</a></td><td></td></tr><tr><td valign="top"><a href="#start-2">start/2</a></td><td></td></tr><tr><td valign="top"><a href="#stop-1">stop/1</a></td><td></td></tr></table>


<a name="functions"></a>

##Function Details##
## Function Details ##

<a name="start-2"></a>
<a name="ensure_deps_started-0"></a>

### ensure_deps_started/0 ###

###start/2##
`ensure_deps_started() -> any()`


<a name="start-2"></a>

### start/2 ###

`start(StartType, StartArgs) -> any()`

<a name="stop-1"></a>

###stop/1##
<a name="stop-1"></a>

### stop/1 ###

`stop(State) -> any()`


133 changes: 133 additions & 0 deletions doc/econfig_deps.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@


# Module econfig_deps #
* [Function Index](#index)
* [Function Details](#functions)


<a name="index"></a>

## Function Index ##


<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#deps_on_path-0">deps_on_path/0</a></td><td>List of project dependencies on the path.</td></tr><tr><td valign="top"><a href="#ensure-0">ensure/0</a></td><td>Ensure that the ebin and include paths for dependencies of
this application are on the code path.</td></tr><tr><td valign="top"><a href="#ensure-1">ensure/1</a></td><td>Ensure that all ebin and include paths for dependencies
of the application for Module are on the code path.</td></tr><tr><td valign="top"><a href="#get_base_dir-0">get_base_dir/0</a></td><td>Return the application directory for this application.</td></tr><tr><td valign="top"><a href="#get_base_dir-1">get_base_dir/1</a></td><td>Return the application directory for Module.</td></tr><tr><td valign="top"><a href="#local_path-1">local_path/1</a></td><td>Return an application-relative directory for this application.</td></tr><tr><td valign="top"><a href="#local_path-2">local_path/2</a></td><td>Return an application-relative directory from Module's application.</td></tr><tr><td valign="top"><a href="#new_siblings-1">new_siblings/1</a></td><td>Find new siblings paths relative to Module that aren't already on the
code path.</td></tr></table>


<a name="functions"></a>

## Function Details ##

<a name="deps_on_path-0"></a>

### deps_on_path/0 ###


<pre><code>
deps_on_path() -&gt; [ProjNameAndVers]
</code></pre>

<br></br>


List of project dependencies on the path.
<a name="ensure-0"></a>

### ensure/0 ###


<pre><code>
ensure() -&gt; ok
</code></pre>

<br></br>


Ensure that the ebin and include paths for dependencies of
this application are on the code path. Equivalent to
ensure(?Module).
<a name="ensure-1"></a>

### ensure/1 ###


<pre><code>
ensure(Module) -&gt; ok
</code></pre>

<br></br>


Ensure that all ebin and include paths for dependencies
of the application for Module are on the code path.
<a name="get_base_dir-0"></a>

### get_base_dir/0 ###


<pre><code>
get_base_dir() -&gt; string()
</code></pre>

<br></br>


Return the application directory for this application. Equivalent to
get_base_dir(?MODULE).
<a name="get_base_dir-1"></a>

### get_base_dir/1 ###


<pre><code>
get_base_dir(Module) -&gt; string()
</code></pre>

<br></br>


Return the application directory for Module. It assumes Module is in
a standard OTP layout application in the ebin or src directory.
<a name="local_path-1"></a>

### local_path/1 ###


<pre><code>
local_path(Components) -&gt; string()
</code></pre>

<br></br>


Return an application-relative directory for this application.
Equivalent to local_path(Components, ?MODULE).
<a name="local_path-2"></a>

### local_path/2 ###


<pre><code>
local_path(Components::[string()], Module) -&gt; string()
</code></pre>

<br></br>


Return an application-relative directory from Module's application.
<a name="new_siblings-1"></a>

### new_siblings/1 ###


<pre><code>
new_siblings(Module) -&gt; [Dir]
</code></pre>

<br></br>


Find new siblings paths relative to Module that aren't already on the
code path.
15 changes: 9 additions & 6 deletions doc/econfig_file_writer.md
Original file line number Diff line number Diff line change
@@ -1,29 +1,32 @@


#Module econfig_file_writer#
# Module econfig_file_writer #
* [Function Index](#index)
* [Function Details](#functions)


<a name="index"></a>

##Function Index##
## Function Index ##


<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#save_to_file-2">save_to_file/2</a></td><td>Saves a Section/Key/Value triple to the ini file File::filename().</td></tr></table>


<a name="functions"></a>

##Function Details##
## Function Details ##

<a name="save_to_file-2"></a>

###save_to_file/2##
### save_to_file/2 ###


<pre>save_to_file(Config::{{Section::string(), Option::string()}, Value::string()}, File::<a href="#type-filename">filename()</a>) -> ok</pre>
<pre><code>
save_to_file(Config::{{Section::string(), Option::string()}, Value::string()}, File::<a href="#type-filename">filename()</a>) -&gt; ok
</code></pre>

<br></br>


Saves a Section/Key/Value triple to the ini file File::filename()
Saves a Section/Key/Value triple to the ini file File::filename()
170 changes: 108 additions & 62 deletions doc/econfig_server.md
Original file line number Diff line number Diff line change
@@ -1,199 +1,245 @@


#Module econfig_server#
# Module econfig_server #
* [Function Index](#index)
* [Function Details](#functions)

__Behaviours:__ [`gen_server`](gen_server.md).
<a name="index"></a>

__Behaviours:__ [`gen_server`](gen_server.md).<a name="index"></a>
## Function Index ##

##Function Index##


<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#all-1">all/1</a></td><td>get all values of a configuration.</td></tr><tr><td valign="top"><a href="#code_change-3">code_change/3</a></td><td></td></tr><tr><td valign="top"><a href="#delete_value-3">delete_value/3</a></td><td>delete a value.</td></tr><tr><td valign="top"><a href="#delete_value-4">delete_value/4</a></td><td></td></tr><tr><td valign="top"><a href="#get_value-2">get_value/2</a></td><td>get values of a section.</td></tr><tr><td valign="top"><a href="#get_value-3">get_value/3</a></td><td>get value for a key in a section.</td></tr><tr><td valign="top"><a href="#get_value-4">get_value/4</a></td><td></td></tr><tr><td valign="top"><a href="#handle_call-3">handle_call/3</a></td><td></td></tr><tr><td valign="top"><a href="#handle_cast-2">handle_cast/2</a></td><td></td></tr><tr><td valign="top"><a href="#handle_info-2">handle_info/2</a></td><td></td></tr><tr><td valign="top"><a href="#init-1">init/1</a></td><td></td></tr><tr><td valign="top"><a href="#register_config-2">register_config/2</a></td><td>register inifiles.</td></tr><tr><td valign="top"><a href="#register_config-3">register_config/3</a></td><td></td></tr><tr><td valign="top"><a href="#reload-1">reload/1</a></td><td>reload the configuration.</td></tr><tr><td valign="top"><a href="#reload-2">reload/2</a></td><td>reload the configuration.</td></tr><tr><td valign="top"><a href="#set_value-4">set_value/4</a></td><td>set a value.</td></tr><tr><td valign="top"><a href="#set_value-5">set_value/5</a></td><td></td></tr><tr><td valign="top"><a href="#start_autoreload-1">start_autoreload/1</a></td><td></td></tr><tr><td valign="top"><a href="#start_link-0">start_link/0</a></td><td></td></tr><tr><td valign="top"><a href="#stop_autoreload-1">stop_autoreload/1</a></td><td></td></tr><tr><td valign="top"><a href="#subscribe-1">subscribe/1</a></td><td>Subscribe to config events for a config named <code>ConfigName</code></td></tr><tr><td valign="top"><a href="#terminate-2">terminate/2</a></td><td></td></tr><tr><td valign="top"><a href="#unregister_config-1">unregister_config/1</a></td><td>unregister a conf.</td></tr><tr><td valign="top"><a href="#unsubscribe-1">unsubscribe/1</a></td><td>Remove subscribtion created using <code>subscribe(ConfigName)</code>.</td></tr></table>
<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#all-1">all/1</a></td><td>get all values of a configuration.</td></tr><tr><td valign="top"><a href="#cfg2list-1">cfg2list/1</a></td><td>retrive config as a proplist.</td></tr><tr><td valign="top"><a href="#cfg2list-2">cfg2list/2</a></td><td>retrieve config as a proplist.</td></tr><tr><td valign="top"><a href="#code_change-3">code_change/3</a></td><td></td></tr><tr><td valign="top"><a href="#delete_value-3">delete_value/3</a></td><td>delete a value.</td></tr><tr><td valign="top"><a href="#delete_value-4">delete_value/4</a></td><td></td></tr><tr><td valign="top"><a href="#get_value-2">get_value/2</a></td><td>get values of a section.</td></tr><tr><td valign="top"><a href="#get_value-3">get_value/3</a></td><td>get value for a key in a section.</td></tr><tr><td valign="top"><a href="#get_value-4">get_value/4</a></td><td></td></tr><tr><td valign="top"><a href="#handle_call-3">handle_call/3</a></td><td></td></tr><tr><td valign="top"><a href="#handle_cast-2">handle_cast/2</a></td><td></td></tr><tr><td valign="top"><a href="#handle_info-2">handle_info/2</a></td><td></td></tr><tr><td valign="top"><a href="#init-1">init/1</a></td><td></td></tr><tr><td valign="top"><a href="#open_config-2">open_config/2</a></td><td>open or create an ini file an register it.</td></tr><tr><td valign="top"><a href="#open_config-3">open_config/3</a></td><td></td></tr><tr><td valign="top"><a href="#prefix-2">prefix/2</a></td><td>get all sections starting by Prefix.</td></tr><tr><td valign="top"><a href="#register_config-2">register_config/2</a></td><td>register inifiles.</td></tr><tr><td valign="top"><a href="#register_config-3">register_config/3</a></td><td></td></tr><tr><td valign="top"><a href="#reload-1">reload/1</a></td><td>reload the configuration.</td></tr><tr><td valign="top"><a href="#reload-2">reload/2</a></td><td>reload the configuration.</td></tr><tr><td valign="top"><a href="#sections-1">sections/1</a></td><td>get all sections of a configuration.</td></tr><tr><td valign="top"><a href="#set_value-4">set_value/4</a></td><td>set a value.</td></tr><tr><td valign="top"><a href="#set_value-5">set_value/5</a></td><td></td></tr><tr><td valign="top"><a href="#start_autoreload-1">start_autoreload/1</a></td><td></td></tr><tr><td valign="top"><a href="#start_link-0">start_link/0</a></td><td></td></tr><tr><td valign="top"><a href="#stop_autoreload-1">stop_autoreload/1</a></td><td></td></tr><tr><td valign="top"><a href="#subscribe-1">subscribe/1</a></td><td>Subscribe to config events for a config named <code>ConfigName</code></td></tr><tr><td valign="top"><a href="#terminate-2">terminate/2</a></td><td></td></tr><tr><td valign="top"><a href="#unregister_config-1">unregister_config/1</a></td><td>unregister a conf.</td></tr><tr><td valign="top"><a href="#unsubscribe-1">unsubscribe/1</a></td><td>Remove subscribtion created using <code>subscribe(ConfigName)</code>.</td></tr></table>


<a name="functions"></a>

##Function Details##
## Function Details ##

<a name="all-1"></a>

###all/1##

### all/1 ###

`all(ConfigName) -> any()`

get all values of a configuration<a name="code_change-3"></a>
get all values of a configuration
<a name="cfg2list-1"></a>

### cfg2list/1 ###

`cfg2list(ConfigName) -> any()`

###code_change/3##
retrive config as a proplist
<a name="cfg2list-2"></a>

### cfg2list/2 ###

`cfg2list(ConfigName, GroupKey) -> any()`

retrieve config as a proplist
<a name="code_change-3"></a>

### code_change/3 ###

`code_change(OldVsn, State, Extra) -> any()`

<a name="delete_value-3"></a>

###delete_value/3##
<a name="delete_value-3"></a>

### delete_value/3 ###

`delete_value(ConfigName, Section, Key) -> any()`

delete a value<a name="delete_value-4"></a>

###delete_value/4##
delete a value
<a name="delete_value-4"></a>

### delete_value/4 ###

`delete_value(ConfigName, Section0, Key0, Persist) -> any()`

<a name="get_value-2"></a>

###get_value/2##
<a name="get_value-2"></a>

### get_value/2 ###

`get_value(ConfigName, Section0) -> any()`

get values of a section<a name="get_value-3"></a>

###get_value/3##
get values of a section
<a name="get_value-3"></a>

### get_value/3 ###

`get_value(ConfigName, Section, Key) -> any()`

get value for a key in a section<a name="get_value-4"></a>

###get_value/4##
get value for a key in a section
<a name="get_value-4"></a>

### get_value/4 ###

`get_value(ConfigName, Section0, Key0, Default) -> any()`

<a name="handle_call-3"></a>

###handle_call/3##
<a name="handle_call-3"></a>

### handle_call/3 ###

`handle_call(Msg, From, State) -> any()`

<a name="handle_cast-2"></a>

###handle_cast/2##
<a name="handle_cast-2"></a>

### handle_cast/2 ###

`handle_cast(Msg, State) -> any()`

<a name="handle_info-2"></a>

###handle_info/2##
<a name="handle_info-2"></a>

### handle_info/2 ###

`handle_info(Info, State) -> any()`

<a name="init-1"></a>

###init/1##
<a name="init-1"></a>

### init/1 ###

`init(X1) -> any()`


<a name="open_config-2"></a>

### open_config/2 ###

`open_config(ConfigName, IniFile) -> any()`

open or create an ini file an register it
<a name="open_config-3"></a>

### open_config/3 ###

`open_config(ConfigName, IniFile, Options) -> any()`


<a name="prefix-2"></a>

### prefix/2 ###

`prefix(ConfigName, Prefix) -> any()`

get all sections starting by Prefix
<a name="register_config-2"></a>

###register_config/2##
### register_config/2 ###


<pre>register_config(ConfigName::term(), IniFiles::<a href="econfig.md#type-inifiles">econfig:inifiles()</a>) -> ok | {error, any()}</pre>
<br></br>
<pre><code>
register_config(ConfigName::term(), IniFiles::<a href="econfig.md#type-inifiles">econfig:inifiles()</a>) -&gt; ok | {error, any()}
</code></pre>

<br></br>

register inifiles<a name="register_config-3"></a>

###register_config/3##
register inifiles
<a name="register_config-3"></a>

### register_config/3 ###

`register_config(ConfigName, IniFiles, Options) -> any()`

<a name="reload-1"></a>

###reload/1##
<a name="reload-1"></a>

### reload/1 ###

`reload(ConfigName) -> any()`

reload the configuration<a name="reload-2"></a>

###reload/2##
reload the configuration
<a name="reload-2"></a>

### reload/2 ###

`reload(ConfigName, IniFiles) -> any()`

reload the configuration<a name="set_value-4"></a>
reload the configuration
<a name="sections-1"></a>

###set_value/4##
### sections/1 ###

`sections(ConfigName) -> any()`

`set_value(ConfigName, Section, Key, Value) -> any()`
get all sections of a configuration
<a name="set_value-4"></a>

set a value<a name="set_value-5"></a>
### set_value/4 ###

###set_value/5##
`set_value(ConfigName, Section, Key, Value) -> any()`

set a value
<a name="set_value-5"></a>

### set_value/5 ###

`set_value(ConfigName, Section0, Key0, Value0, Persist) -> any()`

<a name="start_autoreload-1"></a>

###start_autoreload/1##
<a name="start_autoreload-1"></a>

### start_autoreload/1 ###

`start_autoreload(ConfigName) -> any()`

<a name="start_link-0"></a>

###start_link/0##
<a name="start_link-0"></a>

### start_link/0 ###

`start_link() -> any()`

<a name="stop_autoreload-1"></a>

###stop_autoreload/1##
<a name="stop_autoreload-1"></a>

### stop_autoreload/1 ###

`stop_autoreload(ConfigName) -> any()`

<a name="subscribe-1"></a>

###subscribe/1##
<a name="subscribe-1"></a>

### subscribe/1 ###

`subscribe(ConfigName) -> any()`



Subscribe to config events for a config named `ConfigName`



The message received to each subscriber will be of the form:


`{config_updated, ConfigName, {Section, Key}}`
<a name="terminate-2"></a>

###terminate/2##
<a name="terminate-2"></a>

### terminate/2 ###

`terminate(Reason, State) -> any()`

<a name="unregister_config-1"></a>

###unregister_config/1##
<a name="unregister_config-1"></a>

### unregister_config/1 ###

`unregister_config(ConfigName) -> any()`

unregister a conf<a name="unsubscribe-1"></a>

###unsubscribe/1##
unregister a conf
<a name="unsubscribe-1"></a>

### unsubscribe/1 ###

`unsubscribe(ConfigName) -> any()`

Remove subscribtion created using `subscribe(ConfigName)`

18 changes: 9 additions & 9 deletions doc/econfig_sup.md
Original file line number Diff line number Diff line change
@@ -1,33 +1,33 @@


#Module econfig_sup#
# Module econfig_sup #
* [Function Index](#index)
* [Function Details](#functions)

__Behaviours:__ [`supervisor`](supervisor.md).
<a name="index"></a>

__Behaviours:__ [`supervisor`](supervisor.md).<a name="index"></a>

##Function Index##
## Function Index ##


<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#init-1">init/1</a></td><td></td></tr><tr><td valign="top"><a href="#start_link-0">start_link/0</a></td><td></td></tr></table>


<a name="functions"></a>

##Function Details##
## Function Details ##

<a name="init-1"></a>

###init/1##

### init/1 ###

`init(X1) -> any()`

<a name="start_link-0"></a>

###start_link/0##
<a name="start_link-0"></a>

### start_link/0 ###

`start_link() -> any()`


34 changes: 17 additions & 17 deletions doc/econfig_util.md
Original file line number Diff line number Diff line change
@@ -1,68 +1,68 @@


#Module econfig_util#
# Module econfig_util #
* [Function Index](#index)
* [Function Details](#functions)


<a name="index"></a>

##Function Index##
## Function Index ##


<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#abs_pathname-1">abs_pathname/1</a></td><td></td></tr><tr><td valign="top"><a href="#find_files-1">find_files/1</a></td><td></td></tr><tr><td valign="top"><a href="#find_files-2">find_files/2</a></td><td></td></tr><tr><td valign="top"><a href="#find_files-3">find_files/3</a></td><td></td></tr><tr><td valign="top"><a href="#find_ini_files-1">find_ini_files/1</a></td><td></td></tr><tr><td valign="top"><a href="#implode-2">implode/2</a></td><td></td></tr><tr><td valign="top"><a href="#to_list-1">to_list/1</a></td><td></td></tr></table>


<a name="functions"></a>

##Function Details##
## Function Details ##

<a name="abs_pathname-1"></a>

###abs_pathname/1##

### abs_pathname/1 ###

`abs_pathname(Filename) -> any()`

<a name="find_files-1"></a>

###find_files/1##
<a name="find_files-1"></a>

### find_files/1 ###

`find_files(Paths) -> any()`

<a name="find_files-2"></a>

###find_files/2##
<a name="find_files-2"></a>

### find_files/2 ###

`find_files(Paths, Fun) -> any()`

<a name="find_files-3"></a>

###find_files/3##
<a name="find_files-3"></a>

### find_files/3 ###

`find_files(Rest, Acc, Fun) -> any()`

<a name="find_ini_files-1"></a>

###find_ini_files/1##
<a name="find_ini_files-1"></a>

### find_ini_files/1 ###

`find_ini_files(Path) -> any()`

<a name="implode-2"></a>

###implode/2##
<a name="implode-2"></a>

### implode/2 ###

`implode(List, Sep) -> any()`

<a name="to_list-1"></a>

###to_list/1##
<a name="to_list-1"></a>

### to_list/1 ###

`to_list(V) -> any()`


50 changes: 25 additions & 25 deletions doc/econfig_watcher.md
Original file line number Diff line number Diff line change
@@ -1,89 +1,89 @@


#Module econfig_watcher#
# Module econfig_watcher #
* [Function Index](#index)
* [Function Details](#functions)

__Behaviours:__ [`gen_server`](gen_server.md).
<a name="index"></a>

__Behaviours:__ [`gen_server`](gen_server.md).<a name="index"></a>

##Function Index##
## Function Index ##


<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#code_change-3">code_change/3</a></td><td></td></tr><tr><td valign="top"><a href="#handle_call-3">handle_call/3</a></td><td></td></tr><tr><td valign="top"><a href="#handle_cast-2">handle_cast/2</a></td><td></td></tr><tr><td valign="top"><a href="#handle_info-2">handle_info/2</a></td><td></td></tr><tr><td valign="top"><a href="#init-1">init/1</a></td><td></td></tr><tr><td valign="top"><a href="#pause-1">pause/1</a></td><td></td></tr><tr><td valign="top"><a href="#restart-1">restart/1</a></td><td></td></tr><tr><td valign="top"><a href="#start_link-2">start_link/2</a></td><td></td></tr><tr><td valign="top"><a href="#start_link-3">start_link/3</a></td><td></td></tr><tr><td valign="top"><a href="#terminate-2">terminate/2</a></td><td></td></tr></table>


<a name="functions"></a>

##Function Details##
## Function Details ##

<a name="code_change-3"></a>

###code_change/3##

### code_change/3 ###

`code_change(OldVsn, State, Extra) -> any()`

<a name="handle_call-3"></a>

###handle_call/3##
<a name="handle_call-3"></a>

### handle_call/3 ###

`handle_call(Req, From, State) -> any()`

<a name="handle_cast-2"></a>

###handle_cast/2##
<a name="handle_cast-2"></a>

### handle_cast/2 ###

`handle_cast(Event, State) -> any()`

<a name="handle_info-2"></a>

###handle_info/2##
<a name="handle_info-2"></a>

### handle_info/2 ###

`handle_info(Info, State) -> any()`

<a name="init-1"></a>

###init/1##
<a name="init-1"></a>

### init/1 ###

`init(X1) -> any()`

<a name="pause-1"></a>

###pause/1##
<a name="pause-1"></a>

### pause/1 ###

`pause(Pid) -> any()`

<a name="restart-1"></a>

###restart/1##
<a name="restart-1"></a>

### restart/1 ###

`restart(Pid) -> any()`

<a name="start_link-2"></a>

###start_link/2##
<a name="start_link-2"></a>

### start_link/2 ###

`start_link(ConfName, Paths) -> any()`

<a name="start_link-3"></a>

###start_link/3##
<a name="start_link-3"></a>

### start_link/3 ###

`start_link(ConfName, Paths, Delay) -> any()`

<a name="terminate-2"></a>

###terminate/2##
<a name="terminate-2"></a>

### terminate/2 ###

`terminate(Reason, State) -> any()`


26 changes: 13 additions & 13 deletions doc/econfig_watcher_sup.md
Original file line number Diff line number Diff line change
@@ -1,47 +1,47 @@


#Module econfig_watcher_sup#
# Module econfig_watcher_sup #
* [Function Index](#index)
* [Function Details](#functions)

__Behaviours:__ [`supervisor`](supervisor.md).
<a name="index"></a>

__Behaviours:__ [`supervisor`](supervisor.md).<a name="index"></a>

##Function Index##
## Function Index ##


<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#start_link-0">start_link/0</a></td><td></td></tr><tr><td valign="top"><a href="#start_watcher-2">start_watcher/2</a></td><td></td></tr><tr><td valign="top"><a href="#start_watcher-3">start_watcher/3</a></td><td></td></tr><tr><td valign="top"><a href="#stop-1">stop/1</a></td><td></td></tr></table>


<a name="functions"></a>

##Function Details##
## Function Details ##

<a name="start_link-0"></a>

###start_link/0##

### start_link/0 ###

`start_link() -> any()`

<a name="start_watcher-2"></a>

###start_watcher/2##
<a name="start_watcher-2"></a>

### start_watcher/2 ###

`start_watcher(ConfigName, Path) -> any()`

<a name="start_watcher-3"></a>

###start_watcher/3##
<a name="start_watcher-3"></a>

### start_watcher/3 ###

`start_watcher(ConfigName, Path, Delay) -> any()`

<a name="stop-1"></a>

###stop/1##
<a name="stop-1"></a>

### stop/1 ###

`stop(S) -> any()`


5 changes: 3 additions & 2 deletions doc/edoc-info
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
%% encoding: UTF-8
{application,econfig}.
{packages,[]}.
{modules,[econfig,econfig_app,econfig_file_writer,econfig_server,econfig_sup,
econfig_util,econfig_watcher,econfig_watcher_sup]}.
{modules,[econfig,econfig_app,econfig_deps,econfig_file_writer,econfig_server,
econfig_sup,econfig_util,econfig_watcher,econfig_watcher_sup]}.
8 changes: 4 additions & 4 deletions doc/overview.edoc
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
%%==============================================================================
%% Copyright 2012 Benoît Chesneau
%% Copyright 2012-2013 Benoît Chesneau
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
Expand All @@ -14,8 +14,8 @@
%% limitations under the License.
%%==============================================================================

@copyright 2012 Benoît Chesneau.
@version 0.3
@copyright 2012-2013 Benoît Chesneau.
@version 0.4
@title econfig - simple Erlang config handler using INI files

@doc
Expand All @@ -26,7 +26,7 @@ econfig is a simple Erlang config handler to manage a config from INI
files.

econfig can be use to read and update INI files. Values are cached in an
ETS table and you can manage multiple configuration profile. A process
ETS table and you can manage multiple configuration profiles. A process
can also subscribe to config updates events.

Autoreload of the config when an INI file is updated is supported, you can even
Expand Down
9 changes: 1 addition & 8 deletions rebar.config
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,5 @@
{clean_files, ["*~","*/*~","*/*.xfm","test/*.beam"]}.

{deps, [
{gproc, ".*", {git, "git://github.com/esl/gproc.git", "master"}},

{edown, ".*",
{git, "git://github.com/esl/edown.git", "HEAD"}}
{gproc, ".*", {git, "git://github.com/esl/gproc.git", "master"}}
]}.

{edoc_opts, [{doclet, edown_doclet},
{top_level_readme,
{"./README.md", "http://github.com/benoitc/econfig"}}]}.
21 changes: 21 additions & 0 deletions rebar_dev.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
%% -*- tab-width: 4;erlang-indent-level: 4;indent-tabs-mode: nil -*-
%% ex: ft=erlang ts=4 sw=4 et

{erl_opts, [debug_info]}.
{xref_checks, [undefined_function_calls]}.

{cover_enabled, true}.
{eunit_opts, [verbose]}.

{clean_files, ["*~","*/*~","*/*.xfm","test/*.beam"]}.

{deps, [
{gproc, ".*", {git, "git://github.com/esl/gproc.git", "master"}},

{edown, ".*",
{git, "git://github.com/esl/edown.git", "HEAD"}}
]}.

{edoc_opts, [{doclet, edown_doclet},
{top_level_readme,
{"./README.md", "http://github.com/benoitc/econfig"}}]}.
2 changes: 1 addition & 1 deletion src/econfig.app.src
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
{application, econfig,
[
{description, "simple Erlang config handler using INI files"},
{vsn, "0.3"},
{vsn, "0.4"},
{registered, []},
{applications, [kernel,
stdlib,
Expand Down
41 changes: 40 additions & 1 deletion src/econfig.erl
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,16 @@
%% @doc Public API of econfig.
-module(econfig).

-export([start/0, stop/0]).

-export([register_config/2, register_config/3,
open_config/2, open_config/3,
unregister_config/1,
subscribe/1, unsubscribe/1,
reload/1, reload/2,
start_autoreload/1, stop_autoreload/1,
all/1,
all/1, sections/1, prefix/2,
cfg2list/1, cfg2list/2,
get_value/2, get_value/3, get_value/4,
set_value/4, set_value/5,
delete_value/3, delete_value/4]).
Expand All @@ -20,6 +24,17 @@
-type inifiles() :: [inifile()].
-type options() :: [autoreload].

%% @doc Start the couchbeam process. Useful when testing using the shell.
start() ->
econfig_deps:ensure(),
application:load(econfig),
econfig_app:ensure_deps_started(),
application:start(econfig).

%% @doc Stop the couchbeam process. Useful when testing using the shell.
stop() ->
application:stop(econfig).


-spec register_config(term(), econfig:inifiles()) -> ok | {error,
any()}.
Expand Down Expand Up @@ -52,6 +67,14 @@ register_config(ConfigName, IniFiles, Options) ->
unregister_config(ConfigName) ->
econfig_server:unregister_config(ConfigName).

%% @doc open or create an ini file an register it
open_config(ConfigName, IniFile) ->
econfig_server:open_config(ConfigName, IniFile).

%% @doc open or create an ini file an register it. See the
%% register_config function for a list of available functions.
open_config(ConfigName, IniFile, Options) ->
econfig_server:open_config(ConfigName, IniFile, Options).

%% @doc Subscribe to config events for a config named `ConfigName'
%%
Expand Down Expand Up @@ -88,6 +111,22 @@ stop_autoreload(ConfigName) ->
all(ConfigName) ->
econfig_server:all(ConfigName).

%% @doc get all sections of a configuration
sections(ConfigName) ->
econfig_server:sections(ConfigName).

%% @doc get all sections starting by Prefix
prefix(ConfigName, Prefix) ->
econfig_server:prefix(ConfigName, Prefix).

%% @doc retrive config as a proplist
cfg2list(ConfigName) ->
econfig_server:cfg2list(ConfigName).

%% @doc retrieve config as a proplist
cfg2list(ConfigName, GroupKey) ->
econfig_server:cfg2list(ConfigName, GroupKey).

%% @doc get values of a section
get_value(ConfigName, Section) ->
econfig_server:get_value(ConfigName, Section).
Expand Down
31 changes: 13 additions & 18 deletions src/econfig_app.erl
Original file line number Diff line number Diff line change
Expand Up @@ -9,37 +9,32 @@

%% Application callbacks
-export([start/2, stop/1]).
-export([ensure_deps_started/0]).

%% ===================================================================
%% Application callbacks
%% ===================================================================

start(_StartType, _StartArgs) ->
start_app_deps(econfig),
econfig_deps:ensure(),
ensure_deps_started(),
econfig_sup:start_link().

stop(_State) ->
ok.


%% @spec start_app_deps(App :: atom()) -> ok
%% @doc Start depedent applications of App.
start_app_deps(App) ->
{ok, DepApps} = application:get_key(App, applications),
[ensure_started(A) || A <- DepApps],
ok.
ensure_deps_started() ->
{ok, Deps} = application:get_key(econfig, applications),
true = lists:all(fun ensure_started/1, Deps).

%% @spec ensure_started(Application :: atom()) -> ok
%% @doc Start the named application if not already started.
ensure_started(App) ->
case application:start(App) of
ok ->
ok;
{error, {already_started, App}} ->
ok;
Else ->
error_logger:error_msg("Couldn't start ~p: ~p", [App, Else]),
Else
ok ->
true;
{error, {already_started, App}} ->
true;
Else ->
error_logger:error_msg("Couldn't start ~p: ~p", [App, Else]),
Else
end.


79 changes: 79 additions & 0 deletions src/econfig_deps.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
%%% -*- erlang -*-
%%%
%%% This file is part of econfig released under the Apache 2 license.
%%% See the NOTICE for more information.
%%%

-module(econfig_deps).
-author('Justin Sheehy <justin@basho.com>').
-author('Andy Gross <andy@basho.com>').

-export([ensure/0, ensure/1]).
-export([get_base_dir/0, get_base_dir/1]).
-export([local_path/1, local_path/2]).
-export([deps_on_path/0, new_siblings/1]).

%% @spec deps_on_path() -> [ProjNameAndVers]
%% @doc List of project dependencies on the path.
deps_on_path() ->
ordsets:from_list([filename:basename(filename:dirname(X)) || X <- code:get_path()]).

%% @spec new_siblings(Module) -> [Dir]
%% @doc Find new siblings paths relative to Module that aren't already on the
%% code path.
new_siblings(Module) ->
Existing = deps_on_path(),
SiblingEbin = [ X || X <- filelib:wildcard(local_path(["deps", "*", "ebin"], Module)),
filename:basename(filename:dirname(X)) /= %% don't include self
filename:basename(filename:dirname(
filename:dirname(
filename:dirname(X)))) ],
Siblings = [filename:dirname(X) || X <- SiblingEbin,
ordsets:is_element(
filename:basename(filename:dirname(X)),
Existing) =:= false],
lists:filter(fun filelib:is_dir/1,
lists:append([[filename:join([X, "ebin"]),
filename:join([X, "include"])] ||
X <- Siblings])).


%% @spec ensure(Module) -> ok
%% @doc Ensure that all ebin and include paths for dependencies
%% of the application for Module are on the code path.
ensure(Module) ->
code:add_paths(new_siblings(Module)),
%% code:clash is annoying when you load couchbeam in a script.
%% code:clash(),
ok.

%% @spec ensure() -> ok
%% @doc Ensure that the ebin and include paths for dependencies of
%% this application are on the code path. Equivalent to
%% ensure(?Module).
ensure() ->
ensure(?MODULE).

%% @spec get_base_dir(Module) -> string()
%% @doc Return the application directory for Module. It assumes Module is in
%% a standard OTP layout application in the ebin or src directory.
get_base_dir(Module) ->
{file, Here} = code:is_loaded(Module),
filename:dirname(filename:dirname(Here)).

%% @spec get_base_dir() -> string()
%% @doc Return the application directory for this application. Equivalent to
%% get_base_dir(?MODULE).
get_base_dir() ->
get_base_dir(?MODULE).

%% @spec local_path([string()], Module) -> string()
%% @doc Return an application-relative directory from Module's application.
local_path(Components, Module) ->
filename:join([get_base_dir(Module) | Components]).

%% @spec local_path(Components) -> string()
%% @doc Return an application-relative directory for this application.
%% Equivalent to local_path(Components, ?MODULE).
local_path(Components) ->
local_path(Components, ?MODULE).
2 changes: 1 addition & 1 deletion src/econfig_file_writer.erl
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ save_to_file({{Section, Key}, Value}, File) ->
Lines = re:split(OldFileContents, "\r\n|\n|\r|\032", [{return, list}]),

SectionLine = "[" ++ Section ++ "]",
{ok, Pattern} = re:compile(["^(", Key, "\\s*=)|\\[[a-zA-Z0-9\_-]*\\]"]),
{ok, Pattern} = re:compile(["^(", Key, "\\s*=)|\\[[a-zA-Z0-9\.\_-]*\\]"]),

NewLines = process_file_lines(Lines, [], SectionLine, Pattern, Key, Value),
NewFileContents = reverse_and_add_newline(strip_empty_lines(NewLines), []),
Expand Down
92 changes: 91 additions & 1 deletion src/econfig_server.erl
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@
-behaviour(gen_server).

-export([register_config/2, register_config/3,
open_config/2, open_config/3,
unregister_config/1,
subscribe/1, unsubscribe/1,
reload/1, reload/2,
start_autoreload/1, stop_autoreload/1,
all/1,
all/1, sections/1, prefix/2,
cfg2list/1, cfg2list/2,
get_value/2, get_value/3, get_value/4,
set_value/4, set_value/5,
delete_value/3, delete_value/4]).
Expand Down Expand Up @@ -49,6 +51,25 @@ register_config(ConfigName, IniFiles, Options) ->
unregister_config(ConfigName) ->
gen_server:call(?MODULE, {unregister_conf, ConfigName}).

%% @doc open or create an ini file an register it
open_config(ConfigName, IniFile) ->
open_config(ConfigName, IniFile, []).

open_config(ConfigName, IniFile, Options) ->
IniFileName = econfig_util:abs_pathname(IniFile),
case filelib:is_file(IniFileName) of
true ->
register_config(ConfigName, [IniFile], Options);
false ->
case file:open(IniFileName, [write]) of
{ok, Fd} ->
file:close(Fd),
register_config(ConfigName, [IniFile], Options);
Error ->
Error
end
end.

%% @doc Subscribe to config events for a config named `ConfigName'
%%
%% The message received to each subscriber will be of the form:
Expand Down Expand Up @@ -86,6 +107,75 @@ all(ConfigName) ->
Matches = ets:match(?MODULE, {{ConfigName, '$1', '$2'}, '$3'}),
[{Section, Key, Value} || [Section, Key, Value] <- Matches].

%% @doc get all sections of a configuration
sections(ConfigName) ->
Matches = ets:match(?MODULE, {{ConfigName, '$1', '_'}, '_'}),
lists:umerge(Matches).


%% @doc get all sections starting by Prefix
prefix(ConfigName, Prefix) ->
Matches = ets:match(?MODULE, {{ConfigName, '$1', '_'}, '_'}),
Found = lists:foldl(fun([Match], Acc) ->
case re:split(Match, Prefix, [{return,list}]) of
[Match] -> Acc;
_ ->
case lists:member(Match, Acc) of
true -> Acc;
false -> [Match | Acc]
end
end
end, [], Matches),
lists:reverse(Found).

%% @doc retrive config as a proplist
cfg2list(ConfigName) ->
Matches = ets:match(?MODULE, {{ConfigName, '$1', '$2'}, '$3'}),
lists:foldl(fun([Section, Key, Value], Props) ->
case lists:keyfind(Section, 1, Props) of
false ->
[{Section, [{Key, Value}]} | Props];
{Section, KVs} ->
KVs1 = lists:keymerge(1, KVs, [{Key, Value}]),
lists:keyreplace(Section, 1, Props, {Section, KVs1})
end
end, [], Matches).

%% @doc retrieve config as a proplist
cfg2list(ConfigName, GroupKey) ->
Matches = ets:match(?MODULE, {{ConfigName, '$1', '$2'}, '$3'}),
lists:foldl(fun([Section, Key, Value], Props) ->
case re:split(Section, GroupKey, [{return,list}]) of
[Section] ->
case lists:keyfind(Section, 1, Props) of
false ->
[{Section, [{Key, Value}]} | Props];
{Section, KVs} ->
KVs1 = lists:keymerge(1, KVs, [{Key, Value}]),
lists:keyreplace(Section, 1, Props, {Section, KVs1})
end;
[Section1, SSection] ->
case lists:keyfind(Section1, 1, Props) of
false ->
[{Section1, [{SSection, [{Key, Value}]}]}
| Props];
{Section1, KVs} ->
KVs1 = case lists:keyfind(SSection, 1, KVs) of
false ->
[{SSection, [{Key, Value}]} | KVs];
{SSection, SKVs} ->
SKVs1 = lists:keymerge(1, SKVs,
[{Key, Value}]),
lists:keyreplace(SSection, 1,
KVs, {SSection,
SKVs1})
end,
lists:keyreplace(Section1, 1, Props,
{Section1, KVs1})
end
end
end, [], Matches).

%% @doc get values of a section
get_value(ConfigName, Section0) ->
Section = econfig_util:to_list(Section0),
Expand Down