On Tue, 2008-07-22 at 00:23 +0200, Kjetil Torgrim Homme wrote:
> I thought I'd try to enhance hosts.aug to recognise all syntactically
> correct /etc/hosts as an introduction to Augeas lenses. This turned
> out to be harder than I thought it would be, even with the help of
> Raphaƫl Pinson and David Lutterkort on IRC :-)
If it's any consolation, handling of whitespace and comments is the most
difficult part of dealing with Augeas - there's a lot of subtelty, much
more than in the bits that directly map some part of inpuit into the
tree.
> The problem with the version in 0.2.2 (and Hg) is that it neither
> accepts leading white space nor comments after records, ie. this is
> valid, but Augeas fails silently if fed the file:
>
> # This is a comment
> 127.0.0.1 localhost loghost # another comment
> 192.168.0.1 my-gw.local
> ...
> First I tried to allow trailing comments by changing:
>
> let record = [ seq "host" . [ label "ipaddr" . store word ] . sep_tab .
> [ label "canonical" . store word ] .
> [ label "alias" . sep_spc . store word ]*
> . comment ]
>
> comment is a true superset of eol, after all. This sort of works,
> since it allows "127.0.0.1 localhost# a comment", but will fail if you
> put whitespace in front of the comment. So let's try:
>
> let record = [ seq "host" . [ label "ipaddr" . store word ] . sep_tab .
> [ label "canonical" . store word ] .
> [ label "alias" . sep_spc . store word ]*
> . sep_spc? . comment ]
>
> No -- it doesn't work, since the whitespace could be part of sep_spc
> or of comment, and ambiguity isn't allowed. Let's revert the
> definition of record back to the original and change comment instead:
>
> let comment = [ del /[ \t]*(#.*)?\n/ "\n" ]
>
> It can parse the file! Nice. OK, next task, allow leading whitespace:
>
> let record = [ sep_spc?
> . seq "host" . [ label "ipaddr" . store word ] . sep_tab .
> [ label "canonical" . store word ] .
> [ label "alias" . sep_spc . store word ]*
> . comment ]
There's two subtle problems with the above:
* Because 'comment' produces a tree node, whenever you create a
new entry in the tree, you also have to have a node for the
comment in the tree, no matter what. (This is the source of the
'short split in concat' error you got)
* sep_spc defaults to a single space " ", so that when you write
the tree back to file, you often wind up with a leading space
where there was none before
Attached is a patch (against hg HEAD) that does what you want.
Also, for trying out changes to lenses, I highly recommend using
augparse, and adding/expanding unit tests. For example, for your hosts
change, you could have run
augparse -I lenses/ lenses/tests/test_hosts.aug
(assuming your changed Hosts module is in lenses/hosts.aug)
David
diff --git a/lenses/hosts.aug b/lenses/hosts.aug
--- a/lenses/hosts.aug
+++ b/lenses/hosts.aug
@@ -5,15 +5,17 @@
let sep_tab = Util.del_ws_tab
let sep_spc = Util.del_ws_spc
+ let opt_sep_spc = del /[ \t]*/ ""
let eol = Util.del_str "\n"
- let comment = [ del /(#.*|[ \t]*)\n/ "\n" ]
+ let del_comment = del /[ \t]*(#.*)?\n/ "\n"
+ let comment = [ del_comment ]
let word = /[^# \n\t]+/
- let record = [ seq "host" . [ label "ipaddr" . store word ] . sep_tab .
+ let record = [ opt_sep_spc . seq "host" . [ label "ipaddr" . store word ] . sep_tab .
[ label "canonical" . store word ] .
[ label "alias" . sep_spc . store word ]*
- . eol ]
+ . del_comment ]
let lns = ( comment | record ) *
diff --git a/lenses/tests/test_hosts.aug b/lenses/tests/test_hosts.aug
--- a/lenses/tests/test_hosts.aug
+++ b/lenses/tests/test_hosts.aug
@@ -51,6 +51,13 @@
{ "canonical" = "etch.example.com" }
{ "alias" = "etch" } }
+ test Hosts.lns get "# Some comment
+ \t 127.0.0.1 localhost # my own machine\n \t \n" =
+ {}
+ { "1"
+ { "ipaddr" = "127.0.0.1" }
+ { "canonical" = "localhost" } }
+ {}
(* Local Variables: *)
(* mode: caml *)
_______________________________________________
augeas-devel mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/augeas-devel