# IniFile

Generic module to create INI files lenses

Author: Raphael Pinson rap.nosp@m.hink@gmai.nosp@m.l.com

Summary

IniFile | Generic module to create INI files lenses
License | This file is licensed under the LGPL v2+, like the rest of Augeas.
TODO | Things to add in the future
Lens usage | This lens is made to provide generic primitives to construct INI File lenses.
Examples | The Test_IniFile file contains various examples and tests.
USEFUL PRIMITIVES |
Internal primitives |
eol | End of line, inherited from Util.eol
Separators |
sep | Generic separator
sep_noindent | Generic separator, no indentation
sep_re | The default regexp for a separator
sep_default | The default separator value
Stores |
sto_to_eol | Store until end of line
to_comment_re | Regex until comment
sto_to_comment | Store until comment
sto_multiline | Store multiline values
sto_multiline_nocomment | Store multiline values without an end-of-line comment
Define comment and defaults |
comment_noindent | Map comments into “#comment” nodes, no indentation allowed
comment | Map comments into “#comment” nodes
comment_re | Default regexp for comment pattern
comment_default | Default value for comment pattern
empty_generic | Empty line, including empty comments
empty | Empty line
empty_noindent | Empty line, without indentation
ENTRY |
entry includes comments |
entry_generic_nocomment | A very generic INI File entry, not including comments It allows to set the key lens (to set indentation or subnodes linked to the key) as well as the comment separator regexp, used to tune the store regexps.
entry_generic | A very generic INI File entry It allows to set the key lens (to set indentation or subnodes linked to the key) as well as the comment separator regexp, used to tune the store regexps.
entry | Generic INI File entry
indented_entry | Generic INI File entry that might be indented with an arbitrary amount of whitespace
entry_multiline_generic | A very generic multiline INI File entry It allows to set the key lens (to set indentation or subnodes linked to the key) as well as the comment separator regexp, used to tune the store regexps.
entry_multiline | Generic multiline INI File entry
entry_multiline_nocomment | Generic multiline INI File entry without an end-of-line comment
entry_list | Generic INI File list entry
entry_list_nocomment | Generic INI File list entry without an end-of-line comment
entry_re | Default regexp for entry keyword
RECORD |
Title definition |
title | Title for record.
indented_title | Title for record.
title_label | Title for record.
indented_title_label | Title for record.
record_re | Default regexp for title keyword pattern
record_label_re | Default regexp for title_label keyword pattern
Record definition |
record_noempty | INI File Record with no empty lines allowed.
record | Generic INI File record
GENERIC LENSES |
Lens definition |
lns_noempty | Generic INI File lens with no empty lines
lns | Generic INI File lens
READY-TO-USE LENSES |
lns_loose |
lns_loose_multiline |

### License

This file is licensed under the LGPL v2+, like the rest of Augeas.

### TODO

Things to add in the future

- Support double quotes in value

### Lens usage

This lens is made to provide generic primitives to construct INI File lenses. See <Puppet>, <PHP>, <MySQL> or <Dput> for examples of real life lenses using it.

### Examples

The Test_IniFile file contains various examples and tests.

### USEFUL PRIMITIVES

### Internal primitives

### eol

> let eol = Util.doseol

End of line, inherited from Util.eol

### Separators

### sep

> let sep (pat:regexp) (default:string) = Sep.opt_space . del pat default

Generic separator

#### Parameters

pat:regexp | the pattern to delete
default:string | the default string to use

### sep_noindent

> let sep_noindent (pat:regexp) (default:string) = del pat default

Generic separator, no indentation

#### Parameters

pat:regexp | the pattern to delete
default:string | the default string to use

### sep_re

> let sep_re = /[=:]/

The default regexp for a separator

### sep_default

> let sep_default = "="

The default separator value

### Stores

### sto_to_eol

> let sto_to_eol = Sep.opt_space . store Rx.space_in

Store until end of line

### to_comment_re

