Hi Ian,

Thank you very much for your reply and your help.
I wrote my replies after the quotes.

Ian Eure <[email protected]> writes:
> Sébastien Gendre <[email protected]> writes:
>>     ;; Define serializer functions
>>     (define (serialize-luanti-admin-name field-name value)
>>       "Serialize the Luanti admin name field for the config
>> file."
>>       (let ((field-real-name "name"))
>>         #~(string-append #$field-real-name " = " #$value)))
>
> Since you’re only building strings, you don’t need a gexp, nor do you
> need the let binding.  Here’s a simplified version:
>
>    (define (serialize-luanti-admin-name _ value)
>      "Serialize the Luanti admin name field for the config file."
>      (string-append "name = " #$value))

Thank you very much. I'm still very new with gexp. The
`define-configuration' documentation was saying that the serializer
procedure should return a gexp. But if it can be done without gexp, that
make it easy.


>>     ;; Define the Luanti Game configuration
>>     (define-configuration luanti-game-configuration
>>       (admin-name
>>        maybe-string
>>        "Username of the administrator."
>>        (serializer serialize-luanti-admin-name)))
>
> This is mixing an optional predicate with a required serializer, which
> won’t work right.  While it’s boilerplatey, I find that the best
> approach is to make one type per field:
>
>    (define admin-name? string?)
>    (define (serialize-admin-name field-name value) "do the right
>    thing here")
>
> Then use `define-maybe' and the predicate & serializer it expands to:
>
>    (define-maybe admin-name)
>
>    (define-configuration luanti-game-configuration
>      (admin-name maybe-admin-name "Username of the
>      administrator."))
>
> Within the configuration system, "type" covers both the value *and*
> how it’s handled, which can cause problems when you have two fields
> which take string, but need different serialize-string handling --
> like one needing to be quoted, or one representing an INI-style
> [section] and another a key = value pair.  Starting here gives you
> clean separation you can merge later, if you like.

I thought that I could use an existing type (string) and only specify a
specific serializer for this parameter. An then, define a generic string
serializer for the simple string parameters.

When I define a maybe and a serializer procedure for a type, the
serializer procedure didn't have to adapt its behavior based on the
"maybe" part ? Like returning something only if the value is not empty ?


>>     ;; Define Luanti game configuration file generator
>>     (define (minetest.conf config)
>>       "Return the Luanti config file."
>>       (plain-file "minetest.conf"
>>        (with-output-to-string
>>          (lambda ()
>>            (serialize-configuration
>>             config
>>             luanti-game-configuration-fields)))))
>
> This is the crux of your problem.  The `with-output-to-string'
> procedure captures any value *printed* and returns it as a string.
> Your lambda doesn’t print anything, because `serialize-configuration'
> doesn’t print anything, it returns a value.  Since there’s no output,
> `with-output-to-string' returns an empty string, and `plain-file' puts
> that in your minetest.conf. Whoops.

I took inspiration of `libvirt-conf-file' (in file
gnu/services/virtualization.scm:486). How is it working in the case of
`libvirt-conf-file' ? Is it only working in the context of a system
service activation ?


> The procedure should be:
>
>    ;; Define Luanti game configuration file generator
>    (define (minetest.conf config)
>      "Return the Luanti config file."
>      (mixed-text-file
>       "minetest.conf"
>       (serialize-configuration config
>       luanti-game-configuration-fields)))
>
> Note that if your serializers use gexps, you will need to build the
> mixed-text-file to see anything.  If you’ve used the (guix) module in
> your Guile REPL, you can do this with:
>
>    ,build (minetest.conf ...)

A great thank you for this part. I was trying to use `mixed-text-file'
at the beginning, but didn't know how to generate the content of the
obtained `computed-file'.


> On a closing note, I’ll share that I’ve also struggled a lot with the
> configuration system in Guix, both in its documentation and
> implementation.  Implementation-wise, the system feels both barebones
> and verbose.  I’ve run into some stuff with unsatisfying expressions,
> like fields whose names aren’t needed, config subsections, and
> configurations spanning multiple files.  These all require workarounds
> which feel more like subverting the system than using it as intended.

I have the same problem. I have more experience with Ansible and it's
template module. I thought that `define-configuration' would serve the
same goal but using Scheme programming instead of template. I bit like
the HTML export backend of Org-mode is, compared to usual template
system of static and dynamic web pages generators.


> On the documentation side, the Guix manual is an invaluable reference,
> but a lot of it feels like just that -- a reference. It has great
> "what" and "how" information, but in my opinion, sorely lacks the
> contextual "why" and "when" to effectively apply it.

Yes, I get what you mean about the manual. I think the contextual "why"
and "when" is more in the cookbook. But, for now, there is no section
about writing a system service step by step. Or a home service. I would
love to help, but my actual understanding of it is not a the required
level to write a good tutorial.

And, about the manual, I noticed that as a new Guix and Guix system
user, I have some difficulties to understand some parts. It's like I
miss an information, or a details, in the manual. But I didn't note it
somewhere, so now it would be difficult to notice it again. At least,
for parts I understand now.

Attachment: signature.asc
Description: PGP signature

Reply via email to