Précédent: Services Shepherd, Monter: Définir des services [Table des matières][Index]
Certains programmes peuvent avoir des fichiers ou des formats de
configuration complexes, et pour rendre plus simple la création de liaisons
Scheme pour ces fichiers de configuration, vous pouvez utiliser les fonction
auxiliaires définies dans le modules (gnu services configuration)
.
The main utility is the define-configuration
macro, a helper used to
define a Scheme record type (voir Record Overview dans GNU Guile
Reference Manual). The fields from this Scheme record can be serialized
using serializers, which are procedures that take some kind of Scheme
value and translates them into another Scheme value or G-Expressions.
Crée un type d’enregistrement nommé nom
qui contient les champs
qui se trouvent dans les clauses.
A clause has the following form:
(field-name type-decl documentation option* …)
nom-du-champ est un identifiant qui dénote le nom du champ dans l’enregistrement généré.
type-decl is either type
for fields that require a value
to be set or (type default-value)
otherwise.
type est le type de valeur correspondant à nom-du-champ ; comme
Guile n’est pas typé, une procédure de prédicat — type?
—
sera appelée avec la valeur correspondant au champ pour s’assurer que la
valeur est du type correct. Cela signifie que si type est
package
, alors une procédure nommée package?
sera appliquée
sur la valeur pour s’assurer que c’est bien un objet <package>
.
valeur-par-défaut est la valeur par défaut correspondant au champ ; si aucune n’est spécifiée, l’utilisateur ou l’utilisatrice doit fournir une valeur à la création d’un objet de ce type d’enregistrement.
documentation est une chaine formatée avec la syntaxe de Texinfo qui fournit une description de ce que ce champ de configuration signifie.
option* is one of the following subclauses:
empty-serializer
Exclude this field from serialization.
(serializer serializer)
serializer is the name of a procedure which takes two arguments, the
first is the name of the field, and the second is the value corresponding to
the field. The procedure should return a string or G-Expressions that
represents the content that will be serialized to the configuration file.
If none is specified, a procedure of the name serialize-type
will be used.
An example of a simple serializer procedure:
(define (serialize-boolean field-name value)
(let ((value (if value "true" "false")))
#~(string-append '#$field-name " = " #$value)))
(sanitizer sanitizer)
sanitizer is a procedure which takes one argument, a user-supplied value, and returns a “sanitized” value for the field. If no sanitizer is specified, a default sanitizer is used, which raises an error if the value is not of type type.
An example of a sanitizer for a field that accepts both strings and symbols looks like this:
(define (sanitize-foo value)
(cond ((string? value) value)
((symbol? value) (symbol->string value))
(else (error "bad value"))))
Dans certains cas plusieurs enregistrements de configuration différents
peuvent être définis dans le même fichier, mais leurs sérialiseurs pour le
même type peuvent devoir être différents, à cause de formats de
configuration différents. Par exemple, la procédure serialize-boolean
pour le service Getmail doit être différente de celle pour le service
Transmission. Pour faciliter cette situation, on peut spécifier un préfixe
pour sérialiseur en utilisant le littéral prefix
dans la forme
define-configuration
. Cela signifie qu’on n’a pas à spécifier
manuellement un sérialiseur personnalisé pour chaque champ.
(define (toto-serialize-string field-name value) …) (define (titi-serialize-string field-name value) …) (define-configuration foo-configuration (label string "The name of label.") (prefix foo-)) (define-configuration bar-configuration (ip-address string "The IPv4 address for this device.") (prefix bar-))
Cependant, dans certains cas vous ne voudrez pas sérialiser les valeurs de
l’enregistrement. Pour cela, vous pouvez utiliser le littéral
no-serialization
. Il y a aussi la macro
define-configuration/no-serialization
qui est un raccourci.
Parfois un champ ne devrait pas être sérialisé si l’utilisateur ou
l’utilisatrice de spécifie par de valeur. Pour cela, vous pouvez utiliser la
macro define-maybe
pour définir un « type peut-être » ; si la valeur
d’un type peut-être n’est pas spécifiée, ou est indiquée à
%unset-value
, elle n’est pas sérialisée.
Lorsque vous définissez un « type peut-être », le sérialiseur correspondant
au type normal sera utilisé par défaut. Par exemple, un champ de type
maybe-string
sera sérialisé avec la procédure serialize-string
par défaut, vous pouvez évidemment changer cela en spécifiant une procédure
de sérialisation personnalisée. De la même manière, le type de la valeur
doit être une chaine, ou la valeur doit rester non spécifiée.
(define-maybe string) (define (serialize-string field-name value) …) (define-configuration tata-configuration (name ;; Si c'est une chaine, la procédure « serialize-string » sera utilisée ;; pour sérialiser la chaine. Sinon ce champ n'est pas sérialisé maybe-string "Le nom de ce module."))
Comme avec define-configuration
, on peut indiquer un préfixe pour le
nom de sérialiseur en utilisant le littéral prefix
.
(define-maybe integer (prefix tata-)) (define (tata-serialize-integer field-name value) …)
Il y a aussi le littéral no-serialization
, qui s’il est utilisé
indique qu’aucun sérialiseur ne sera défini pour le « type peut-être »,
indépendamment de si la valeur est indiquée ou
non. define-maybe/no-serialization
est un raccourci pour spécifier le
littéral no-serialization
.
(define-maybe/no-serialization symbol) (define-configuration/no-serialization test-configuration (mode maybe-symbol "Docstring."))
Prédicat pour vérifier si l’utilisateur ou l’utilisatrice a spécifié la valeur d’un champ peut-être.
Renvoie une G-expression qui contient les valeurs correspondant aux
champs de configuration, un enregistrement qui a été généré par
define-configuration
. La G-expression peut ensuite être sérialisée
vers le disque en utilisant par exemple mixed-text-file
.
Une fois que vous avez défini un enregistrement de configuration, vous voudrez aussi sans doute le documenter pour que d’autres personnes sachent comment l’utiliser. Pour vous aider, il y a deux procédure qui sont documentées plus bas.
Génère un fragment Texinfo à partir de docstrings dans documentation,
une liste de (étiquette champs sous-documentation
…)
. étiquette devrait être un symbole et devrait être le nom de
l’enregistrement de configuration. champs devrait être une liste de
tous les champs disponibles pour l’enregistrement de configuration.
sub-documentation is a (field-name
configuration-name)
tuple. field-name is the name of the field
which takes another configuration record as its value, and
configuration-name is the name of that configuration record. The same
value may be used for multiple field-names, in case a field accepts
different types of configurations.
sous-documentation n’est requis que s’il y a des enregistrements de
configuration imbriqués. Par exemple, l’enregistrement
getmail-configuration
(voir Services de courriels) accepte un
enregistrement getmail-configuration-file
dans l’un de ses champs
rcfile
, donc la documentation de getmail-configuration-file
est imbriquée dans getmail-configuration
.
(generate-documentation
`((getmail-configuration ,getmail-configuration-fields
(rcfile getmail-configuration-file))
…)
'getmail-configuration)
nom-de-documentation devrait être un symbole et devrait être le nom de l’enregistrement de configuration.
Prend configuration-symbol, le symbole correspondant au nom utilisé
pour définir un enregistrement de configuration avec
define-configuration
, et affiche la documentation Texinfo pour ses
champs. Cette procédure est utile s’il n’y a pas d’enregistrement de
configuration imbriqué car elle n’affiche que la documentation des champs de
plus haut niveau.
Actuellement, il n’y a pas de manière automatique de générer la
documentation pour les enregistrements de configuration et les ajouter au
manuel. Au lieu de cela, chaque fois que vous faites un changement dans les
docstrings d’un enregistrement de configuration, vous devez appeler
manuellement generate-documentation
ou
configuration->documentation
et coller la sortie dans le fichier
doc/guix.texi.
Ci-dessous se trouve un exemple d’un type d’enregistrement créé avec
define-configuration
et compagnie.
(use-modules (gnu services) (guix gexp) (gnu services configuration) (srfi srfi-26) (srfi srfi-1)) ;; Transforme les noms de champs, qui sont des symboles Scheme, en chaines (define (uglify-field-name field-name) (let ((str (symbol->string field-name))) ;; field? -> is-field (if (string-suffix? "?" str) (string-append "is-" (string-drop-right str 1)) str))) (define (serialize-string field-name value) #~(string-append #$(uglify-field-name field-name) " = " #$value "\n")) (define (serialize-integer field-name value) (serialize-string field-name (number->string value))) (define (serialize-boolean field-name value) (serialize-string field-name (if value "true" "false"))) (define (serialize-contact-name field-name value) #~(string-append "\n[" #$value "]\n")) (define (list-of-contact-configurations? lst) (every contact-configuration? lst)) (define (serialize-list-of-contact-configurations field-name value) #~(string-append #$@(map (cut serialize-configuration <> contact-configuration-fields) value))) (define (serialize-contacts-list-configuration configuration) (mixed-text-file "contactrc" #~(string-append "[Owner]\n" #$(serialize-configuration configuration contacts-list-configuration-fields)))) (define-maybe integer) (define-maybe string) (define-configuration contact-configuration (name string "The name of the contact." serialize-contact-name) (phone-number maybe-integer "The person's phone number.") (email maybe-string "The person's email address.") (married? boolean "Whether the person is married.")) (define-configuration contacts-list-configuration (name (string) "Le nom du propriétaire de cette liste de contacts.") (email (string) "L'adresse de courriel du propriétaire.") (contacts (list-of-contact-configurations '()) "Une liste d'enregistrements @code{contact-configuration} qui contiennent des informations sur tous vos contacts."))
Une configuration de liste de contacts pourrait alors être créée de cette manière :
(define my-contacts
(contacts-list-configuration
(name "Alice")
(email "alice@example.org")
(contacts
(list (contact-configuration
(name "Bob")
(phone-number 1234)
(email "bob@gnu.org")
(married? #f))
(contact-configuration
(name "Charlie")
(phone-number 0000)
(married? #t))))))
Après la sérialisation de la configuration sur le disque, le fichier qui en résulte ressemble à ceci :
[owner] name = Alice email = alice@example.org [Bob] phone-number = 1234 email = bob@gnu.org is-married = false [Charlie] phone-number = 0 is-married = true
Précédent: Services Shepherd, Monter: Définir des services [Table des matières][Index]