> let to_comment_re = /[^";# \t\n][^";#\n]*[^";# \t\n]|[^";# \t\n]/

Regex until comment

### sto_to_comment

> let sto_to_comment = Sep.opt_space . store to_comment_re

Store until comment

### sto_multiline

> let sto_multiline = Sep.opt_space . store (to_comment_re . (/[ \t]*\n/ . Rx.space . to_comment_re)*)

Store multiline values

### sto_multiline_nocomment

> let sto_multiline_nocomment = Sep.opt_space . store (Rx.space_in . (/[ \t]*\n/ . Rx.space . Rx.space_in)*)

Store multiline values without an end-of-line comment

### Define comment and defaults

### comment_noindent

> let comment_noindent (pat:regexp) (default:string) = Util.comment_generic_seteol (pat . Rx.opt_space) default eol

Map comments into “#comment” nodes, no indentation allowed

#### Parameters

pat:regexp | pattern to delete before commented data
default:string | default pattern before commented data

#### Sample Usage

>     let comment  = IniFile.comment_noindent "#" "#"
>     let comment  = IniFile.comment_noindent IniFile.comment_re IniFile.comment_default

### comment

> let comment (pat:regexp) (default:string) = Util.comment_generic_seteol (Rx.opt_space . pat . Rx.opt_space) default eol

Map comments into “#comment” nodes

#### Parameters

pat:regexp | pattern to delete before commented data
default:string | default pattern before commented data

#### Sample Usage

>     let comment  = IniFile.comment "#" "#"
>     let comment  = IniFile.comment IniFile.comment_re IniFile.comment_default

### comment_re

> let comment_re = /[;#]/

Default regexp for comment pattern

### comment_default

> let comment_default = ";"

Default value for comment pattern

### empty_generic

> let empty_generic (indent:regexp) (comment_re:regexp) = Util.empty_generic_dos (indent . comment_re? . Rx.opt_space)

Empty line, including empty comments

#### Parameters

indent:regexp | the indentation regexp
comment_re:regexp | the comment separator regexp

### empty

> let empty = empty_generic Rx.opt_space comment_re

Empty line

### empty_noindent

> let empty_noindent = empty_generic "" comment_re

Empty line, without indentation

### ENTRY

### entry includes comments

### entry_generic_nocomment

> let entry_generic_nocomment (kw:lens) (sep:lens) (comment_re:regexp) (comment:lens) = let bare_re_noquot = (/[^" \t\r\n]/ - comment_re) in let bare_re = (/[^\r\n]/ - comment_re)+ in let no_quot = /[^"\r\n]*/ in let bare = Quote.do_dquote_opt_nil (store (bare_re_noquot . (bare_re* . bare_re_noquot)?)) in let quoted = Quote.do_dquote (store (no_quot . comment_re+ . no_quot)) in [ kw . sep . (Sep.opt_space . bare)? . (comment|eol) ] | [ kw . sep . Sep.opt_space . quoted . (comment|eol) ]

A very generic INI File entry, not including comments It allows to set the key lens (to set indentation or subnodes linked to the key) as well as the comment separator regexp, used to tune the store regexps.

#### Parameters

kw:lens | lens to match the key, including optional indentation
sep:lens | lens to use as key/value separator
comment_re:regexp | comment separator regexp
comment:lens | lens to use as comment

#### Sample Usage

>     let entry = IniFile.entry_generic (key "setting") sep IniFile.comment_re comment

### entry_generic

> let entry_generic (kw:lens) (sep:lens) (comment_re:regexp) (comment:lens) = entry_generic_nocomment kw sep comment_re comment | comment

A very generic INI File entry It allows to set the key lens (to set indentation or subnodes linked to the key) as well as the comment separator regexp, used to tune the store regexps.

#### Parameters

kw:lens | lens to match the key, including optional indentation
sep:lens | lens to use as key/value separator
comment_re:regexp | comment separator regexp
comment:lens | lens to use as comment

#### Sample Usage

>     let entry = IniFile.entry_generic (key "setting") sep IniFile.comment_re comment

### entry

> let entry (kw:regexp) (sep:lens) (comment:lens) = entry_generic (key kw) sep comment_re comment

Generic INI File entry

#### Parameters

kw:regexp | keyword regexp for the label
sep:lens | lens to use as key/value separator
comment:lens | lens to use as comment

#### Sample Usage

>     let entry = IniFile.entry setting sep comment

### indented_entry

> let indented_entry (kw:regexp) (sep:lens) (comment:lens) = entry_generic (Util.indent . key kw) sep comment_re comment

Generic INI File entry that might be indented with an arbitrary amount of whitespace

#### Parameters

kw:regexp | keyword regexp for the label
sep:lens | lens to use as key/value separator
comment:lens | lens to use as comment

#### Sample Usage

>     let entry = IniFile.indented_entry setting sep comment

### entry_multiline_generic

> let entry_multiline_generic (kw:lens) (sep:lens) (comment_re:regexp) (comment:lens) (eol:lens) = let newline = /\r?\n[ \t]+/ in let bare = let word_re_noquot = (/[^" \t\r\n]/ - comment_re)+ in let word_re = (/[^\r\n]/ - comment_re)+ in let base_re = (word_re_noquot . (word_re* . word_re_noquot)?) in let sto_re = base_re . (newline . base_re)* | (newline . base_re)+ in Quote.do_dquote_opt_nil (store sto_re) in let quoted = let no_quot = /[^"\r\n]*/ in let base_re = (no_quot . comment_re+ . no_quot) in let sto_re = base_re . (newline . base_re)* | (newline . base_re)+ in Quote.do_dquote (store sto_re) in [ kw . sep . (Sep.opt_space . bare)? . eol ] | [ kw . sep . Sep.opt_space . quoted . eol ] | comment

A very generic multiline INI File entry It allows to set the key lens (to set indentation or subnodes linked to the key) as well as the comment separator regexp, used to tune the store regexps.

#### Parameters

kw:lens | lens to match the key, including optional indentation
sep:lens | lens to use as key/value separator
comment_re:regexp | comment separator regexp
comment:lens | lens to use as comment
eol:lens | lens for end of line

#### Sample Usage

>     let entry = IniFile.entry_generic (key "setting") sep IniFile.comment_re comment comment_or_eol

### entry_multiline

> let entry_multiline (kw:regexp) (sep:lens) (comment:lens) = entry_multiline_generic (key kw) sep comment_re comment (comment|eol)

Generic multiline INI File entry

#### Parameters

kw:regexp | keyword regexp for the label
sep:lens | lens to use as key/value separator
comment:lens | lens to use as comment

### entry_multiline_nocomment

> let entry_multiline_nocomment (kw:regexp) (sep:lens) (comment:lens) = entry_multiline_generic (key kw) sep comment_re comment eol

Generic multiline INI File entry without an end-of-line comment

#### Parameters

kw:regexp | keyword regexp for the label
sep:lens | lens to use as key/value separator
comment:lens | lens to use as comment

### entry_list

> let entry_list (kw:regexp) (sep:lens) (sto:regexp) (list_sep:lens) (comment:lens) = let list = counter "elem" . Build.opt_list [ seq "elem" . store sto ] list_sep in Build.key_value_line_comment kw sep (Sep.opt_space . list) comment

Generic INI File list entry

#### Parameters

kw:regexp | keyword regexp for the label
sep:lens | lens to use as key/value separator
sto:regexp | store regexp for the values
list_sep:lens | lens to use as list separator
comment:lens | lens to use as comment

### entry_list_nocomment

> let entry_list_nocomment (kw:regexp) (sep:lens) (sto:regexp) (list_sep:lens) = let list = counter "elem" . Build.opt_list [ seq "elem" . store sto ] list_sep in Build.key_value_line kw sep (Sep.opt_space . list)

Generic INI File list entry without an end-of-line comment

#### Parameters

kw:regexp | keyword regexp for the label
sep:lens | lens to use as key/value separator
sto:regexp | store regexp for the values
list_sep:lens | lens to use as list separator

### entry_re

> let entry_re = ( /[A-Za-z][A-Za-z0-9._-]*/ )

Default regexp for entry keyword

### RECORD

### Title definition

### title

> let title (kw:regexp) = Util.del_str "[" . key kw . Util.del_str "]". eol

Title for record. This maps the title of a record as a node in the abstract tree.

#### Parameters

kw:regexp | keyword regexp for the label

#### Sample Usage

>     let title   = IniFile.title IniFile.record_re

### indented_title

> let indented_title (kw:regexp) = Util.indent . title kw

Title for record. This maps the title of a record as a node in the abstract tree. The title may be indented with arbitrary amounts of whitespace

#### Parameters

kw:regexp | keyword regexp for the label

#### Sample Usage

>     let title   = IniFile.title IniFile.record_re

### title_label

> let title_label (name:string) (kw:regexp) = label name . Util.del_str "[" . store kw . Util.del_str "]". eol

Title for record. This maps the title of a record as a value in the abstract tree.

#### Parameters

name:string | name for the title label
kw:regexp | keyword regexp for the label

#### Sample Usage

>     let title   = IniFile.title_label "target" IniFile.record_label_re

### indented_title_label

> let indented_title_label (name:string) (kw:regexp) = Util.indent . title_label name kw

Title for record. This maps the title of a record as a value in the abstract tree. The title may be indented with arbitrary amounts of whitespace

#### Parameters

name:string | name for the title label
kw:regexp | keyword regexp for the label

#### Sample Usage

>     let title   = IniFile.title_label "target" IniFile.record_label_re

### record_re

> let record_re = ( /[^]\r\n\/]+/ - /#comment/ )

Default regexp for title keyword pattern

### record_label_re

> let record_label_re = /[^]\r\n]+/

Default regexp for title_label keyword pattern

### Record definition

### record_noempty

> let record_noempty (title:lens) (entry:lens) = [ title . entry* ]

INI File Record with no empty lines allowed.

#### Parameters

title:lens | lens to use for title. Use either title or title_label.
entry:lens | lens to use for entries in the record. See entry.

### record

> let record (title:lens) (entry:lens) = record_noempty title ( entry | empty )

Generic INI File record

#### Parameters

title:lens | lens to use for title. Use either title or title_label.
entry:lens | lens to use for entries in the record. See entry.

#### Sample Usage

>     let record  = IniFile.record title entry

### GENERIC LENSES

### Lens definition

### lns_noempty

> let lns_noempty (record:lens) (comment:lens) = comment* . record*

Generic INI File lens with no empty lines

#### Parameters

record:lens | record lens to use. See record_noempty.
comment:lens | comment lens to use. See comment.

#### Sample Usage

>     let lns     = IniFile.lns_noempty record comment

### lns

> let lns (record:lens) (comment:lens) = lns_noempty record (comment|empty)

Generic INI File lens

#### Parameters

record:lens | record lens to use. See record.
comment:lens | comment lens to use. See comment.

#### Sample Usage

>     let lns     = IniFile.lns record comment

### READY-TO-USE LENSES

### lns_loose

> let lns_loose = let l_comment = comment comment_re comment_default in let l_sep = sep sep_re sep_default in let l_entry = indented_entry entry_re l_sep l_comment in let l_title = indented_title_label "section" (record_label_re - ".anon") in let l_record = record l_title l_entry in (record_anon l_entry)? . l_record*

#### A loose, ready-to-use lens, featuring

- sections as values (to allow ‘/’ in names)
- support empty lines and comments
- support for [#;] as comment, defaulting to “;”
- .anon sections
- don’t allow multiline values
- allow indented titles
- allow indented entries

### lns_loose_multiline

> let lns_loose_multiline = let l_comment = comment comment_re comment_default in let l_sep = sep sep_re sep_default in let l_entry = entry_multiline entry_re l_sep l_comment in let l_title = title_label "section" (record_label_re - ".anon") in let l_record = record l_title l_entry in (record_anon l_entry)? . l_record*

#### A loose, ready-to-use lens, featuring

- sections as values (to allow ‘/’ in names)
- support empty lines and comments
- support for [#;] as comment, defaulting to “;”
- .anon sections
- allow multiline values

Provides unit tests and examples for the IniFile module.

> let eol = Util.doseol

End of line, inherited from Util.eol

> let eol = del /[ \t]*\n/ "\n"

Delete end of line, including optional trailing whitespace

> let sep (pat:regexp) (default:string) = Sep.opt_space . del pat default

Generic separator

> let sep_noindent (pat:regexp) (default:string) = del pat default

Generic separator, no indentation

> let sep_re = /[=:]/

The default regexp for a separator

> let sep_default = "="

The default separator value

> let sto_to_eol = Sep.opt_space . store Rx.space_in

Store until end of line

> let to_comment_re = /[^";# \t\n][^";#\n]*[^";# \t\n]|[^";# \t\n]/

Regex until comment

> let sto_to_comment = Sep.opt_space . store to_comment_re

Store until comment

> let sto_multiline = Sep.opt_space . store (to_comment_re . (/[ \t]*\n/ . Rx.space . to_comment_re)*)

Store multiline values

> let sto_multiline_nocomment = Sep.opt_space . store (Rx.space_in . (/[ \t]*\n/ . Rx.space . Rx.space_in)*)

Store multiline values without an end-of-line comment

> let comment_noindent (pat:regexp) (default:string) = Util.comment_generic_seteol (pat . Rx.opt_space) default eol

Map comments into “#comment” nodes, no indentation allowed

> let comment (pat:regexp) (default:string) = Util.comment_generic_seteol (Rx.opt_space . pat . Rx.opt_space) default eol

Map comments into “#comment” nodes

> let comment_re = /[;#]/

Default regexp for comment pattern

> let comment_default = ";"

Default value for comment pattern

> let empty_generic (indent:regexp) (comment_re:regexp) = Util.empty_generic_dos (indent . comment_re? . Rx.opt_space)

Empty line, including empty comments

> let empty = empty_generic Rx.opt_space comment_re

Empty line

> let empty_noindent = empty_generic "" comment_re

Empty line, without indentation

> let entry_generic_nocomment (kw:lens) (sep:lens) (comment_re:regexp) (comment:lens) = let bare_re_noquot = (/[^" \t\r\n]/ - comment_re) in let bare_re = (/[^\r\n]/ - comment_re)+ in let no_quot = /[^"\r\n]*/ in let bare = Quote.do_dquote_opt_nil (store (bare_re_noquot . (bare_re* . bare_re_noquot)?)) in let quoted = Quote.do_dquote (store (no_quot . comment_re+ . no_quot)) in [ kw . sep . (Sep.opt_space . bare)? . (comment|eol) ] | [ kw . sep . Sep.opt_space . quoted . (comment|eol) ]

A very generic INI File entry, not including comments It allows to set the key lens (to set indentation or subnodes linked to the key) as well as the comment separator regexp, used to tune the store regexps.

> let entry_generic (kw:lens) (sep:lens) (comment_re:regexp) (comment:lens) = entry_generic_nocomment kw sep comment_re comment | comment

A very generic INI File entry It allows to set the key lens (to set indentation or subnodes linked to the key) as well as the comment separator regexp, used to tune the store regexps.

> let entry (kw:regexp) (sep:lens) (comment:lens) = entry_generic (key kw) sep comment_re comment

Generic INI File entry

> let indented_entry (kw:regexp) (sep:lens) (comment:lens) = entry_generic (Util.indent . key kw) sep comment_re comment

Generic INI File entry that might be indented with an arbitrary amount of whitespace

> let entry_multiline_generic (kw:lens) (sep:lens) (comment_re:regexp) (comment:lens) (eol:lens) = let newline = /\r?\n[ \t]+/ in let bare = let word_re_noquot = (/[^" \t\r\n]/ - comment_re)+ in let word_re = (/[^\r\n]/ - comment_re)+ in let base_re = (word_re_noquot . (word_re* . word_re_noquot)?) in let sto_re = base_re . (newline . base_re)* | (newline . base_re)+ in Quote.do_dquote_opt_nil (store sto_re) in let quoted = let no_quot = /[^"\r\n]*/ in let base_re = (no_quot . comment_re+ . no_quot) in let sto_re = base_re . (newline . base_re)* | (newline . base_re)+ in Quote.do_dquote (store sto_re) in [ kw . sep . (Sep.opt_space . bare)? . eol ] | [ kw . sep . Sep.opt_space . quoted . eol ] | comment

A very generic multiline INI File entry It allows to set the key lens (to set indentation or subnodes linked to the key) as well as the comment separator regexp, used to tune the store regexps.

> let entry_multiline (kw:regexp) (sep:lens) (comment:lens) = entry_multiline_generic (key kw) sep comment_re comment (comment|eol)

Generic multiline INI File entry

> let entry_multiline_nocomment (kw:regexp) (sep:lens) (comment:lens) = entry_multiline_generic (key kw) sep comment_re comment eol

Generic multiline INI File entry without an end-of-line comment

> let entry_list (kw:regexp) (sep:lens) (sto:regexp) (list_sep:lens) (comment:lens) = let list = counter "elem" . Build.opt_list [ seq "elem" . store sto ] list_sep in Build.key_value_line_comment kw sep (Sep.opt_space . list) comment

Generic INI File list entry

> let entry_list_nocomment (kw:regexp) (sep:lens) (sto:regexp) (list_sep:lens) = let list = counter "elem" . Build.opt_list [ seq "elem" . store sto ] list_sep in Build.key_value_line kw sep (Sep.opt_space . list)

Generic INI File list entry without an end-of-line comment

> let entry_re = ( /[A-Za-z][A-Za-z0-9._-]*/ )

Default regexp for entry keyword

> let title (kw:regexp) = Util.del_str "[" . key kw . Util.del_str "]". eol

Title for record.

> let record (title:lens) (entry:lens) = record_noempty title ( entry | empty )

Generic INI File record

> let indented_title (kw:regexp) = Util.indent . title kw

Title for record.

> let title_label (name:string) (kw:regexp) = label name . Util.del_str "[" . store kw . Util.del_str "]". eol

Title for record.

> let indented_title_label (name:string) (kw:regexp) = Util.indent . title_label name kw

Title for record.

> let record_re = ( /[^]\r\n\/]+/ - /#comment/ )

Default regexp for title keyword pattern

> let record_label_re = /[^]\r\n]+/

Default regexp for title_label keyword pattern

> let record_noempty (title:lens) (entry:lens) = [ title . entry* ]

INI File Record with no empty lines allowed.

> let lns_noempty (record:lens) (comment:lens) = comment* . record*

Generic INI File lens with no empty lines

> let lns (record:lens) (comment:lens) = lns_noempty record (comment|empty)

Generic INI File lens

> let lns_loose = let l_comment = comment comment_re comment_default in let l_sep = sep sep_re sep_default in let l_entry = indented_entry entry_re l_sep l_comment in let l_title = indented_title_label "section" (record_label_re - ".anon") in let l_record = record l_title l_entry in (record_anon l_entry)? . l_record*

> let lns_loose_multiline = let l_comment = comment comment_re comment_default in let l_sep = sep sep_re sep_default in let l_entry = entry_multiline entry_re l_sep l_comment in let l_title = title_label "section" (record_label_re - ".anon") in let l_record = record l_title l_entry in (record_anon l_entry)? . l_record*

Close