Adaptation d’une commande incorporée (GNU LilyPond – Extension des fonctionnalités)

#### Adaptation d’une commande incorporée

Le meilleur moyen de construire ses propres commandes de markup consiste à prendre exemple sur les commandes déjà incorporées. La plupart des commandes de markup fournies avec LilyPond sont répertoriées dans le fichier `scm/define-markup-commands.scm`.

Nous pourrions, par exemple, envisager d’adapter la commande `\draw-line` pour dessiner plutôt une ligne double. Voici comment est définie la commande `\draw-line`, expurgée de sa documentation :

    (define-markup-command (draw-line layout props dest)
      (number-pair?)
      #:category graphic
      #:properties ((thickness 1))
      "…documentation…"
      (let ((th (* (ly:output-def-lookup layout 'line-thickness)
                   thickness))
            (x (car dest))
            (y (cdr dest)))
        (make-line-stencil th 0 0 x y)))

Avant de définir notre propre commande basée sur l’une de celles fournies par LilyPond, commençons par en recopier la définition, puis attribuons lui un autre nom. Le mot-clé `#:category` peut être supprimé sans risque ; il ne sert que lors de la génération de la documentation et n’est d’aucune utilité pour une commande personnalisée.

    (define-markup-command (draw-double-line layout props dest)
      (number-pair?)
      #:properties ((thickness 1))
      "…documentation…"
      (let ((th (* (ly:output-def-lookup layout 'line-thickness)
                   thickness))
            (x (car dest))
            (y (cdr dest)))
        (make-line-stencil th 0 0 x y)))

Nous ajoutons ensuite une propriété pour gérer l’écart entre les deux lignes, que nous appelons `line-gap`, et lui attribuons une valeur par défaut de 6 dixièmes :

    (define-markup-command (draw-double-line layout props dest)
      (number-pair?)
      #:properties ((thickness 1)
                    (line-gap 0.6))
      "…documentation…"
      …

Nous ajoutons enfin le code qui dessinera nos deux lignes. Deux appels à `make-line-stencil` permettrons de dessiner les lignes dont nous regrouperons les stencils à l’aide de `ly:stencil-add` :

>     #(define-markup-command (my-draw-line layout props dest)
>       (number-pair?)
>       #:properties ((thickness 1)
>                     (line-gap 0.6))
>       "..documentation.."
>       (let* ((th (* (ly:output-def-lookup layout 'line-thickness)
>                     thickness))
>              (dx (car dest))
>              (dy (cdr dest))
>              (w (/ line-gap 2.0))
>              (x (cond ((= dx 0) w)
>                       ((= dy 0) 0)
>                       (else (/ w (sqrt (+ 1 (* (/ dx dy) (/ dx dy))))))))
>              (y (* (if (< (* dx dy) 0) 1 -1)
>                    (cond ((= dy 0) w)
>                          ((= dx 0) 0)
>                          (else (/ w (sqrt (+ 1 (* (/ dy dx) (/ dy dx))))))))))
>          (ly:stencil-add (make-line-stencil th x y (+ dx x) (+ dy y))
>                          (make-line-stencil th (- x) (- y) (- dx x) (- dy y)))))

>     \markup \my-draw-line #'(4 . 3)
>     \markup \override #'(line-gap . 1.2) \my-draw-line #'(4 . 3)

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