Exemple commenté (GNU LilyPond – Extension des fonctionnalités)

#### Exemple commenté

Nous allons, dans cet exemple, nous attacher à encadrer du texte avec un double liseré.

Commençons par construire quelque chose d’approximatif à l’aide d’un simple markup. La lecture de Commandes pour markup nous indique la commande `\box`, qui semble ici appropriée.

>     \markup \box \box HELLO

Dans un souci d’esthétique, nous aimerions que le texte et les encadrements ne soient pas autant accolés. Selon la documentation de `\box`, cette commande utilise la propriété `box-padding`, fixée par défaut à 0,2. Cette même documentation nous indique aussi comment la modifier :

>     \markup \box \override #'(box-padding . 0.6) \box A

L’espacement des deux liserés est cependant toujours trop réduit ; modifions le à son tour :

>     \markup \override #'(box-padding . 0.4) \box
>          \override #'(box-padding . 0.6) \box A

Vous conviendrez que recopier une telle définition de markup deviendra vite fastidieux. C’est pourquoi nous écrivons la commande de markup `double-box` qui prendra un seul argument – le texte. Cette commande se chargera de dessiner les encadrements, en tenant compte des espacements.

    #(define-markup-command (double-box layout props text) (markup?)
      "Dessine un double encadrement autour du texte."
      (interpret-markup layout props
        #{\markup \override #'(box-padding . 0.4) \box
                \override #'(box-padding . 0.6) \box { #text }#}))

ou bien son équivalent

    #(define-markup-command (double-box layout props text) (markup?)
      "Dessine un double encadrement autour du texte."
      (interpret-markup layout props
        (markup #:override '(box-padding . 0.4) #:box
                #:override '(box-padding . 0.6) #:box text)))

`text` est le nom de l’argument de notre commande, et `markup?` son type – l’argument sera identifié comme étant un markup. La fonction `interpret-markup`, utilisée dans la plupart des commandes de markup, construira un stencil à partir de `layout`, `props` et un markup. Dans la seconde variante, ce markup sera construit à l’aide de la macro Scheme `markup` – voir Construction d’un markup en Scheme. La transformation d’une expression `\markup` en expression Scheme est des plus triviales.

Notre commande personnalisée s’utilise ainsi :

    \markup \double-box A

Il serait intéressant de rendre cette commande `double-box` plus souple : les valeurs de `box-padding` sont figées et ne peuvent être modifiées à l’envie. Pareillement, il serait bien de distinguer l’espacement entre les encadrements de l’espacement entre le texte et ses encadrements. Nous allons donc introduire une propriété supplémentaire, que nous appellerons `inter-box-padding`, chargée de gérer l’espacement des encadrements ; `box-padding` ne servira alors que pour l’espacement intérieur. Voici le code adapté à ces évolutions :

    #(define-markup-command (double-box layout props text) (markup?)
      #:properties ((inter-box-padding 0.4)
                    (box-padding 0.6))
      "Dessine un double encadrement autour du texte."
      (interpret-markup layout props
        #{\markup \override #`(box-padding . ,inter-box-padding) \box
                   \override #`(box-padding . ,box-padding) \box
                   { #text } #}))

Ainsi que son équivalent à partir de la macro markup :

    #(define-markup-command (double-box layout props text) (markup?)
      #:properties ((inter-box-padding 0.4)
                    (box-padding 0.6))
      "Dessine un double encadrement autour du texte."
      (interpret-markup layout props
        (markup #:override `(box-padding . ,inter-box-padding) #:box
                #:override `(box-padding . ,box-padding) #:box text)))

C’est ici le mot-clé `#:properties` qui permet de lire les propriétés `inter-box-padding` et `box-padding` à partir de l’argument `props` ; on leur a d’ailleurs fourni des valeurs par défaut au cas où elles ne seraient pas définies.

Ces valeurs permettront alors d’adapter les propriétés de `box-padding` utilisées par les deux commandes `\box`. Vous aurez remarqué, dans l’argument `\override`, la présence de l’apostrophe inversée (```) et de la virgule ; elles vous permettent d’insérer une valeur variable au sein d’une expression littérale.

Notre commande est maintenant prête à servir dans un markup, et les encadrements sont repositionnables.

>     #(define-markup-command (double-box layout props text) (markup?)
>       #:properties ((inter-box-padding 0.4)
>                     (box-padding 0.6))
>       "Draw a double box around text."
>       (interpret-markup layout props
>         #{\markup \override #`(box-padding . ,inter-box-padding) \box
>                   \override #`(box-padding . ,box-padding) \box
>                   { #text } #}))

>     \markup \double-box A
>     \markup \override #'(inter-box-padding . 0.8) \double-box A
>     \markup \override #'(box-padding . 1.0) \double-box A

#### GNU LilyPond – Extension des fonctionnalités v2.26.0 (stable-branch).

- 1 Tutoriel Scheme
  - 1.1 Introduction à Scheme
    - 1.1.1 Le bac à sable de Scheme
    - 1.1.2 Scheme et les variables
    - 1.1.3 Types de données Scheme simples
    - 1.1.4 Types de données Scheme composites
      - Paires
      - Listes
      - Listes associatives (alists)
      - Tables de hachage
    - 1.1.5 Scheme et les calculs
    - 1.1.6 Scheme et les procédures
      - Définition de procédures
      - Prédicats
      - Valeurs de retour
    - 1.1.7 Scheme et les conditions
      - if
      - cond
  - 1.2 Scheme et LilyPond
    - 1.2.1 Syntaxe Scheme dans LilyPond
    - 1.2.2 Variables LilyPond
    - 1.2.3 Débogage de code Scheme
    - 1.2.4 Saisie de variables et Scheme
    - 1.2.5 Import de code Scheme dans LilyPond
    - 1.2.6 Propriétés des objets
    - 1.2.7 Variables LilyPond composites
      - Décalages (offsets)
      - Fractions
      - Étendues (extents)
      - Propriété en alist
      - Chaînes d’alist
    - 1.2.8 Le modèle de boîte de LilyPond
    - 1.2.9 Représentation interne de la musique
  - 1.3 Construction de fonctions complexes
    - 1.3.1 Première approche (exemple)
    - 1.3.2 Affichage d’expressions musicales
    - 1.3.3 Propriétés musicales
    - 1.3.4 Doublement d’une note avec liaison (exemple)
    - 1.3.5 Ajout d’articulation à des notes (exemple)
- 2 Interfaces pour programmeurs
  - 2.1 Blocs de code LilyPond
  - 2.2 Fonctions Scheme
    - 2.2.1 Définition de fonctions Scheme
    - 2.2.2 Utilisation de fonctions Scheme
    - 2.2.3 Fonctions Scheme fantômes
  - 2.3 Fonctions musicales
    - 2.3.1 Définition de fonctions musicales
    - 2.3.2 Utilisation de fonctions musicales
    - 2.3.3 Fonctions de substitution simple
    - 2.3.4 Fonctions de substitution intermédiaires
    - 2.3.5 De l’usage des mathématiques dans les fonctions
    - 2.3.6 Fonctions dépourvues d’argument
    - 2.3.7 Fonctions musicales fantômes
  - 2.4 Fonctions événementielles
  - 2.5 Fonctions pour markups
    - 2.5.1 Construction d’un markup en Scheme
    - 2.5.2 Fonctionnement interne des markups
    - 2.5.3 Définition d’une nouvelle commande de markup
      - Syntaxe d’une commande markup
      - Attribution de propriétés
      - Exemple commenté
      - Adaptation d’une commande incorporée
      - Conversion de markups en chaînes
    - 2.5.4 Définition d’une nouvelle commande de liste de markups
  - 2.6 Contextes pour programmeurs
    - 2.6.1 Évaluation d’un contexte
    - 2.6.2 Application d’une fonction à tous les objets de mise en forme
  - 2.7 Fonctions de rappel
  - 2.8 Conteneurs requalifiants
  - 2.9 Retouches complexes
- 3 Interfaces LilyPond Scheme
- Appendix A GNU Free Documentation License
- Appendix B Index