[augeas-devel] [Interfaces] Draft lense
Free Ekanayaka
free at 64studio.com
Wed Aug 20 12:36:20 UTC 2008
Hi Raphaël,
thanks a lot for your comments!
|--==> Raphaël Pinson writes:
[...]
RP> Nicolas Valcarcel (aka nxvl) was already working on this lens, so I'm sure
RP> he will be interested in it.
Oh, I didn't now it. Is his work already committed somewhere? I would
be glad to collaborate.
RP> Please paste the contents of the files in the mails, it makes it easier to
RP> comment.
Sure, I'll do.
RP> =========================================================
>>module Interfaces =
>>autoload xfm
>>
>>(* Define useful primitives *)
>>let eol = del /[ \t]*\n/ "\n"
RP> You can also use Util.eol for this.
Ok, cool. It seems it was not yet present in version 0.3.0, but works
perfectly with the mercurial head.
>>
>>>let value_to_eol = store /([^ \t\n].*[^ \t\n]|[^ \t\n])/
>>>let value_to_spc = store /[^, \t\n]+/
>>>let spc = Util.del_ws_spc
>>>
>>>(* Define comment *)
>>>let comment = [ del /(#.*\n|[ \t]*\n)/ "# " ]
>>>
>>
RP> I tend to prefer mapping comments in the tree. There has been quite a few
RP> patches to do that in older lenses lately, so it's in hg for most of them.
RP> In your case, you could probably use Util.comment.
Ok, fixed.
>>(* Define a generic entry *)
>>>let entry (l:string) = [ spc . label l . value_to_spc ]
>>>
>>>(* Define a stanza type *)
>>>let type (t:string) = del t t . entry t
>>>
>>
RP> It seems to me that all this is equivalent to
RP> let entry (l:string) = [ key l . spc . value_to_spc ]
RP> Maybe you should use Util.indent instead of Util.del_opt_ws (aka spc for
RP> you) here, since Util.del_opt_ws will insert a space before new entries by
RP> default.
If I simply replace Util.del_opt_ws with Util.indent, I get a series
of errors like this one:
lenses/interfaces.aug:26.3-.80:Failed to compile option
lenses/interfaces.aug:26.18-.72:exception: ambiguous concatenation
'ifacA' can be split into
'ifa|=|cA'
and
'ifac|=|A'
First lens: lenses/interfaces.aug:26.18-.57
Second lens: lenses/interfaces.aug:9.22-.59
Should I change something else too?
>>(* Define a iface stanza *)
>>>let option = [ spc . key /([a-z]|-)+/ . spc . value_to_eol . eol ]
>>>let iface = type "iface" . entry "family" . entry "method" . eol .
>>>option*
>>>
>>
RP> And there I see why you "have to" indent options. The best way around would
RP> probably be to specify the list of known options, or at least specify that
RP> options cannot be "iface", "family" or "method".
I think the latter is better, because there are many options and even
more can be added by packages like wireless-tools.
[...]
>>(* Define a auto stanza *)
>>>let auto = type "auto". (entry "auto")* . eol
>>>
>>
RP> Ah, now that explains the trick with type & entry :)
:)
A bit hackish though, I think I'll change that.
>>(* Note that allow-auto and auto are synonims *)
>>>let allow_auto = type "allow-auto". (entry "allow-auto")* . eol
>>>
>>
RP> You could also have
RP> let type (r:regexp) (t:string) = del r t . entry
RP> And then
RP> let auto = type /(allow_)?auto/ "auto" (entry "auto")* . eol
RP> If these are stricly equivalent. This way, allow_auto and auto will be
RP> parsed equally, but the type will default to "auto".
Yes, I had thought it too, but didn't find a way to do it. I tried
your hint, but I'm getting an error like:
lenses/interfaces.aug:21.46-.51:type error: expected string, regexp, lens, or filter but found string -> lens
I will try to sort it out.
>>(* Define a allow-hotplug stanza *)
>>>let allow_hotplug = type "allow-hotplug". (entry "allow-hotplug")* .
>>>eol
>>>
>>
RP> And that would become
RP> let allow_hotplug = type "allow-hotplug" "allow-hotplug" . (entry
RP> "allow-hotplug")* . eol
RP> Maybe you could make a generic function for this kind of syntax
RP> let type_gen (r:regexp) (t:string) = type r t . (entry t)* . eol
RP> let auto = type_gen /(allow_)?auto/ "auto"
RP> let allow_hotplug = type_gen "allow-hotplug" "allow-hotplug"
Good idea.
[...]
RP> You don't have to number nodes like this. It actually makes it a bit
RP> confusing to parse
RP> { "1"
RP> { "auto" = "lo" }
RP> { "auto" = "eth0" } }
RP> { "2"
RP> { "allow-hotplug" = "eth1" }}
RP> {}
RP> { "3"
RP> { "iface" = "lo" }
RP> { "family" = "inet"}
RP> { "method" = "loopback"} }
RP> if more complicated than
RP> { "auto" = "lo" }
RP> { "auto" = "eth0" }
RP> { "allow-hotplug" = "eth1" }
RP> {}
RP> {"iface"
RP> { "name" = "lo" }
RP> { "family" = "inet"}
RP> { "method" = "loopback"} }
RP> which is much easier to parse with xpath. This means that iface could be
RP> rewritten as
RP> let iface = label "iface" . entry "name" . entry "family" . entry "method" .
RP> eol . option*
RP> and the same with other sections.
Initially I planned to do it like you suggest (without seq), and it
was easy to do for records like iface. However I'm having difficulties
with the auto construct, which can accept more than one interface,
like:
auto lo eth0
which I can't really turn to:
{ "auto" = "lo" }
{ "auto" = "eth0" } }
I've tried with:
let entry (l:string) = [ spc . label l . value_to_spc ]
let auto = del "auto" "auto" . (entry "auto")+ . eol
but I get:
lenses/interfaces.aug:31.13-.42:exception: ambiguous tree iteration
'auto/auto/' can be split into
'auto/|=|auto/'
and
'auto/auto/|=|'
Note that using concatenation instead of repetition does work:
let auto = del "auto" "auto" . entry "auto" . entry "auto" . eol
but of course it hard-wires the number of parameters. I'm a bit
confused here.
>>(* Define lens *)
>>>let lns = ( comment | stanza )*
>>
>>
RP> Have you tried putting comments in the middle of stanzas ?
RP> It seems to me that the option field could be a comment aswell.
I did not try, it problably needs to be fixed.
RP> A very good first lens :)
:)
RP> Known issues:
>>
>>1) Options after an iface or mapping stanza must start with a space or
>>a tab, like:
>>
>>iface eth0-home inet static
>>address 192.168.1.1
>>
>>otherwise the parse will fail. Note this is not strictly required by
>>the official format, but I did not find a clean way to support it.
>>
RP> I believe this should be addressed by the comments above.
Yes, I think so.
>>2) The official format support splitting long lines using a \ at the
>>end of the line, this not supported by the lense yet.
>>
RP> You can have a look at sudoers.aug in hg, which supports this (thanks to
RP> David) with
RP> let sep = del /([ \t]+|[ \t]*\\\\\n[ \t]*)/ " "
RP> This will take care of \ everywhere there could be a space, which should be
RP> enough in real life (I've never seen someone putting a \ in the middle of a
RP> value).
Thanks again, I'll have a look at it.
For the moment I'm mostly interested in solving the issue with the
"auto" stanza, so that I can remove the numbering.
Ciao!
Free
More information about the augeas-devel
mailing list