]> git.donarmstrong.com Git - lilypond.git/blobdiff - Documentation/fr/extending/programming-interface.itely
Merge branch 'master' of /home/jcharles/GIT/Lily/. into translation
[lilypond.git] / Documentation / fr / extending / programming-interface.itely
index a66da00d6c6e37d2a1462ca06e76d0b4894b0b4f..541b744b495f11aee56f7f18f2f4a0ff436d3bca 100644 (file)
 @c -*- coding: utf-8; mode: texinfo; documentlanguage: fr -*-
 
 @ignore
-    Translation of GIT committish: 3f4496001441e0b1b27d7bc5395c4520f4f2088c
+    Translation of GIT committish: e8c4826ed3fca952984600bcce60b53e76aff5d2
 
     When revising a translation, copy the HEAD committish of the
     version that you are working on.  For details, see the Contributors'
     Guide, node Updating translation committishes..
 @end ignore
 
-@c \version "2.14.0"
+@c \version "2.19.22"
 
-@c Translators: Valentin Villenave
-@c Translation checkers: Gilles Thibault, Jean-Charles Malahieude
+@c Translators: Valentin Villenave, Jean-Charles Malahieude
+@c Translation checkers: Gilles Thibault
 
-
-@node Interfaces pour les programmeurs
-@chapter Interfaces pour les programmeurs
+@node Interfaces pour programmeurs
+@chapter Interfaces pour programmeurs
 @translationof Interfaces for programmers
 
-@untranslated
-
+Scheme permet de réaliser des affinages très pointus.  Si vous ne
+connaissez rien de Scheme, vous en aurez un aperçu au travers de notre
+@ref{Tutoriel Scheme}.
 
 @menu
+* Blocs de code LilyPond::
+* Fonctions Scheme::
 * Fonctions musicales::
-* Interfaces de programmation::
-* Construction de fonctions complexes::
-* Interface de programmation des marqueurs de texte::
+* Fonctions événementielles::
+* Fonctions pour markups::
 * Contextes pour programmeurs::
-* Utilisation de procédures Scheme en tant que propriétés::
-* Utilisation de code Scheme au lieu de \"tweak\"::
+* Fonctions de rappel::
 * Retouches complexes::
 @end menu
 
