2.6.1 Évaluation d’un contexte (GNU LilyPond – Extension des fonctionnalités)

#### 2.6.1 Évaluation d’un contexte

Un contexte peut être modifié, au moment même de son interprétation, par du code Scheme. La syntaxe consacrée au sein d’un bloc LilyPond est

    \applyContext fonction

et, dans le cadre d’un code Scheme :

    (make-apply-context fonction)

`fonction` est constitué d’une fonction Scheme comportant un unique argument : le contexte au sein duquel la commande `\applyContext` est appelée. Cette fonction peut accéder aussi bien aux propriétés de grob (y compris modifiées par `\override` ou `\set`) qu’aux propriétés de contexte. Toute action entreprise par la fonction et qui dépendrait de l’état du contexte sera limitée à l’état de ce contexte au moment de l’appel à la fonction. Par ailleurs, les adaptations résultant d’un appel à `\applyContext` seront effectives jusqu’à ce qu’elles soient à nouveau directement modifiées ou bien annulées, quand bien même les conditions initiales dont elles dépendent auraient changé.

Voici quelques fonctions Scheme utiles avec `\applyContext` :

`ly:context-property`

  recherche la valeur d’une propriété de contexte,

`ly:context-set-property!`

  détermine une propriété de contexte,

`ly:context-grob-definition`
`ly:assoc-get`

  recherche la valeur d’une propriété de grob,

`ly:context-pushpop-property`

  réalise un `\temporary \override` ou un `\revert` sur une propriété de grob.

L’exemple suivant recherche la valeur en cours de `fontSize` puis la double :

>     doubleFontSize =
>     \applyContext
>       #(lambda (context)
>          (let ((fontSize (ly:context-property context 'fontSize)))
>            (ly:context-set-property! context 'fontSize (+ fontSize 6))))

>     {
>       \set fontSize = -3
>       b'4
>       \doubleFontSize
>       b'
>     }

L’exemple suivant recherche la couleur des objets `NoteHead`, `Stem` et `Beam`, puis diminue pour chacun d’eux le degré de saturation.

>     desaturate =
>     \applyContext
>       #(lambda (context)
>          (define (desaturate-grob grob)
>            (let* ((grob-def (ly:context-grob-definition context grob))
>                   (color (ly:assoc-get 'color grob-def black))
>                   (new-color (map (lambda (x) (min 1 (/ (1+ x) 2))) color)))
>              (ly:context-pushpop-property context grob 'color new-color)))
>          (for-each desaturate-grob '(NoteHead Stem Beam)))

>     \relative {
>       \time 3/4
>       g'8[ g] \desaturate g[ g] \desaturate g[ g]
>      \override NoteHead.color = #darkred
>       \override Stem.color = #darkred
>       \override Beam.color = #darkred
>       g[ g] \desaturate g[ g] \desaturate g[ g]
>     }

Ceci pourrait tout à fait s’implémenter sous la forme d’une fonction musicale, afin d’en réduire les effets à un seul bloc de musique. Notez comment `ly:context-pushpop-property` est utilisé à la fois pour un `\temporary \override` et pour un `\revert` :

>     desaturate =
>     #(define-music-function
>        (music) (ly:music?)
>        #{
>          \applyContext
>          #(lambda (context)
>             (define (desaturate-grob grob)
>               (let* ((grob-def (ly:context-grob-definition context grob))
>                      (color (ly:assoc-get 'color grob-def black))
>                      (new-color (map (lambda (x) (min 1 (/ (1+ x) 2))) color)))
>                 (ly:context-pushpop-property context grob 'color new-color)))
>             (for-each desaturate-grob '(NoteHead Stem Beam)))
>          #music
>          \applyContext
>          #(lambda (context)
>             (define (revert-color grob)
>               (ly:context-pushpop-property context grob 'color))
>             (for-each revert-color '(NoteHead Stem Beam)))
>        #})

>     \relative {
>       \override NoteHead.color = #darkblue
>       \override Stem.color = #darkblue
>       \override Beam.color = #darkblue
>       g'8 a b c
>       \desaturate { d c b a }
>       g b d b g2
>     }

#### 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