Imported Upstream version 1.7.0
[platform/upstream/augeas.git] / lenses / build.aug
1 (*
2 Module: Build
3    Generic functions to build lenses
4
5 Author: Raphael Pinson <raphink@gmail.com>
6
7 About: License
8   This file is licensed under the LGPL v2+, like the rest of Augeas.
9
10 About: Reference
11   This file provides generic functions to build Augeas lenses
12 *)
13
14
15 module Build =
16
17 let eol = Util.eol
18
19 (************************************************************************
20  * Group:               GENERIC CONSTRUCTIONS
21  ************************************************************************)
22
23 (************************************************************************
24  * View: brackets
25  *   Put a lens inside brackets
26  *
27  *   Parameters:
28  *     l:lens   - the left bracket lens
29  *     r: lens  - the right bracket lens
30  *     lns:lens - the lens to put inside brackets
31  ************************************************************************)
32 let brackets (l:lens) (r:lens) (lns:lens) = l . lns . r
33
34
35 (************************************************************************
36  * Group:             LIST CONSTRUCTIONS
37  ************************************************************************)
38
39 (************************************************************************
40  * View: list
41  *   Build a list of identical lenses separated with a given separator
42  *   (at least 2 elements)
43  *
44  *   Parameters:
45  *     lns:lens - the lens to repeat in the list
46  *     sep:lens - the separator lens, which can be taken from the <Sep> module
47  ************************************************************************)
48 let list (lns:lens) (sep:lens) = lns . ( sep . lns )+
49
50
51 (************************************************************************
52  * View: opt_list
53  *   Same as <list>, but there might be only one element in the list
54  *
55  *   Parameters:
56  *     lns:lens - the lens to repeat in the list
57  *     sep:lens - the separator lens, which can be taken from the <Sep> module
58  ************************************************************************)
59 let opt_list (lns:lens) (sep:lens) = lns . ( sep . lns )*
60
61
62 (************************************************************************
63  * Group:                   LABEL OPERATIONS
64  ************************************************************************)
65
66 (************************************************************************
67  * View: xchg
68  *   Replace a pattern with a different label in the tree,
69  *   thus emulating a key but allowing to replace the keyword
70  *   with a different value than matched
71  *
72  *   Parameters:
73  *     m:regexp - the pattern to match
74  *     d:string - the default value when a node in created
75  *     l:string - the label to apply for such nodes
76  ************************************************************************)
77 let xchg (m:regexp) (d:string) (l:string) = del m d . label l
78
79 (************************************************************************
80  * View: xchgs
81  *   Same as <xchg>, but the pattern is the default string
82  *
83  *   Parameters:
84  *     m:string - the string to replace, also used as default
85  *     l:string - the label to apply for such nodes
86  ************************************************************************)
87 let xchgs (m:string) (l:string) = xchg m m l
88
89
90 (************************************************************************
91  * Group:                   SUBNODE CONSTRUCTIONS
92  ************************************************************************)
93
94 (************************************************************************
95  * View: key_value_line
96  *   A subnode with a keyword, a separator and a storing lens,
97  *   and an end of line
98  *
99  *   Parameters:
100  *     kw:regexp - the pattern to match as key
101  *     sep:lens  - the separator lens, which can be taken from the <Sep> module
102  *     sto:lens  - the storing lens
103  ************************************************************************)
104 let key_value_line (kw:regexp) (sep:lens) (sto:lens) =
105                                    [ key kw . sep . sto . eol ]
106
107 (************************************************************************
108  * View: key_value_line_comment
109  *   Same as <key_value_line>, but allows to have a comment in the end of a line
110  *   and an end of line
111  *
112  *   Parameters:
113  *     kw:regexp    - the pattern to match as key
114  *     sep:lens     - the separator lens, which can be taken from the <Sep> module
115  *     sto:lens     - the storing lens
116  *     comment:lens - the comment lens, which can be taken from <Util>
117  ************************************************************************)
118 let key_value_line_comment (kw:regexp) (sep:lens) (sto:lens) (comment:lens) =
119                                    [ key kw . sep . sto . (eol|comment) ]
120
121 (************************************************************************
122  * View: key_value
123  *   Same as <key_value_line>, but does not end with an end of line
124  *
125  *   Parameters:
126  *     kw:regexp - the pattern to match as key
127  *     sep:lens  - the separator lens, which can be taken from the <Sep> module
128  *     sto:lens  - the storing lens
129  ************************************************************************)
130 let key_value (kw: regexp) (sep:lens) (sto:lens) =
131                                    [ key kw . sep . sto ]
132
133 (************************************************************************
134  * View: key_ws_value
135  *
136  *   Store a key/value pair where key and value are separated by whitespace
137  *   and the value goes to the end of the line. Leading and trailing
138  *   whitespace is stripped from the value. The end of line is consumed by
139  *   this lens
140  *
141  *   Parameters:
142  *     kw:regexp - the pattern to match as key
143  ************************************************************************)
144 let key_ws_value (kw:regexp) =
145   key_value_line kw Util.del_ws_spc (store Rx.space_in)
146
147 (************************************************************************
148  * View: flag
149  *   A simple flag subnode, consisting of a single key
150  *
151  *   Parameters:
152  *     kw:regexp - the pattern to match as key
153  ************************************************************************)
154 let flag (kw:regexp) = [ key kw ]
155
156 (************************************************************************
157  * View: flag_line
158  *   A simple flag line, consisting of a single key
159  *
160  *   Parameters:
161  *     kw:regexp - the pattern to match as key
162  ************************************************************************)
163 let flag_line (kw:regexp) = [ key kw . eol ]
164
165
166 (************************************************************************
167  * Group:                   BLOCK CONSTRUCTIONS
168  ************************************************************************)
169
170 (************************************************************************
171  * View: block_generic
172  *   A block enclosed in brackets
173  *
174  *   Parameters:
175  *     entry:lens                - the entry to be stored inside the block.
176  *                                 This entry should include <Util.empty>
177  *                                 or its equivalent if necessary.
178  *     entry_noindent:lens       - the entry to be stored inside the block,
179  *                                 without indentation.
180  *                                 This entry should not include <Util.empty>
181  *     entry_noeol:lens          - the entry to be stored inside the block,
182  *                                 without eol.
183  *                                 This entry should not include <Util.empty>
184  *     entry_noindent_noeol:lens - the entry to be stored inside the block,
185  *                                 without indentation or eol.
186  *                                 This entry should not include <Util.empty>
187  *     comment:lens              - the comment lens used in the block
188  *     comment_noindent:lens     - the comment lens used in the block,
189  *                                 without indentation.
190  *     ldelim_re:regexp          - regexp for the left delimiter
191  *     rdelim_re:regexp          - regexp for the right delimiter
192  *     ldelim_default:string     - default value for the left delimiter
193  *     rdelim_default:string     - default value for the right delimiter
194  ************************************************************************)
195 let block_generic
196      (entry:lens) (entry_noindent:lens)
197      (entry_noeol:lens) (entry_noindent_noeol:lens)
198      (comment:lens) (comment_noindent:lens)
199      (ldelim_re:regexp) (rdelim_re:regexp)
200      (ldelim_default:string) (rdelim_default:string) =
201      let block_single = entry_noindent_noeol | comment_noindent
202   in let block_start  = entry_noindent | comment_noindent
203   in let block_middle = (entry | comment)*
204   in let block_end    = entry_noeol | comment
205   in del ldelim_re ldelim_default
206      . ( ( block_start . block_middle . block_end )
207        | block_single )
208      . del rdelim_re rdelim_default
209
210 (************************************************************************
211  * View: block_setdefault
212  *   A block enclosed in brackets
213  *
214  *   Parameters:
215  *     entry:lens - the entry to be stored inside the block.
216  *                  This entry should not include <Util.empty>,
217  *                  <Util.comment> or <Util.comment_noindent>,
218  *                  should not be indented or finish with an eol.
219  *     ldelim_re:regexp      - regexp for the left delimiter
220  *     rdelim_re:regexp      - regexp for the left delimiter
221  *     ldelim_default:string - default value for the left delimiter
222  *     rdelim_default:string - default value for the right delimiter
223  ************************************************************************)
224 let block_setdelim (entry:lens)
225                      (ldelim_re:regexp)
226                      (rdelim_re:regexp)
227                      (ldelim_default:string)
228                      (rdelim_default:string) =
229     block_generic (Util.empty | Util.indent . entry . eol)
230                   (entry . eol) (Util.indent . entry) entry
231                   Util.comment Util.comment_noindent
232                   ldelim_re rdelim_re
233                   ldelim_default rdelim_default
234
235 (* Variable: block_ldelim_re *)
236 let block_ldelim_re = /[ \t\n]+\{[ \t\n]*/
237
238 (* Variable: block_rdelim_re *)
239 let block_rdelim_re = /[ \t\n]*\}/
240
241 (* Variable: block_ldelim_default *)
242 let block_ldelim_default = " {\n"
243
244 (* Variable: block_rdelim_default *)
245 let block_rdelim_default = "}"
246
247 (************************************************************************
248  * View: block
249  *   A block enclosed in brackets
250  *
251  *   Parameters:
252  *     entry:lens - the entry to be stored inside the block.
253  *                  This entry should not include <Util.empty>,
254  *                  <Util.comment> or <Util.comment_noindent>,
255  *                  should not be indented or finish with an eol.
256  ************************************************************************)
257 let block (entry:lens) = block_setdelim entry
258                          block_ldelim_re block_rdelim_re
259                          block_ldelim_default block_rdelim_default
260
261 (* Variable: block_ldelim_newlines_re *)
262 let block_ldelim_newlines_re = /[ \t\n]*\{([ \t\n]*\n)?/
263
264 (* Variable: block_rdelim_newlines_re *)
265 let block_rdelim_newlines_re = /[ \t]*\}/
266
267 (* Variable: block_ldelim_newlines_default *)
268 let block_ldelim_newlines_default = "\n{\n"
269
270 (* Variable: block_rdelim_newlines_default *)
271 let block_rdelim_newlines_default = "}"
272
273 (************************************************************************
274  * View: block_newline
275  *   A block enclosed in brackets, with newlines forced
276  *   and indentation defaulting to a tab.
277  *
278  *   Parameters:
279  *     entry:lens - the entry to be stored inside the block.
280  *                  This entry should not include <Util.empty>,
281  *                  <Util.comment> or <Util.comment_noindent>,
282  *                  should be indented and finish with an eol.
283  ************************************************************************)
284 let block_newlines (entry:lens) (comment:lens) =
285    del block_ldelim_newlines_re block_ldelim_newlines_default
286  . ((entry | comment) . (Util.empty | entry | comment)*)?
287  . del block_rdelim_newlines_re block_rdelim_newlines_default
288
289 (************************************************************************
290  * View: block_newlines_spc
291  *   A block enclosed in brackets, with newlines forced
292  *   and indentation defaulting to a tab. The opening brace
293  *   must be preceded by whitespace
294  *
295  *   Parameters:
296  *     entry:lens - the entry to be stored inside the block.
297  *                  This entry should not include <Util.empty>,
298  *                  <Util.comment> or <Util.comment_noindent>,
299  *                  should be indented and finish with an eol.
300  ************************************************************************)
301 let block_newlines_spc (entry:lens) (comment:lens) =
302    del (/[ \t\n]/ . block_ldelim_newlines_re) block_ldelim_newlines_default
303  . ((entry | comment) . (Util.empty | entry | comment)*)?
304  . del block_rdelim_newlines_re block_rdelim_newlines_default
305
306 (************************************************************************
307  * View: named_block
308  *   A named <block> enclosed in brackets
309  *
310  *   Parameters:
311  *     kw:regexp  - the regexp for the block name
312  *     entry:lens - the entry to be stored inside the block
313  *                   this entry should not include <Util.empty>
314  ************************************************************************)
315 let named_block (kw:regexp) (entry:lens) = [ key kw . block entry . eol ]
316
317
318 (************************************************************************
319  * Group:               COMBINATORICS
320  ************************************************************************)
321
322 (************************************************************************
323  * View: combine_two_ord
324  *   Combine two lenses, ensuring first lens is first
325  *
326  *   Parameters:
327  *     a:lens - the first lens
328  *     b:lens - the second lens
329  ************************************************************************)
330 let combine_two_ord (a:lens) (b:lens) = a . b
331
332 (************************************************************************
333  * View: combine_two
334  *   Combine two lenses
335  *
336  *   Parameters:
337  *     a:lens - the first lens
338  *     b:lens - the second lens
339  ************************************************************************)
340 let combine_two (a:lens) (b:lens) =
341   combine_two_ord a b | combine_two_ord b a
342
343 (************************************************************************
344  * View: combine_two_opt_ord
345  *   Combine two lenses optionally, ensuring first lens is first
346  *   (a, and optionally b)
347  *
348  *   Parameters:
349  *     a:lens - the first lens
350  *     b:lens - the second lens
351  ************************************************************************)
352 let combine_two_opt_ord (a:lens) (b:lens) = a . b?
353
354 (************************************************************************
355  * View: combine_two_opt
356  *   Combine two lenses optionally
357  *   (either a, b, or both, in any order)
358  *
359  *   Parameters:
360  *     a:lens - the first lens
361  *     b:lens - the second lens
362  ************************************************************************)
363 let combine_two_opt (a:lens) (b:lens) =
364   combine_two_opt_ord a b | combine_two_opt_ord b a
365
366 (************************************************************************
367  * View: combine_three_ord
368  *   Combine three lenses, ensuring first lens is first
369  *   (a followed by either b, c, in any order)
370  *
371  *   Parameters:
372  *     a:lens - the first lens
373  *     b:lens - the second lens
374  *     c:lens - the third lens
375  ************************************************************************)
376 let combine_three_ord (a:lens) (b:lens) (c:lens) =
377   combine_two_ord a (combine_two b c)
378
379 (************************************************************************
380  * View: combine_three
381  *   Combine three lenses
382  *
383  *   Parameters:
384  *     a:lens - the first lens
385  *     b:lens - the second lens
386  *     c:lens - the third lens
387  ************************************************************************)
388 let combine_three (a:lens) (b:lens) (c:lens) =
389     combine_three_ord a b c
390   | combine_three_ord b a c
391   | combine_three_ord c b a
392
393
394 (************************************************************************
395  * View: combine_three_opt_ord
396  *   Combine three lenses optionally, ensuring first lens is first
397  *   (a followed by either b, c, or any of them, in any order)
398  *
399  *   Parameters:
400  *     a:lens - the first lens
401  *     b:lens - the second lens
402  *     c:lens - the third lens
403  ************************************************************************)
404 let combine_three_opt_ord (a:lens) (b:lens) (c:lens) =
405   combine_two_opt_ord a (combine_two_opt b c)
406
407 (************************************************************************
408  * View: combine_three_opt
409  *   Combine three lenses optionally
410  *   (either a, b, c, or any of them, in any order)
411  *
412  *   Parameters:
413  *     a:lens - the first lens
414  *     b:lens - the second lens
415  *     c:lens - the third lens
416  ************************************************************************)
417 let combine_three_opt (a:lens) (b:lens) (c:lens) =
418     combine_three_opt_ord a b c
419   | combine_three_opt_ord b a c
420   | combine_three_opt_ord c b a