+
+@node Blocs de code LilyPond
+@section Blocs de code LilyPond
+@translationof LilyPond code blocks
+
+@cindex code, blocs LilyPond
+@cindex LilyPond, bloc de code
+
+@funindex #@{ ... #@}
+@funindex $
+@funindex #
+
+L'utilisation de Scheme pour créer des expressions musicales peut
+s'avérer ardue, principalement à cause des imbrications et de la
+longueur du code Scheme qui en résulte.  Dans le cas de tâches
+simples, on peut toutefois contourner une partie du problème en
+utilisant des blocs de code LilyPond, ce qui autorise la syntaxe
+habituelle de LilyPond au sein même de Scheme.
+
+Les blocs de code LilyPond ressemblent à
+
+@example
+  #@{ @var{du code LilyPond} #@}
+@end example
+
+En voici un exemple basique :
+
+@lilypond[verbatim,quote]
+ritpp = #(define-event-function () ()
+  #{ ^"rit." \pp #}
+)
+
+{ c'4 e'4\ritpp g'2 }
+@end lilypond
+
+Les blocs de code LilyPond peuvent s'utiliser partout où vous pouvez
+écrire du code Scheme.  Le lecteur Scheme est en fait quelque peu adapté
+pour accepter des blocs de code LilyPond ; il est capable de traiter des
+expressions Scheme intégrées débutant par @code{$} ou @code{#}.
+
+@cindex parser (fonction argument)
+@cindex location
+
+Le lecteur Scheme extrait le bloc de code LilyPond et déclenche un appel
+à l'analyseur grammatical de LilyPond (le @code{parser}) qui réalise en
+temps réel l'interprétation de ce bloc de code LilyPond.  Toute
+expression Scheme imbriquée est exécutée dans l'environnement lexical du
+bloc de code LilyPond, de telle sorte que vous avez accès aux variables
+locales et aux paramètres de la fonction au moment même où le bloc de
+code LilyPond est écrit.  Les variables définies dans d'autres modules
+Scheme, tels ceux contenant les blocs @code{\header} ou @code{\layout},
+ne sont pas accessibles en tant que variables Scheme (préfixées par
+un @code{#}) mais en tant que variables LilyPond (préfixées par
+un @code{\}).
+
+Lorsque l'emplacement (@code{location} -- voir @ref{Fonctions Scheme})
+fait référence à un endroit valide dans la source -- ce qui est en
+général le cas au sein de fonctions musicales ou Scheme --, toute la
+musique générée au sein de ce bloc de code voit son @code{origine}
+établie à cet @emph{emplacement}.
+
+Un bloc de code LilyPond peut contenir tout ce que vous pourriez mettre
+à droite de l'assignation.  Par ailleurs, un bloc LilyPond vide
+correspond à une expression fantôme, et un bloc LilyPond de multiples
+événements musicaux sera transformé en une expression de musique
+séquentielle.
+
+
+@node Fonctions Scheme
+@section Fonctions Scheme
+@translationof Scheme functions
+
+@cindex Scheme, fonctions (syntaxe LilyPond)
+
+Les @emph{fonctions Scheme} sont des procédures Scheme chargées de créer
+des expressions Scheme à partir de code rédigé selon la syntaxe de
+LilyPond.  Elles peuvent être appelées en de nombreux endroits, à l'aide
+d'un @code{#}, où spécifier une valeur en syntaxe Scheme est autorisé.
+Bien que Scheme dispose de fonctions en propre, nous nous intéresserons,
+au fil des paragraphes qui suivent, aux fonctions @emph{syntaxiques},
+autrement dit des fonctions qui reçoivent des arguments libellés dans la
+syntaxe de LilyPond.
+
+@menu
+* Définition de fonctions Scheme::
+* Utilisation de fonctions Scheme::
+* Fonctions Scheme fantômes::
+@end menu
+
+@node Définition de fonctions Scheme
+@subsection Définition de fonctions Scheme
+@translationof Scheme function definitions
+
+@funindex define-scheme-function
+
+D'une manière générale, une fonction Scheme se définit ainsi :
+
+@example
+fonction =
+#(define-scheme-function
+     (@var{arg1} @var{arg2}@dots{})
+     (@var{type1?} @var{type2?}@dots{})
+   @var{corps})
+@end example
+
+@noindent
+où
+
+@multitable @columnfractions .33 .66
+@item @code{parser}
+@tab doit être littéralement @code{parser}, de telle sorte que
+l'analyseur grammatical puisse accéder aux blocs de code LilyPond
+(@code{#@{}@dots{}@code{#@}}).
+
+@item @code{location}
+@tab doit être littéralement @code{location}, de telle sorte que soit
+accessible l'emplacement de l'objet dans la source, aux fins de
+transmettre aux messages d'erreur les fichier et numéro de ligne.
+
+@item @code{@var{argN}}
+@tab @var{n}ième argument
+
+@item @code{@var{typeN?}}
+@tab un @emph{type de prédicat} Scheme pour lequel @code{@var{argN}}
+devra retourner @code{#t}.  Il existe aussi une forme spécifique --
+@code{(@emph{prédicat?} @emph{default})} -- qui permet de fournir des
+argument optionnels.  En l'absence d'argument réel au moment de l'appel
+à la fonction, c'est la valeur par défaut qui lui sera substituée.  Les
+valeurs par défaut sont évaluées dès l'apparition de la définition, y
+compris dans le cas de blocs de code LilyPond ; vous devrez donc,
+si ces valeurs par défaut ne peuvent être déterminées que plus tard,
+mentionner une valeur spéciale que vous reconnaîtrez facilement.
+Lorsque vous mentionnez un prédicat entre parenthèses sans toutefois
+fournir sa valeur par défaut, celle-ci sera considérée comme
+étant @code{#f}.  Les valeurs par défaut d'un @code{prédicat?} ne sont
+vérifiées ni au moment de la définition, ni à l'exécution ; il est
+de votre ressort de gérer les valeurs que vous spécifiez.  Une valeur
+par défaut constituée d'une expression musicale est recopiée dès la
+définition de @code{origin} vers le paramètre @code{location}.
+
+@item @code{@var{corps}}
+@tab une séquence de formules Scheme évaluées dans l'ordre, la dernière
+servant de valeur de retour de la fonction. Il peut contenir des blocs
+de code LilyPond, enchâssés dans des accolades et @emph{hashes} --
+@w{@code{#@{@dots{}#@}}} -- comme indiqué à la rubrique
+@ref{Blocs de code LilyPond}.  Au sein d'un bloc de code LilyPond, un
+@code{#} permet de référencer des arguments de la fonction -- tel
+@samp{#arg1} -- ou d'ouvrir une expression Scheme contenant les
+arguments de la fonction -- par exemple @w{@samp{#(cons arg1 arg2)}}.
+Dans le cas où une expression Scheme introduite par @code{#} ne vous
+permet pas de parvenir à vos fins, vous pourriez devoir revenir à une
+expression Scheme « immédiate » à l'aide d'un @code{$}, comme
+@samp{$music}.
+
+Lorsque votre fonction retourne une expression musicale, lui est
+attribuée la valeur @code{origin}.
+@end multitable
+
+@noindent
+La recevabilité des arguments est déterminée par un appel effectif au
+prédicat après que LilyPond les a déjà convertis en expression Scheme.
+Par voie de conséquence, l'argument peut tout à fait se libeller en
+syntaxe Scheme -- introduite par un @code{#} ou en tant que résultat
+d'un appel à une fonction Scheme.  Par ailleurs, LilyPond convertira en
+Scheme un certain nombre de constructions purement LilyPond avant même
+d'en avoir vérifié le prédicat.  C'est notamment le cas de la musique,
+des @emph{postévénements}, des chaînes simples (avec ou sans
+guillemets), des nombres, des @emph{markups} et listes de
+@emph{markups}, ainsi que des blocs @emph{score}, @emph{book},
+@emph{bookpart}, ou qui définissent un contexte ou un format de sortie.
+
+Il existe certaines situations pour lesquelles LilyPond lèvera toute
+ambiguïté grâce aux fonctions de prédicat : un @samp{-3} est-il un
+@emph{postévénement} de type doigté ou un nombre négatif ?  Un
+@code{"a" 4} en mode paroles est-il une chaîne suivie d'un nombre ou
+bien un événement syllabe de durée @code{4} ?  LilyPond répondra à ces
+questions par des interprétations successives du prédicat de l'argument,
+dans un ordre défini de sorte à minimiser les interprétations erronées
+et le besoin de lecture en avance.
+
+Un prédicat qui accepte par exemple aussi bien une expression musicale
+qu'une hauteur considèrera @code{c''} comme étant une hauteur plutôt
+qu'une expression musicale.  Les durées ou @emph{postévénements} qui
+viennent juste après viendront modifier cette interprétation.  C'est la
+raison pour laquelle il vaut mieux éviter des prédicats par trop
+permissifs tel que @code{Scheme?} lorsque l'application fait plutôt
+appel à des type d'argument plus spécifiques.
+
+Les différents types de prédicat propres à LilyPond sont recensés à
+l'annexe @ruser{Types de prédicats prédéfinis}.
+
+@seealso
+Manuel de notation :
+@ruser{Types de prédicats prédéfinis}.
+
+Fichiers d'initialisation :
+@file{lily/music-scheme.cc},
+@file{scm/c++.scm},
+@file{scm/lily.scm}.
+
+
+@node Utilisation de fonctions Scheme
+@subsection Utilisation de fonctions Scheme
+@translationof Scheme function usage
+
+Vous pouvez appeler une fonction Scheme pratiquement partout où une
+expression Scheme derrière un @code{#} peut prendre place.  Vous appelez
+une fonction Scheme en faisant précéder son nom d'un @code{\}, et en le
+faisant suivre de ses arguments.  Lorsqu'un prédicat d'argument
+optionnel ne correspond pas à un argument, LilyPond l'ignore ainsi que
+tous les arguments optionnels qui suivent, les remplaçant par leur
+valeur par défaut, et « sauvegarde » en tant que prochain argument
+obligatoire l'argument qui ne correspondait pas.  Dans la mesure où
+l'argument sauvegardé doit servir, les argument optionnels ne sont en
+fait pas considérés comme optionnels, sauf à être suivis d'un argument
+obligatoire.
+
+Une exception cependant à cette règle : le fait de donner un
+@code{\default} en tant qu'argument optionnel aura pour résultat que cet
+argument et tous les autres arguments optionnels qui suivent seront
+ignorés et remplacés par leur valeur par défaut.  Il en va de même
+lorsqu'aucun argument obligatoire ne suit, du fait que @code{\default}
+ne requiert pas de sauvegarde.  C'est d'ailleurs ainsi que fonctionnent
+les commandes @code{mark} et @code{key}, qui retrouvent leur
+comportement par défaut lorsque vous les faites suivre d'un
+@code{\default}.
+
+En plus de là où une expression Scheme est requise, il y a quelques
+endroits où des expressions @code{#} sont acceptées et évaluées
+uniquement pour leurs effets annexes.  Il s'agit, dans la plupart des
+cas, d'endroits où une affectation serait tout à fait envisageable.
+
+Dans la mesure où il n'est pas bon de renvoyer une valeur qui pourrait
+être mal interprétée dans certains contextes, nous vous enjoignons à
+utiliser des fonctions Scheme normales uniquement dans les cas où vous
+renvoyez toujours une valeur utile, et une fonction fantôme -- voir
+@ref{Fonctions Scheme fantômes} -- dans le cas contraire.
+
+
+@node Fonctions Scheme fantômes
+@subsection Fonctions Scheme fantômes
+@translationof Void scheme functions
+
+@cindex @emph{void}, fonction
+@cindex fantôme, fonction
+
+@funindex define-void-function
+@funindex \void
+
+Il arrive qu'une procédure soit exécutée pour réaliser une action, non
+pour renvoyer une valeur.  Certains langages de programmation, tels
+le C et Scheme, utilisent des fonctions dans les deux cas et se
+débarrassent tout bonnement de la valeur renvoyée ; en règle
+générale, il suffit que l'expression fasse office de déclaration, et
+d'ignorer le résultat.  C'est futé, mais pas sans risque d'erreur :
+la plupart des compilateurs C actuels déclenchent un avertissement si
+l'on se débarrasse de certaines expressions non @emph{void}.  Pour de
+nombreuses fonctions réalisant une action, les standards Scheme
+déclarent que la valeur de retour est indéfinie.  L'interpréteur Guile
+qu'utilise le Scheme de LilyPond dispose d'une valeur unique
+@code{*unspecified*} qu'il retourne alors, en règle générale -- notamment
+lorsqu'on utilise @code{set!} directement sur une variable -- mais
+malheureusement pas toujours.
+
+Une fonction LilyPond définie à l'aide de la clause
+@code{define-void-function} vous apporte l'assurance que c'est cette
+valeur spéciale -- la seule valeur qui satisfasse au prédicat
+@code{void?} -- qui sera retournée.
+
+@example
+noPointAndClick =
+#(define-void-function
+     ()
+     ()
+   (ly:set-option 'point-and-click #f))
+@dots{}
+\noPointAndClick   % desactive le "pointer-cliquer"
+@end example
+
+L'utilisation d'un préfixe @code{\void} permet ainsi d'évaluer une
+expression pour ses effets annexes sans interprétation d'une quelconque
+valeur de retour :
+
+@example
+\void #(hashq-set! une-table une-clé une-valeur)
+@end example
+
+Vous serez alors assuré que LilyPond ne tentera pas d'affecter un sens à
+la valeur de retour, à quelque endroit qu'elle ressorte.  Ceci est aussi
+opérationnel dans le cadre de fonctions musicales telles que
+@code{\displayMusic}.
+
+
 @node Fonctions musicales
 @section Fonctions musicales
 @translationof Music functions
 
-@untranslated
+@cindex musicale, fonction
 
+Les @emph{fonctions musicales} sont des procédures Scheme capables de
+créer automatiquement des expressions musicales ; elles permettent
+de grandement simplifier un fichier source.
 
 @menu
-* Aperçu des fonctions musicales::
+* Définition de fonctions musicales::
+* Utilisation de fonctions musicales::
 * Fonctions de substitution simple::
-* Fonctions de substitution par paire::
+* Fonctions de substitution intermédiaires::
 * De l'usage des mathématiques dans les fonctions::
-* Fonctions fantômes::
 * Fonctions dépourvues d'argument::
-* Liste des fonctions musicales prédéfinies::
+* Fonctions musicales fantômes::
 @end menu
 
-@node Aperçu des fonctions musicales
-@subsection Aperçu des fonctions musicales
-@translationof Overview of music functions
 
-@untranslated
+@node Définition de fonctions musicales
+@subsection Définition de fonctions musicales
+@translationof Music function definitions
+
+@cindex fonction musicale, définition
+
+@funindex define-music-function
+
+Une fonction musicale se définit ainsi :
+
+@example
+fonction =
+#(define-music-function
+     (@var{arg1} @var{arg2}@dots{})
+     (@var{type1?} @var{type2?}@dots{})
+   @var{corps})
+@end example
+
+@noindent
+de manière similaire aux @ref{Définition de fonctions Scheme, fonctions
+Scheme}.  La plupart du temps, le @code{corps} sera constitué d'un
+@ref{Blocs de code LilyPond, bloc de code Lilypond}.
+
+Les différents types des prédicat sont recensés à l'annexe
+@ruser{Types de prédicats prédéfinis}.
+
+@seealso
+Manuel de notation :
+@ruser{Types de prédicats prédéfinis}.
+
+Fichiers d'initialisation :
+@file{lily/music-scheme.cc},
+@file{scm/c++.scm},
+@file{scm/lily.scm}.
+
+
+@node Utilisation de fonctions musicales
+@subsection Utilisation de fonctions musicales
+@translationof Music function usage
+
+Une « fonction musicale » doit impérativement renvoyer une expression
+répondant au prédicat @code{ly:music?}.  Ceci a pour conséquence
+d'autoriser l'appel à une fonction musicale en tant qu'argument de type
+@code{ly:music?} dans le cadre de l'appel à une autre fonction musicale.
+
+Certaines restrictions s'appliqueront selon le contexte où une fonction
+musicale est utilisée, de telle sorte que l'analyse syntaxique soit sans
+ambiguïté.
+
+@itemize
+@item
+Dans une expression musicale de haut niveau, aucun postévénement n'est
+toléré.
+
+@item
+Lorsqu'une fonction musicale -- contrairement à une fonction
+événementielle -- renvoie une expression de type postévénement, LilyPond
+requiert son introduction par un indicateur de positionnement -- à
+savoir @code{-}, @code{^} ou @code{_} -- de telle sorte que le
+postévénement produit par l'appel à cette fonction s'intègre
+correctement dans l'expression environnante.
+
+@item
+En tant que partie d'un accord, l'expression musicale renvoyée doit
+être du type @code{rhythmic-event}, et plus particulièrement un
+@code{NoteEvent}.
+@end itemize
+
+@noindent
+Des fonctions « polymorphes » telles que @code{\tweak} peuvent
+s'appliquer aux postévénements, constituants d'accord et expressions de
+haut niveau.
 
 
 @node Fonctions de substitution simple
 @subsection Fonctions de substitution simple
 @translationof Simple substitution functions
 
-@untranslated
+Une fonction de substitution simple renvoie une expression musicale
+écrite au format LilyPond et contient des arguments au format de
+l'expression résultante.  Vous en trouverez une description détaillée à
+la rubrique @ruser{Exemples de fonction de substitution}.
 
 
-@node Fonctions de substitution par paire
-@subsection Fonctions de substitution par paire
-@translationof Paired substitution functions
+@node Fonctions de substitution intermédiaires
+@subsection Fonctions de substitution intermédiaires
+@translationof Intermediate substitution functions
 
-@untranslated
+Une fonction de substitution intermédiaire est une fonction dont
+l'expression musicale résultante mélangera du code Scheme au code
+LilyPond.
+
+Certaines commandes @code{\override} nécessitent un argument
+supplémentaire constitué d'une paire de nombres, appelée @emph{cons
+cell} en Scheme -- que l'on pourrait traduire par « construction de
+cellule ».
+
+Cette paire peut se mentionner directement dans la fonction musicale à
+l'aide d'une variable @code{pair?} :
+
+@example
+manualBeam =
+#(define-music-function
+     (beg-end)
+     (pair?)
+   #@{
+     \once \override Beam.positions = #beg-end
+   #@})
+
+\relative c' @{
+  \manualBeam #'(3 . 6) c8 d e f
+@}
+@end example
+
+Autre manière de procéder, les nombres formant la paire sont transmis
+comme arguments séparés ; le code Scheme chargé de créer la paire
+pourra alors être inclus dans l'expression musicale :
+
+@lilypond[quote,verbatim,ragged-right]
+manualBeam =
+#(define-music-function
+     (beg end)
+     (number? number?)
+   #{
+     \once \override Beam.positions = #(cons beg end)
+   #})
+
+\relative c' {
+  \manualBeam #3 #6 c8 d e f
+}
+@end lilypond
+
+@funindex \temporary
+@cindex temporaire, dérogation (override)
+@cindex dérogation temporaire (override)
+@cindex propriétés, retour à la valeur précédente
+
+L'entretien des propriétés peut se voir comme un empilement par
+propriété par objet par contexte.  Les fonctions musicales peuvent
+nécessiter des dérogations pour une ou plusieurs propriétés pour la
+durée de la fonction, puis de revenir aux valeurs précédentes avant de
+quitter.  Néanmoins, une dérogation normale va retirer de la pile -- ou
+dépiler -- et supprimer le sommet de la pile de la propriété avant
+d'y ajouter quoi que ce soit -- ou empiler -- ; la valeur précédente de
+la propriété est de fait perdue.  Lorsque la valeur antérieure doit être
+préservée, l'instruction @code{\override} devra être préfixée d'un
+@code{\temporary}, comme ceci :
+
+@example
+\temporary \override @dots{}
+@end example
+
+L'utilisation d'un @code{\temporary} a pour effet d'effacer la propriété
+@code{pop-first} (@emph{commence par dépiler} normalement activée) de la
+dérogation ; la valeur antérieure ne sera alors pas supprimée de la pile
+de la propriété avant d'y empiler la nouvelle valeur.  Lorsqu'un
+@code{\revert} viendra par la suite supprimer la valeur dérogatoire
+temporaire, réapparaitra la valeur antérieure.
+
+En d'autres termes, un @code{\revert} qui suit un @code{\temporary
+\override} pour la même propriété n'apporte rien.  Ce principe est aussi
+valable pour un couple @code{\temporary} et @code{\undo} sur la même
+musique contenant des dérogations.
+
+Voici un exemple de fonction musicale utilisant cette fonctionnalité.
+La présence du @code{\temporary} permet de s'assurer qu'en sortant de la
+fonction, les propriétés @code{cross-staff} et @code{style} retrouveront
+les valeurs qu'elles avaient avant que ne soit appelée la fonction
+@code{crossStaff}.  En l'absence de @code{\temporary}, ces propriétés
+auraient retrouvé leurs valeurs par défaut à la sortie de la fonction.
+
+@example
+crossStaff =
+#(define-music-function (notes) (ly:music?)
+  (_i "Create cross-staff stems")
+  #@{
+  \temporary \override Stem.cross-staff = #cross-staff-connect
+  \temporary \override Flag.style = #'no-flag
+  #notes
+  \revert Stem.cross-staff
+  \revert Flag.style
+#@})
+@end example
 
 
 @node De l'usage des mathématiques dans les fonctions
 @subsection De l'usage des mathématiques dans les fonctions
 @translationof Mathematics in functions
 
-@untranslated
+Une fonction musicale peut requérir, en plus d'une simple substitution,
+une part de programmation en Scheme.
 
+@lilypond[quote,verbatim,ragged-right]
+AltOn =
+#(define-music-function
+     (mag)
+     (number?)
+   #{
+     \override Stem.length = #(* 7.0 mag)
+     \override NoteHead.font-size =
+       #(inexact->exact (* (/ 6.0 (log 2.0)) (log mag)))
+   #})
+
+AltOff = {
+  \revert Stem.length
+  \revert NoteHead.font-size
+}
 
-@node Fonctions fantômes
-@subsection Fonctions fantômes
-@translationof Void functions
+\relative {
+  c'2 \AltOn #0.5 c4 c
+  \AltOn #1.5 c c \AltOff c2
+}
+@end lilypond
 
-@untranslated
+@noindent
+Cette fonction pourrait tout à fait être réécrite de telle sorte qu'elle
+s'applique à une expression musicale :
+
+@lilypond[quote,verbatim,ragged-right]
+withAlt =
+#(define-music-function
+     (mag music)
+     (number? ly:music?)
+   #{
+     \override Stem.length = #(* 7.0 mag)
+     \override NoteHead.font-size =
+       #(inexact->exact (* (/ 6.0 (log 2.0)) (log mag)))
+     #music
+     \revert Stem.length
+     \revert NoteHead.font-size
+   #})
+
+\relative {
+  c'2 \withAlt #0.5 { c4 c }
+  \withAlt #1.5 { c c } c2
+}
+@end lilypond
 
 
 @node Fonctions dépourvues d'argument
 @subsection Fonctions dépourvues d'argument
 @translationof Functions without arguments
 
-@untranslated
+Dans la plupart des cas, une fonction dépourvue d'argument devrait
+être créée à l'aide d'une variable :
 
+@example
+dolce = \markup@{ \italic \bold dolce @}
+@end example
 
-@node Liste des fonctions musicales prédéfinies
-@subsection Liste des fonctions musicales prédéfinies
-@translationof Overview of available music functions
+Il peut, dans certains cas particuliers, s'avérer utile de créer une
+fonction sans argument comme ici,
 
-@untranslated
+@example
+displayBarNum =
+#(define-music-function
+     ()
+     ()
+   (if (eq? #t (ly:get-option 'display-bar-numbers))
+       #@{ \once \override Score.BarNumber.break-visibility = ##f #@}
+       #@{#@}))
+@end example
 
+@noindent
+de manière à pouvoir afficher les numéros de mesure grâce à un appel à
+cette fonction.  En pareil cas, vous devrez invoquer @command{lilypond}
+en respectant la syntaxe
 
-@include identifiers.tely
-@node Interfaces de programmation
-@section Interfaces de programmation
-@translationof Programmer interfaces
+@example
+lilypond -d display-bar-numbers MONFICHIER.ly
+@end example
 
-@untranslated
 
+@node Fonctions musicales fantômes
+@subsection Fonctions musicales fantômes
+@translationof Void music functions
 
-@menu
-* Variables d'entrée et Scheme::
-* Représentation interne de la musique::
-@end menu
+Une fonction musicale doit renvoyer une expression musicale.  Toutefois,
+une fonction musicale peut n'être exécutée que dans le but d'en retenir
+les effets annexes ; vous devrez alors utiliser une procédure
+@code{define-void-function}.  Il peut cependant arriver que vous ayez
+besoin d'une fonction qui, selon le cas, produise ou non (comme dans
+l'exemple de la rubrique précédente) une expression musicale.
+L'utilisation d'un @code{#@{ #@}} vous permettra de renvoyer une
+expression musicale @code{void}.
 
-@node Variables d'entrée et Scheme
-@subsection Variables d'entrée et Scheme
-@translationof Input variables and Scheme
 
-@untranslated
+@node Fonctions événementielles
+@section Fonctions événementielles
+@translationof Event functions
 
+@funindex define-event-function
+@cindex événementielle, fonction
 
-@node Représentation interne de la musique
-@subsection Représentation interne de la musique
-@translationof Internal music representation
+L'utilisation d'une fonction musicale pour placer un événement requiert
+l'insertion d'un indicateur de position, ce qui peut ne pas correspondre
+à la syntaxe de la construction à remplacer.  C'est par exemple le cas
+lorsque vous voulez écrire une commande de nuance, instruction qui
+ne comporte habituellement pas d'indicateur de positionnement, comme
+dans @code{c'\pp}.  Voici de quoi vous permettre de mentionner n'importe
+quelle nuance :
 
-@untranslated
+@lilypond[quote,verbatim,ragged-right]
+dyn=#(define-event-function (arg) (markup?)
+         (make-dynamic-script arg))
+\relative { c'\dyn pfsss }
+@end lilypond
 
+Vous pourriez obtenir le même résultat avec une fonction musicale, à
+ceci près que chaque appel à la fonction devra être précédé d'un
+indicateur de positionnement, comme @code{c-\dyn pfsss}.
 
-@node Construction de fonctions complexes
-@section Construction de fonctions complexes
-@translationof Building complicated functions
 
-@untranslated
+@node Fonctions pour markups
+@section Fonctions pour @emph{markups}
+@translationof Markup functions
 
+Les @emph{markups} sont implémentés au travers de fonctions Scheme
+spécifiques qui produisent des objets @code{Stencil} comprenant un
+certain nombre d'arguments.
 
 @menu
-* Affichage d'expressions musicales::
-* Propriétés de la musique::
-* Exemple : redoubler une note avec liaison::
-* Exemple : ajouter une articulation à plusieurs notes::
+* Construction d'un markup en Scheme::
+* Fonctionnement interne des markups::
+* Définition d'une nouvelle commande de markup::
+* Définition d'une nouvelle commande de liste de markups::
 @end menu
 
-@node Affichage d'expressions musicales
-@subsection Affichage d'expressions musicales
-@translationof Displaying music expressions
 
-@untranslated
+@node Construction d'un markup en Scheme
+@subsection Construction d'un @emph{markup} en Scheme
+@translationof Markup construction in Scheme
+
+@cindex définition d'une commande markup
+
+@funindex \displayScheme
+
+Les expressions @emph{markup} sont représentées en Scheme de manière
+interne par la macro @code{markup} :
+
+@example
+(markup @var{expression})
+@end example
+
+La commande @code{\displayScheme} permet d'obtenir la représentation en
+Scheme d'une expression @emph{markup} :
 
+@example
+\displayScheme
+\markup @{
+  \column @{
+    \line @{ \bold \italic "hello" \raise #0.4 "world" @}
+    \larger \line @{ foo bar baz @}
+  @}
+@}
+@end example
 
-@node Propriétés de la musique
-@subsection Propriétés de la musique
-@translationof Music properties
+@noindent
+Compiler ce code renverra en console les lignes suivantes :
 
-@untranslated
+@example
+(markup
+  #:line
+  (#:column
+   (#:line
+    (#:bold (#:italic "hello") #:raise 0.4 "world")
+    #:larger
+    (#:line
+     (#:simple "foo" #:simple "bar" #:simple "baz")))))
+@end example
 
+L'impression du @emph{markup} sera suspendue dès lors qu'apparaîtra un
+@w{@samp{\void \displayScheme @var{markup}}}.  Tout comme pour la
+commande @code{\displayMusic}, le résultat de @code{\displayScheme} peut
+être sauvegardé dans un fichier séparé.  Voir à ce sujet
+@ref{Affichage d'expressions musicales}.
 
-@node Exemple : redoubler une note avec liaison
-@subsection Exemple : redoubler une note avec liaison
-@translationof Doubling a note with slurs (example)
+@noindent
+Vous pouvez constater les principales règles de traduction entre les
+syntaxes respectives de LilyPond et de Scheme en matière de
+@emph{markup}.  Bien que le passage en syntaxe LilyPond grâce à
+@code{#@{ @dots{} #@}} apporte de la souplesse, nous allons voir comment
+utiliser la macro @code{markup} en Scheme exclusivement.
+
+@quotation
+@multitable @columnfractions .3 .3
+@item @b{LilyPond} @tab @b{Scheme}
+@item @code{\markup markup1} @tab @code{(markup markup1)}
+@item @code{\markup @{ markup1 markup2@dots{} @}} @tab
+        @code{(markup markup1 markup2@dots{} )}
+@item @code{\commande-markup} @tab @code{#:commande-markup}
+@item @code{\variable} @tab @code{variable}
+@item @code{\center-column @{ @dots{} @}} @tab
+        @code{#:center-column ( @dots{} )}
+@item @code{chaîne} @tab @code{"chaîne"}
+@item @code{#argument-scheme} @tab @code{argument-scheme}
+@end multitable
+@end quotation
+
+L'intégralité du langage Scheme est accessible à l'intérieur même de la
+macro @code{markup}.  Vous pouvez ainsi appeler des fonctions à partir
+de @code{markup} pour manipuler des chaînes de caractères, ce qui est
+particulièrement pratique lorsque vous créez votre propre commande de
+@emph{markup} -- voir
+@ref{Définition d'une nouvelle commande de markup}.
+
+@knownissues
+L'argument @var{markup-list} des commandes @code{#:line},
+@code{#:center} ou @code{#:column} ne saurait être une variable ni le
+résultat de l'appel à une fonction.
+
+@lisp
+(markup #:line (fonction-qui-retourne-des-markups))
+@end lisp
 
-@untranslated
+@noindent
+n'est pas valide.  Il vaut mieux, en pareil cas, utiliser les fonctions
+@code{make-line-markup}, @code{make-center-markup} ou
+@code{make-column-markup} :
 
+@lisp
+(markup (make-line-markup (fonction-qui-retourne-des-markups)))
+@end lisp
 
-@node Exemple : ajouter une articulation à plusieurs notes
-@subsection Exemple : ajouter une articulation à plusieurs notes
-@translationof Adding articulation to notes (example)
 
-@untranslated
+@node Fonctionnement interne des markups
+@subsection Fonctionnement interne des @emph{markups}
+@translationof How markups work internally
 
+Dans un @emph{markup} tel que
 
-@node Interface de programmation des marqueurs de texte
-@section Interface de programmation des marqueurs de texte
-@translationof Markup programmer interface
+@example
+\raise #0.5 "text example"
+@end example
 
-@untranslated
+@noindent
+@code{\raise} représente en fait la fonction @code{raise-markup}.
+L'expression @emph{markup} est enregistrée sous la forme
 
+@example
+(list raise-markup 0.5 (list simple-markup "text example"))
+@end example
+
+Lorsque ce @emph{markup} est converti en objets imprimables (stencils),
+la fonction @code{raise-markup} est appelée ainsi :
+
+@example
+(apply raise-markup
+       @var{\layout objet}
+       @var{liste des alists de propriété}
+       0.5
+       @var{le @emph{markup} "text example"})
+@end example
+
+La fonction @code{raise-markup} commence par créer le stencil pour la
+chaîne @code{text example}, puis remonte ce stencil d'un demi espace de
+portée.  Il s'agit là d'un exemple relativement simple, et nous en
+aborderons de plus complexes au fil des paragraphes suivants ;
+d'autres exemples se trouvent directement dans le fichier
+@file{scm/define-markup-commands.scm}.
+
+
+@node Définition d'une nouvelle commande de markup
+@subsection Définition d'une nouvelle commande de @emph{markup}
+@translationof New markup command definition
+
+Nous allons étudier dans ce qui suit la manière de définir une nouvelle
+commande de @emph{markup}.
 
 @menu
-* Construction Scheme d'un marqueur::
-* Fonctionnement interne des marqueurs::
-* Définition d'une nouvelle commande de marqueur::
-* Définition d'une nouvelle commande de liste de marqueurs::
+* Syntaxe d'une commande markup::
+* Attribution de propriétés::
+* Exemple commenté::
+* Adaptation d'une commande incorporée::
 @end menu
 
-@node Construction Scheme d'un marqueur
-@subsection Construction Scheme d'un marqueur
-@translationof Markup construction in Scheme
 
-@untranslated
+@node Syntaxe d'une commande markup
+@unnumberedsubsubsec Syntaxe d'une commande @emph{markup}
+@translationof Markup command definition syntax
+
+Une commande de @emph{markup} personnalisée se définit à l'aide de la
+macro Scheme @code{define-markup-command}, placée en tête de fichier.
+
+@lisp
+(define-markup-command (@var{nom-commande} @var{layout} @var{props} @var{arg1} @var{arg2}@dots{})
+    (@var{arg1-type?} @var{arg2-type?}@dots{})
+    [ #:properties ((@var{propriété1} @var{valeur-par-défaut1})
+                    @dots{}) ]
+  @dots{}corps de la commande@dots{})
+@end lisp
+
+Quelques commentaires sur les arguments :
+
+@table @code
+@item @var{nom-commande}
+le nom que vous attribuez à votre commande de @emph{markup}.
+@item layout
+la définition du « layout » -- son formatage.
+@item props
+une liste de listes associatives, comprenant toutes les propriétés actives.
+@item @var{argi}
+le @var{ième} argument de la commande.
+@item @var{argi-type?}
+un type de prédicat pour le @var{ième} argument.
+@end table
+
+Si la commande utilise des propriétés à partir des arguments
+@code{props}, le mot-clé @code{#:properties} permet de spécifier ces
+différentes propriétés ainsi que leur valeur par défaut.
+
+Les arguments se distinguent selon leur type :
+@itemize
+@item un @emph{markup}, correspondant au type de prédicat
+@code{markup?} ;
+@item une liste de @emph{markups}, correspondant au type de prédicat
+@code{markup-list?} ;
+@item tout autre objet Scheme, correspondant au types de prédicat tels
+que @code{list?}, @code{number?}, @code{boolean?}, etc.
+@end itemize
 
+Il n'existe aucune restriction quant à l'ordre des arguments fournis à
+la suite des arguments @code{layout} et @code{props}.  Néanmoins, les
+fonctions @emph{markup} qui ont en dernier argument un @emph{markup} ont
+ceci de particulier qu'elles peuvent s'appliquer à des listes de
+@emph{markups} ; ceci résultera en une liste de @emph{markups} où
+tous les éléments de la liste originelle se verront appliquer cette
+fonction @emph{markup} avec ses arguments de tête.
+
+La réplication des arguments de tête dans le but d'appliquer une
+fonction @emph{markup} à une liste de markups est économique,
+principalement lorsqu'il s'agit d'arguments Scheme.  Vous éviterez
+ainsi d'éventuelles pertes de performance en utilisant des arguments
+Scheme en tant qu'arguments principaux d'une fonction @emph{markup} dont
+le dernier argument est un @emph{markup}.
+
+@cindex markup macro
+@cindex macro de markup
+@funindex \markup
+@funindex interpret-markup
+
+Les commandes de @emph{markup} ont un cycle de vie relativement
+complexe.  Le corps de la définition d'une commande de @emph{markup} est
+chargé de convertir les arguments de la commande en expression stencil
+qui sera alors renvoyée.  Bien souvent, ceci s'accomplit par un appel à
+la fonction @code{interpret-markup}, en lui passant les arguments
+@var{layout} et @var{props}.  Ces arguments ne seront en principe connus
+que bien plus tardivement dans le processus typographique.  Lors de
+l'expansion d'une expression LilyPond @code{\markup} ou d'une macro
+Scheme @code{markup}, les expressions @emph{markup} auront déjà vu leurs
+composants assemblés en expressions @emph{markup}.  L'évaluation et le
+contrôle du type des arguments à une commande de @emph{markup}
+n'interviennent qu'au moment de l'interprétation de @code{\markup} ou
+@code{markup}.
+
+Seule l'application de @code{interpret-markup} sur une expression
+@emph{markup} réalisera effectivement la conversion des expressions
+@emph{markup} en stencil, au travers de l'exécution du corps des
+fonctions @emph{markup}.
+
+
+@node Attribution de propriétés
+@unnumberedsubsubsec Attribution de propriétés
+@translationof On properties
+
+Les arguments @code{layout} et @code{props} d'une commande de
+@emph{markup} fournissent un contexte à l'interprétation du
+@emph{markup} : taille de fonte, longueur de ligne, etc.
+
+L'argument @code{layout} permet d'accéder aux propriétés définies dans
+les blocs @code{\paper}, grâce à la fonction
+@code{ly:output-def-lookup}.  Par exemple, la longueur de ligne,
+identique à celle de la partition, est lue au travers de
 
-@node Fonctionnement interne des marqueurs
-@subsection Fonctionnement interne des marqueurs
-@translationof How markups work internally
+@example
+(ly:output-def-lookup layout 'line-width)
+@end example
 
-@untranslated
+L'argument @code{props} rend certaines propriétés accessibles aux
+commandes de @emph{markup}.  Il en va ainsi lors de l'interprétation
+d'un @emph{markup} de titre d'ouvrage : toutes les variables
+définies dans le bloc @code{\header} sont automatiquement ajoutées aux
+@code{props}, de telle sorte que le @emph{markup} de titrage de
+l'ouvrage pourra accéder aux différents champs titre, compositeur, etc.
+Ceci permet aussi de configurer le comportement d'une commande de
+@emph{markup} : la taille des fontes, par exemple, est lue à
+partir de @code{props} plutôt que grâce à un argument @code{font-size}.
+La fonction appelant une commande de @emph{markup} peut altérer la
+valeur de la propriété taille des fontes et donc en modifier le
+comportement.  L'utilisation du mot-clé @code{#:properties}, attaché à
+@code{define-markup-command}, permet de spécifier les propriétés devant
+être lues parmi les arguments @code{props}.
+
+L'exemple proposé à la rubrique suivante illustre comment, au sein d'une
+commande de @emph{markup}, accéder aux différentes propriétés et les
+modifier.
+
+
+@node Exemple commenté
+@unnumberedsubsubsec Exemple commenté
+@translationof A complete example
+
+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 @emph{markup}.  La lecture de @ruser{Commandes pour markup} nous
+indique la commande @code{\box}, qui semble ici appropriée.
 
+@lilypond[quote,verbatim,ragged-right]
+\markup \box \box HELLO
+@end lilypond
 
-@node Définition d'une nouvelle commande de marqueur
-@subsection Définition d'une nouvelle commande de marqueur
-@translationof New markup command definition
+Dans un souci d'esthétique, nous aimerions que le texte et les
+encadrements ne soient pas autant accolés.  Selon la documentation de
+@code{\box}, cette commande utilise la propriété @code{box-padding},
+fixée par défaut à 0,2.  Cette même documentation nous indique
+aussi comment la modifier :
+
+@lilypond[quote,verbatim,ragged-right]
+\markup \box \override #'(box-padding . 0.6) \box A
+@end lilypond
+
+L'espacement des deux liserés est cependant toujours trop réduit ;
+modifions le à son tour :
+
+@lilypond[quote,verbatim,ragged-right]
+\markup \override #'(box-padding . 0.4) \box
+     \override #'(box-padding . 0.6) \box A
+@end lilypond
 
-@untranslated
+Vous conviendrez que recopier une telle définition de @emph{markup}
+deviendra vite fastidieux.  C'est pourquoi nous écrivons la commande de
+@emph{markup} @code{double-box} qui prendra un seul argument -- le
+texte.  Cette commande se chargera de dessiner les encadrements, en
+tenant compte des espacements.
+
+@lisp
+#(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 @}#@}))
+@end lisp
+
+ou bien son équivalent
+
+@lisp
+#(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)))
+@end lisp
+
+@code{text} est le nom de l'argument de notre commande, et
+@code{markup?} son type -- l'argument sera identifié comme étant un
+@emph{markup}.  La fonction @code{interpret-markup}, utilisée dans la
+plupart des commandes de @emph{markup}, construira un stencil à partir
+de @code{layout}, @code{props} et un @emph{markup}.  Dans la seconde
+variante, ce @emph{markup} sera construit à l'aide de la macro Scheme
+@code{markup} -- voir @ref{Construction d'un markup en Scheme}.  La
+transformation d'une expression @code{\markup} en expression Scheme est
+des plus triviales.
+
+Notre commande personnalisée s'utilise ainsi :
+
+@example
+\markup \double-box A
+@end example
+
+Il serait intéressant de rendre cette commande @code{double-box} plus
+souple :  les valeurs de @code{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 @code{inter-box-padding}, chargée
+de gérer l'espacement des encadrements ; @code{box-padding} ne
+servira alors que pour l'espacement intérieur.  Voici le code adapté à
+ces évolutions :
+
+@lisp
+#(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 @} #@}))
+@end lisp
+
+Ainsi que son équivalent à partir de la macro @emph{markup} :
+
+@lisp
+#(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)))
+@end lisp
+
+C'est ici le mot-clé @code{#:properties} qui permet de lire les
+propriétés @code{inter-box-padding} et @code{box-padding} à partir de
+l'argumenet @code{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
+@code{box-padding} utilisées par les deux commandes @code{\box}.  Vous
+aurez remarqué, dans l'argument @code{\override}, la présence de
+l'apostrophe inversée (@code{`}) 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 @emph{markup}, et
+les encadrements sont repositionnables.
+
+@lilypond[quote,verbatim,ragged-right]
+#(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
+@end lilypond
 
 
-@node Définition d'une nouvelle commande de liste de marqueurs
-@subsection Définition d'une nouvelle commande de liste de marqueurs
+@node Adaptation d'une commande incorporée
+@unnumberedsubsubsec Adaptation d'une commande incorporée
+@translationof Adapting builtin commands
+
+Le meilleur moyen de construire ses propres commandes de @emph{markup}
+consiste à prendre exemple sur les commandes déjà incorporées.  La
+plupart des commandes de @emph{markup} fournies avec LilyPond sont
+répertoriées dans le fichier @file{scm/define-markup-commands.scm}.
+
+Nous pourrions, par exemple, envisager d'adapter la commande
+@code{\draw-line} pour dessiner plutôt une ligne double.  Voici comment
+est définie la commande @code{\draw-line}, expurgée de sa
+documentation :
+
+@lisp
+(define-markup-command (draw-line layout props dest)
+  (number-pair?)
+  #:category graphic
+  #:properties ((thickness 1))
+  "@dots{}documentation@dots{}"
+  (let ((th (* (ly:output-def-lookup layout 'line-thickness)
+               thickness))
+        (x (car dest))
+        (y (cdr dest)))
+    (make-line-stencil th 0 0 x y)))
+@end lisp
+
+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é @code{#: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.
+
+@lisp
+(define-markup-command (draw-double-line layout props dest)
+  (number-pair?)
+  #:properties ((thickness 1))
+  "@dots{}documentation@dots{}"
+  (let ((th (* (ly:output-def-lookup layout 'line-thickness)
+               thickness))
+        (x (car dest))
+        (y (cdr dest)))
+    (make-line-stencil th 0 0 x y)))
+@end lisp
+
+Nous ajoutons ensuite une propriété pour gérer l'écart entre les deux
+lignes, que nous appelons @code{line-gap}, et lui attribuons une valeur
+par défaut de 6 dixièmes :
+
+@lisp
+(define-markup-command (draw-double-line layout props dest)
+  (number-pair?)
+  #:properties ((thickness 1)
+                (line-gap 0.6))
+  "@dots{}documentation@dots{}"
+  @dots{}
+@end lisp
+
+Nous ajoutons enfin le code qui dessinera nos deux lignes.  Deux appels
+à @code{make-line-stencil} permettrons de dessiner les lignes dont nous
+regrouperons les stencils à l'aide de @code{ly:stencil-add} :
+
+@lilypond[quote,verbatim,ragged-right]
+#(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)
+@end lilypond
+
+
+@node Définition d'une nouvelle commande de liste de markups
+@subsection Définition d'une nouvelle commande de liste de @emph{markups}
 @translationof New markup list command definition
 
-@untranslated
+@cindex liste de markup, définition de commande
+@funindex define-markup-list-command
+@funindex interpret-markup-list
+
+Une commande traitant une liste de @emph{markups} se définit à l'aide de
+la macro Scheme @code{define-markup-list-command}, de manière analogue à
+la macro @code{define-markup-command} abordée à la rubrique
+@ref{Définition d'une nouvelle commande de markup}, à ceci près que
+cette dernière renvoie un seul stencil, non une liste de stencils.
+
+La fonction @code{interpret-markup-list}, à l'instar de la fonction
+@code{interpret-markup}, permet de convertir une liste de @emph{markups}
+en liste de stencils.
+
+Dans l'exemple suivant, nous définissons @code{\paragraph}, une commande
+de liste de @emph{markups}, qui renverra une liste de lignes justifiées
+dont la première sera indentée.  La largeur de l'alinéa sera récupérée
+par l'argument @code{props}.
+
+@example
+#(define-markup-list-command (paragraph layout props args) (markup-list?)
+   #:properties ((par-indent 2))
+   (interpret-markup-list layout props
+     #@{\markuplist \justified-lines @{ \hspace #par-indent #args @} #@}))
+@end example
+
+La version purement Scheme est un peu plus complexe :
+@example
+#(define-markup-list-command (paragraph layout props args) (markup-list?)
+   #:properties ((par-indent 2))
+   (interpret-markup-list layout props
+     (make-justified-lines-markup-list (cons (make-hspace-markup par-indent)
+                                             args))))
+@end example
+
+En dehors des habituels arguments @code{layout} et @code{props}, la
+commande de liste de @emph{markups} @code{paragraph} prend en argument
+une liste de @emph{markups} appelée @code{args}.  Le prédicat des listes
+de @emph{markups} est @code{markup-list?}.
+
+Pour commencer, la fonction récupère la taille de l'alinéa, propriété
+ici dénommée @code{par-indent}, à partir de la liste de propriétés
+@code{props}.  En cas d'absence, la valeur par défaut sera
+de @code{2}.  Ensuite est créée une liste de lignes justifiées
+grâce à la commande prédéfinie @code{\justified-lines}, liée à la
+fonction @code{make-justified-lines-markup-list}.  Un espace horizontal
+est ajouté en tête, grâce à @code{\hspace} ou à la fonction
+@code{make-hspace-markup}.  Enfin, la liste de @emph{markups} est
+interprétée par la fonction @code{interpret-markup-list}.
+
+Voici comment utiliser cette nouvelle commande de liste de
+@emph{markups} :
+
+@example
+\markuplist @{
+  \paragraph @{
+    The art of music typography is called \italic @{(plate) engraving.@}
+    The term derives from the traditional process of music printing.
+    Just a few decades ago, sheet music was made by cutting and stamping
+    the music into a zinc or pewter plate in mirror image.
+  @}
+  \override-lines #'(par-indent . 4) \paragraph @{
+    The plate would be inked, the depressions caused by the cutting
+    and stamping would hold ink.  An image was formed by pressing paper
+    to the plate.  The stamping and cutting was completely done by
+    hand.
+  @}
+@}
+@end example
 
 
 @node Contextes pour programmeurs
 @section Contextes pour programmeurs
 @translationof Contexts for programmers
 
-@untranslated
-
-
 @menu
 * Évaluation d'un contexte::
 * Application d'une fonction à tous les objets de mise en forme::
 @end menu
 
+
 @node Évaluation d'un contexte
 @subsection Évaluation d'un contexte
 @translationof Context evaluation
 
-@untranslated
+@cindex appel de code durant l'interprétation
+@funindex \applyContext
+@funindex make-apply-context
+@funindex ly:context-property
+@funindex ly:context-set-property!
+@funindex ly:context-grob-definition
+@funindex ly:assoc-get
+@funindex ly:context-pushpop-property
+
+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
+
+@example
+\applyContext @var{fonction}
+@end example
+
+@noindent
+et, dans le cadre d'un code Scheme :
+
+@example
+(make-apply-context @var{fonction})
+@end example
+
+@code{@var{fonction}} est constitué d'une fonction Scheme comportant un
+unique argument : le contexte au sein duquel la commande
+@code{\applyContext} est appelée.  Cette fonction peut accéder aussi
+bien aux propriétés de @emph{grob} (y compris modifiées par
+@code{\override} ou @code{\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 @b{au moment de l'appel à
+la fonction}.  Par ailleurs, les adaptations résultant d'un appel à
+@code{\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 @code{\applyContext} :
+
+@table @code
+@item ly:context-property
+recherche la valeur d'une propriété de contexte,
+
+@item ly:context-set-property!
+détermine une propriété de contexte,
+
+@item ly:context-grob-definition
+@itemx ly:assoc-get
+recherche la valeur d'une propriété de @emph{grob},
+
+@item ly:context-pushpop-property
+réalise un @code{\temporary \override} ou un @code{\revert} sur une
+propriété de @emph{grob}.
+@end table
+
+L'exemple suivant recherche la valeur en cours de @code{fontSize} puis
+la double :
+
+@lilypond[quote,verbatim]
+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'
+}
+@end lilypond
+
+L'exemple suivant recherche la couleur des objets @code{NoteHead},
+@code{Stem} et @code{Beam}, puis diminue pour chacun d'eux le degré de
+saturation.
+
+@lilypond[quote,verbatim]
+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]
+}
+@end lilypond
+
+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 @code{ly:context-pushpop-property} est utilisé à la fois pour un
+@code{\temporary \override} et pour un @code{\revert} :
+
+@lilypond[quote,verbatim]
+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
+}
+@end lilypond
 
 
 @node Application d'une fonction à tous les objets de mise en forme
 @subsection Application d'une fonction à tous les objets de mise en forme
 @translationof Running a function on all layout objects
 
-@untranslated
+@cindex appel de code sur des objets de mise en forme
+@cindex objets de mise en forme, appel de code
+@funindex \applyOutput
 
+La manière la plus souple d'affiner un objet consiste à utiliser la
+commande @code{\applyOutput}.  Celle-ci va insérer un événement
+(@rinternals{ApplyOutputEvent}) dans le contexte spécifié.  Elle répond
+à la syntaxe
+@example
+\applyOutput @var{Contexte} @var{procédure}
+@end example
 
-@node Utilisation de procédures Scheme en tant que propriétés
-@section Utilisation de procédures Scheme en tant que propriétés
-@translationof Scheme procedures as properties
+@noindent
+où @code{@var{procédure}} est une fonction Scheme à trois arguments.
+
+Lors de l'interprétation de cette commande, la fonction
+@code{@var{procédure}} est appelée pout tout objet de rendu appartenant
+au contexte @code{@var{Contexte}} à cet instant précis, avec les
+arguments suivants :
+@itemize
+@item l'objet de rendu en lui-même,
+@item le contexte au sein duquel cet objet est créé,
+@item le contexte dans lequel @code{\applyOutput} est effectué.
+@end itemize
 
-@untranslated
+De plus, ce qui est à l'origine de l'objet de rendu -- l'expression
+musicale ou l'objet qui l'a générée -- se retrouve en tant que propriété
+d'objet @code{cause}.  Il s'agit, pour une tête de note, d'un événement
+@rinternals{NoteHead}, et d'un objet @rinternals{Stem} pour une hampe.
 
+Voici une fonction utilisable avec la commande
+@code{\applyOutput} : elle « blanchit » la tête des notes se trouvant
+sur la ligne médiane ou bien directement à son contact.
 
-@menu
-* Utilisation de code Scheme au lieu de \"tweak\"::
-* Retouches complexes::
-@end menu
+@lilypond[quote,verbatim,ragged-right]
+#(define (blanker grob grob-origin context)
+   (if (and (memq 'note-head-interface (ly:grob-interfaces grob))
+            (< (abs (ly:grob-property grob 'staff-position)) 2))
+       (set! (ly:grob-property grob 'transparent) #t)))
 
-@node Utilisation de code Scheme au lieu de \"tweak\"
-@section Utilisation de code Scheme au lieu de @code{\tweak}
-@translationof Using Scheme code instead of tweak
+\relative {
+  a'4 e8 <<\applyOutput #'Voice #blanker a c d>> b2
+}
+@end lilypond
+
+La @var{procédure} sera interprétée au niveau @code{Score}
+(partition) ou @code{Staff} (portée) dès lors que vous utiliserez l'une
+des syntaxes
+
+@example
+\applyOutput #'Score #@var{procédure}
+\applyOutput #'Staff #@var{procédure}
+@end example
+
+
+@node Fonctions de rappel
+@section Fonctions de rappel
+@translationof Callback functions
+
+Certaines propriétés, entre autres @code{thickness} ou @code{direction},
+peuvent voir leur valeur figée à l'aide d'un @code{\override} comme
+ici :
+
+@example
+\override Stem.thickness = #2.0
+@end example
+
+Une procédure Scheme peut aussi se charger de modifier des propriétés :
+
+@lilypond[fragment,verbatim,quote,relative=2]
+\override Stem.thickness = #(lambda (grob)
+    (if (= UP (ly:grob-property grob 'direction))
+        2.0
+        7.0))
+c b a g b a g b
+@end lilypond
+
+@noindent
+Dans ce cas, la procédure est exécutée dès que la valeur de la propriété
+est nécessaire au processus de mise en forme.
+
+La majeure partie du procédé typographique consiste en la réalisation de
+tels rappels (@emph{callbacks} en anglais).  Entre autres propriétés
+utilisant particulièrement des rappels, nous mentionnerons
+
+@table @code
+@item stencil
+  Routine d'impression, construisant le dessin du symbole
+@item X-offset
+  Routine effectuant le positionnement horizontal
+@item X-extent
+  Routine calculant la largeur d'un objet
+@end table
+
+La procédure prend un unique argument, en l'occurrence l'objet graphique
+(le @emph{grob}).
+
+Cette procédure, grâce à un appel à la fonction de rappel dévolue à
+cette propriété -- mentionnée dans la référence des propriétés internes
+et dans le fichier @file{define-grobs.scm} --, pourra accéder à la
+valeur usuelle de la propriété :
+
+@example
+\relative @{
+  \override Flag.X-offset = #(lambda (flag)
+    (let ((default (ly:flag::calc-x-offset flag)))
+      (* default 4.0)))
+  c''4. d8 a4. g8
+@}
+@end example
+
+Au sein d'un @emph{callback}, le meilleur moyen d'évaluer un
+@emph{markup} consiste à utiliser la fonction
+@code{grob-interpret-markup}, comme ici :
+
+@example
+my-callback = #(lambda (grob)
+                 (grob-interpret-markup grob (markup "foo")))
+@end example
+
+
+@ignore
+@n ode Code Scheme intégré
+@s ection Code Scheme intégré
+@t ranslationof Inline Scheme code
+
+À REVOIR : depuis la rédaction de cette section, LilyPond en est
+arrivé à un point tel que trouver un exemple @emph{simple} où l'on se
+retrouve obligé d'en venir à utiliser du code Scheme devient chose
+ardue.
+
+En attendant un remaniement de cette section, faisons comme si nous
+l'ignorions.
 
 L'inconvénient principal de la commande @code{\tweak} est la rigidité de
-sa syntaxe.  Par exemple, le code suivant produit une erreur.
+sa syntaxe.  Par exemple, le code suivant produit une erreur de syntaxe
+(du moins, c'était le cas auparavant).
 
 @example
-F = \tweak #'font-size #-3 -\flageolet
+F = \tweak font-size #-3 -\flageolet
 
-\relative c'' @{
-  c4^\F c4_\F
+\relative @{
+  c''4^\F c4_\F
 @}
 @end example
 
 @noindent
-En d'autres termes, @code{\tweak} ne se comporte pas comme une
-articulation@tie{}: il ne peut notamment pas être accolé avec les
-symboles @samp{^} ou @samp{_}.
-
 C'est en se servant du langage Scheme que l'on peut résoudre ce
 problème.  Dans cet exemple, on a recours aux méthodes décrites dans
-@ref{Exemple : ajouter une articulation à plusieurs notes}, en
+@ref{Ajout d'articulation à des notes (exemple)}, en
 particulier quant à l'emploi de @code{\displayMusic}.
 
 @example
@@ -280,20 +1555,22 @@ F = #(let ((m (make-music 'ArticulationEvent
                     (ly:music-property m 'tweaks)))
        m)
 
-\relative c'' @{
-  c4^\F c4_\F
+\relative @{
+  c''4^\F c4_\F
 @}
 @end example
 
 @noindent
-Ici les propriétés @code{tweak} de l'objet flageolet nommé
-@samp{m} (créé au moyen de @code{make-music}) sont extraites par
+Ici les propriétés @code{tweak} de l'objet flageolet nommé @samp{m}
+(créé au moyen de @code{make-music}) sont extraites par
 @code{ly:music-property}, une nouvelle valeur de la taille de fonte
 est ajoutée à la liste de ses propriétés (grâce à la fonction Scheme
 @code{acons}), et le résultat de cette opération est renvoyé par
 @code{set!}.  Le dernier élément, dans ce bloc @code{let}, est la valeur
 finale de @samp{m} lui-même.
 
+@end ignore
+
 
 @node Retouches complexes
 @section Retouches complexes
@@ -301,22 +1578,20 @@ finale de @samp{m} lui-même.
 
 Certains réglages sont plus délicats que d'autres.
 
-@itemize @bullet
-
-
+@itemize
 @item
-L'un d'entre eux est l'apparence des objets dits @qq{spanner}, qui
-s'étendent horizontalement, tels que les liaisons.  Si, en principe, un
-seul de ces objets est créé à la fois et peut donc être modifié de façon
-habituelle, lorsque ces objets doivent enjamber un changement de ligne,
-ils sont dupliqués au début du ou des systèmes suivants.  Comme ces
-objets sont des clones de l'objet d'origine, ils en héritent toutes les
-propriétés, y compris les éventuelles commandes @code{\override}.
-
+L'un d'entre eux est l'apparence des objets dits « extenseurs »
+(@emph{spanner}), qui s'étendent horizontalement, tels que les liaisons.
+Si, en principe, un seul de ces objets est créé à la fois et peut donc
+être modifié de façon habituelle, lorsque ces objets doivent enjamber un
+changement de ligne, ils sont dupliqués au début du ou des systèmes
+suivants.  Comme ces objets sont des clones de l'objet d'origine, ils en
+héritent toutes les propriétés, y compris les éventuelles commandes
+@code{\override}.
 
 En d'autres termes, une commande @code{\override} affecte toujours les
-deux extrémités d'un objet @q{spanner}.  Pour ne modifier que la partie
-précédant ou suivant le changement de ligne, il faut intervenir
+deux extrémités d'un objet @emph{spanner}.  Pour ne modifier que la
+partie précédant ou suivant le changement de ligne, il faut intervenir
 directement dans le processus de mise en page.
 La fonction de rappel @code{after-line-breaking} contient toute
 l'opération Scheme effectuée lorsque les sauts de lignes ont été
@@ -326,68 +1601,83 @@ systèmes différents.
 Dans l'exemple suivant, on définit une nouvelle opération nommée
 @code{my-callback}.  Cette opération
 
-@itemize @bullet
+@itemize
 @item
 détermine si l'objet a été divisé à l'occasion d'un changement de ligne
 @item
-si oui, recherche les différents morceaux de l'objet
+dans l'affirmative, recherche les différents tronçons de l'objet
 @item
 vérifie si l'objet considéré est bien la deuxième moitié d'un objet
 divisé
 @item
-si oui, applique un espacement supplémentaire (@code{extra-offset}).
+dans l'affirmative, applique un espacement supplémentaire
+(@code{extra-offset}).
 @end itemize
 
 On ajoute cette procédure à l'objet @rinternals{Tie} (liaison de tenue),
-de façon à ce que le deuxième morceau d'une liaison divisée soit
+de façon à ce que le deuxième tronçon d'une liaison divisée soit
 rehaussé.
 
 @c KEEP LY
 @lilypond[quote,verbatim,ragged-right]
 #(define (my-callback grob)
-  (let* (
-         ; l'objet a-t-il été divisé ?
-         (orig (ly:grob-original grob))
+   (let* (
+          ;; l'objet a-t-il été divisé ?
+          (orig (ly:grob-original grob))
 
-         ; si oui, rechercher les morceaux frères (siblings)
-         (siblings (if (ly:grob? orig)
-                     (ly:spanner-broken-into orig) '() )))
+          ;; si oui, rechercher les tronçons frères (siblings)
+          (siblings (if (ly:grob? orig)
+                        (ly:spanner-broken-into orig)
+                        '())))
 
-   (if (and (>= (length siblings) 2)
-             (eq? (car (last-pair siblings)) grob))
-     (ly:grob-set-property! grob 'extra-offset '(-2 . 5)))))
+     (if (and (>= (length siblings) 2)
+              (eq? (car (last-pair siblings)) grob))
+         (ly:grob-set-property! grob 'extra-offset '(-2 . 5)))))
 
-\relative c'' {
-  \override Tie #'after-line-breaking =
+\relative {
+  \override Tie.after-line-breaking =
   #my-callback
-  c1 ~ \break c2 ~ c
+  c''1 ~ \break
+  c2 ~ 2
 }
 @end lilypond
 
 @noindent
 Lorsque cette astuce va être appliquée, notre nouvelle fonction de
 rappel @code{after-line-breaking} devra également appeler celle
-d'origine (@code{after-line-breaking}), si elle existe.
-Ainsi, pour l'utiliser dans le cas d'un crescendo (objet
-@code{Hairpin}), il faudra appeler également
-@code{ly:spanner::kill-zero-spanned-time}.
+d'origine (@code{after-line-breaking}), si elle existe.  Ainsi, pour
+l'utiliser dans le cas d'un crescendo (objet @code{Hairpin}), il faudra
+également appeler @code{ly:spanner::kill-zero-spanned-time}.
 
 
-@item Pour des raisons d'ordre technique, certains objets ne peuvent
-être modifiés par @code{\override}.  Parmi ceux-là, les objets
+@item
+Pour des raisons d'ordre technique, certains objets ne peuvent être
+modifiés par @code{\override}.  Parmi ceux-là, les objets
 @code{NonMusicalPaperColumn} et @code{PaperColumn}.  La commande
 @code{\overrideProperty} sert à les modifier, de façon similaire à
-@code{\once \override}, mais avec une syntaxe différente@tie{}:
+@code{\once \override}, mais avec une syntaxe différente :
 
 @example
 \overrideProperty
-#"Score.NonMusicalPaperColumn"  % Nom de l'objet
-#'line-break-system-details     % Nom de la propriété
-#'((next-padding . 20))         % valeur
+Score.NonMusicalPaperColumn      % Nom de l'objet
+  . line-break-system-details    % Nom de la propriété
+  . next-padding                 % Nom de la sous-propriété (optionnel)
+  . #20                          % Valeur
 @end example
 
-Notez cependant que la commande @code{\override} peut tout de même être
+Notez toutefois que la commande @code{\override} peut tout de même être
 appliquée à @code{NonMusicalPaperColumn} et @code{PaperColumn} dans un
 bloc @code{\context}.
 
 @end itemize
+
+
+@node Interfaces LilyPond Scheme
+@chapter Interfaces LilyPond Scheme
+@translationof LilyPond Scheme interfaces
+
+Ce chapitre aborde les différents outils fournis par LilyPond à
+l'intention des programmeurs en Scheme désireux d'obtenir des
+informations à partir et autour des fluxs de musique.
+
+TODO -- figure out what goes in here and how to organize it