IniFile

Generic module to create INI files lenses

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

Summary
IniFileGeneric module to create INI files lenses
LicenseThis file is licensed under the LGPL v2+, like the rest of Augeas.
TODOThings to add in the future
Lens usageThis lens is made to provide generic primitives to construct INI File lenses.
ExamplesThe Test_IniFile file contains various examples and tests.
USEFUL PRIMITIVES
Internal primitives
eolEnd of line, inherited from Util.eol
Separators
sepGeneric separator
sep_noindentGeneric separator, no indentation
sep_reThe default regexp for a separator
sep_defaultThe default separator value
Stores
sto_to_eolStore until end of line
to_comment_reRegex until comment
sto_to_commentStore until comment
sto_multilineStore multiline values
sto_multiline_nocommentStore multiline values without an end-of-line comment
Define comment and defaults
comment_noindentMap comments into “#comment” nodes, no indentation allowed
commentMap comments into “#comment” nodes
comment_reDefault regexp for comment pattern
comment_defaultDefault value for comment pattern
empty_genericEmpty line, including empty comments
emptyEmpty line
empty_noindentEmpty line, without indentation
ENTRY
entry includes comments
entry_generic_nocommentA 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_genericA 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.
entryGeneric INI File entry
indented_entryGeneric INI File entry that might be indented with an arbitrary amount of whitespace
entry_multiline_genericA 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_multilineGeneric multiline INI File entry
entry_multiline_nocommentGeneric multiline INI File entry without an end-of-line comment
entry_listGeneric INI File list entry
entry_list_nocommentGeneric INI File list entry without an end-of-line comment
entry_reDefault regexp for entry keyword
RECORD
Title definition
titleTitle for record.
indented_titleTitle for record.
title_labelTitle for record.
indented_title_labelTitle for record.
record_reDefault regexp for title keyword pattern
record_label_reDefault regexp for title_label keyword pattern
Record definition
record_noemptyINI File Record with no empty lines allowed.
recordGeneric INI File record
GENERIC LENSES
Lens definition
lns_noemptyGeneric INI File lens with no empty lines
lnsGeneric 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:regexpthe pattern to delete
default:stringthe default string to use

sep_noindent

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

Generic separator, no indentation

Parameters

pat:regexpthe pattern to delete
default:stringthe 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:regexppattern to delete before commented data
default:stringdefault 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:regexppattern to delete before commented data
default:stringdefault 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:regexpthe indentation regexp
comment_re:regexpthe 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:lenslens to match the key, including optional indentation
sep:lenslens to use as key/value separator
comment_re:regexpcomment separator regexp
comment:lenslens 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:lenslens to match the key, including optional indentation
sep:lenslens to use as key/value separator
comment_re:regexpcomment separator regexp
comment:lenslens 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:regexpkeyword regexp for the label
sep:lenslens to use as key/value separator
comment:lenslens 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:regexpkeyword regexp for the label
sep:lenslens to use as key/value separator
comment:lenslens 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:lenslens to match the key, including optional indentation
sep:lenslens to use as key/value separator
comment_re:regexpcomment separator regexp
comment:lenslens to use as comment
eol:lenslens 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:regexpkeyword regexp for the label
sep:lenslens to use as key/value separator
comment:lenslens 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:regexpkeyword regexp for the label
sep:lenslens to use as key/value separator
comment:lenslens 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:regexpkeyword regexp for the label
sep:lenslens to use as key/value separator
sto:regexpstore regexp for the values
list_sep:lenslens to use as list separator
comment:lenslens 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:regexpkeyword regexp for the label
sep:lenslens to use as key/value separator
sto:regexpstore regexp for the values
list_sep:lenslens 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:regexpkeyword 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:regexpkeyword 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:stringname for the title label
kw:regexpkeyword 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:stringname for the title label
kw:regexpkeyword 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:lenslens to use for title.  Use either title or title_label.
entry:lenslens 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:lenslens to use for title.  Use either title or title_label.
entry:lenslens 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:lensrecord lens to use.  See record_noempty.
comment:lenscomment 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:lensrecord lens to use.  See record.
comment:lenscomment 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