Named blocks standardization
Contents |
[edit]
Rationale
Several lenses (logrotate.aug, xinetd.aug, keepalived.aug, aptconf.aug, dhclient.aug, shellvars.aug) use named blocks with the following syntax:
block_name {
entry+
}
but each lens implements it differently. It would be good to add a (or several types of) block entry to build.aug to make it easier to build such blocks in a standard way.
[edit]
Existing implementations
The following are existing implementations of such blocks. They are not working examples, but they show the general pattern of each implementation.
[edit]
xinetd.aug
[edit]
Code
let body (attr:lens) = del /\n\{[ \t]*\n/ "\n{\n"
. (empty|comment|attr)*
. del /[ \t]*\}[ \t]*\n/ "}\n"
let service =
let sto_re = /[^# \t\n\/]+/ in
[ key "service" . Sep.space . store sto_re . body service_attr ]
[edit]
Notes
- This implementation forces a newline after the opening bracket;
[edit]
logrotate.aug
[edit]
Code
let body = del /\{[ \t]*\n/ "{\n"
. ( comment "\t" | attrs "\t" | hooks | empty )*
. del /[ \t]*\}[ \t]*\n/ "}\n"
let rule =
[ label "rule" . Util.indent .
[ label "file" . store filename ] .
[ del /[ \t\n]+/ " " . label "file" . store filename ]* .
del /[ \t\n]*/ " " . body ]
[edit]
Notes
- This lens was inspired by xinetd.aug and uses a similar "body" construct, only more complex;
- This example shows that a standard block pattern should take a lens as the block name rather than a regexp, since the construction in logrotate.aug accepts several files (we could use Build.opt_list here) before the body;
- This implementation forces a newline after the opening bracket, just like xinetd.aug;
[edit]
keepalived.aug
[edit]
Code
let lbracket = Util.del_str "{"
let rbracket = Util.del_str "}"
let lens_block (title:lens) (sto:lens) = [ indent . title . opt_eol . lbracket
. (sto | empty | comment)+
. indent . rbracket . eol ]
[edit]
Notes
- This lens doesn't force a newline after the opening bracket;
- As a result, new blocks have no newlines;
- This lens allows for eol before the opening bracket. This might not be the case of all formats (but it doesn't hurt in general to support it);
- This lens doesn't allow the closing bracket to be on the same line as an entry (since entries have eol);
[edit]
aptconf.aug
[edit]
Code
let rec entry_noeol =
let value =
Util.del_str "\"" . store /[^"\n]+/
. del /";?/ "\";" in
let opt_eol = del /[ \t\n]*/ "\n" in
let long_eol = del /[ \t]*\n+/ "\n" in
let list_elem = [ opt_eol . label "@elem" . value ] in
let eol_comment = del /([ \t\n]*\n)?/ "" . comment in
[ key name_re . Sep.space . value ]
| [ key name_re . del /[ \t\n]*\{/ " {" .
( (opt_eol . entry_noeol) |
list_elem |
eol_comment
)* .
del /[ \t\n]*\};?/ "\n};" ]
| [ key name_re . Util.del_str "::" . entry_noeol ]
let entry = indent . entry_noeol . eol
[edit]
Notes
- This is a recursive lens, allowing two different formats. It might not be easy to fit it into a standard block pattern.
[edit]
Comparison of existing implementations
| eol before lbracket | eol after lbracket | eol before rbracket | block name |
|---|---|---|---|
| xinetd | mandatory | mandatory | mandatory |
| logrotate | optional | mandatory | mandatory |
| keepalived | optional | optional | mandatory |
| aptconf | optional | optional | optional |
[edit]
Problems
The main issue has to do with newlines:
- We want newlines to be allowed, optionally, in most places;
- We would like newlines to be placed by default in most places;
- We don't want newlines to conflict with empty lines;
- When a comment is put right after the lbracket, where should it be mapped?


