[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