1@c -*- coding: utf-8; mode: texinfo; documentlanguage: fr -*- 2 3@ignore 4 Translation of GIT committish: 529eb23f3ddb597ae0738685d194cb88b4733054 5 6 When revising a translation, copy the HEAD committish of the 7 version that you are working on. For details, see the Contributors' 8 Guide, node Updating translation committishes.. 9@end ignore 10 11@c \version "2.19.24" 12 13@c Translators: Valentin Villenave, Jean-Charles Malahieude 14@c Translation checkers: Gilles Thibault 15 16 17@node Interfaces pour programmeurs 18@chapter Interfaces pour programmeurs 19@translationof Interfaces for programmers 20 21Scheme permet de réaliser des affinages très pointus. Si vous ne 22connaissez rien de Scheme, vous en aurez un aperçu au travers de notre 23@ref{Tutoriel Scheme}. 24 25@menu 26* Blocs de code LilyPond:: 27* Fonctions Scheme:: 28* Fonctions musicales:: 29* Fonctions événementielles:: 30* Fonctions pour markups:: 31* Contextes pour programmeurs:: 32* Fonctions de rappel:: 33* Retouches complexes:: 34@end menu 35 36 37@node Blocs de code LilyPond 38@section Blocs de code LilyPond 39@translationof LilyPond code blocks 40 41@cindex code, blocs LilyPond 42@cindex LilyPond, bloc de code 43 44@funindex #@{ ... #@} 45@funindex $ 46@funindex # 47 48L'utilisation de Scheme pour créer des expressions musicales peut 49s'avérer ardue, principalement à cause des imbrications et de la 50longueur du code Scheme qui en résulte. Dans le cas de tâches 51simples, on peut toutefois contourner une partie du problème en 52utilisant des blocs de code LilyPond, ce qui autorise la syntaxe 53habituelle de LilyPond au sein même de Scheme. 54 55Les blocs de code LilyPond ressemblent à 56 57@example 58 #@{ @var{du code LilyPond} #@} 59@end example 60 61En voici un exemple basique : 62 63@lilypond[verbatim,quote] 64ritpp = #(define-event-function () () 65 #{ ^"rit." \pp #} 66) 67 68{ c'4 e'4\ritpp g'2 } 69@end lilypond 70 71Les blocs de code LilyPond peuvent s'utiliser partout où vous pouvez 72écrire du code Scheme. Le lecteur Scheme est en fait quelque peu adapté 73pour accepter des blocs de code LilyPond ; il est capable de traiter des 74expressions Scheme intégrées débutant par @code{$} ou @code{#}. 75 76Le lecteur Scheme extrait le bloc de code LilyPond et déclenche un appel 77à l'analyseur grammatical de LilyPond (le @emph{parser}) qui réalise en 78temps réel l'interprétation de ce bloc de code LilyPond. Toute 79expression Scheme imbriquée est exécutée dans l'environnement lexical du 80bloc de code LilyPond, de telle sorte que vous avez accès aux variables 81locales et aux paramètres de la fonction au moment même où le bloc de 82code LilyPond est écrit. Les variables définies dans d'autres modules 83Scheme, tels ceux contenant les blocs @code{\header} ou @code{\layout}, 84ne sont pas accessibles en tant que variables Scheme (préfixées par 85un @code{#}) mais en tant que variables LilyPond (préfixées par 86un @code{\}). 87 88Toute la musique générée au sein de ce bloc de code voit son 89@code{origine} établie à cet @emph{emplacement}. 90 91Un bloc de code LilyPond peut contenir tout ce que vous pourriez mettre 92à droite de l'assignation. Par ailleurs, un bloc LilyPond vide 93correspond à une expression fantôme, et un bloc LilyPond de multiples 94événements musicaux sera transformé en une expression de musique 95séquentielle. 96 97 98@node Fonctions Scheme 99@section Fonctions Scheme 100@translationof Scheme functions 101 102@cindex Scheme, fonctions (syntaxe LilyPond) 103 104Les @emph{fonctions Scheme} sont des procédures Scheme chargées de créer 105des expressions Scheme à partir de code rédigé selon la syntaxe de 106LilyPond. Elles peuvent être appelées en de nombreux endroits, à l'aide 107d'un @code{#}, où spécifier une valeur en syntaxe Scheme est autorisé. 108Bien que Scheme dispose de fonctions en propre, nous nous intéresserons, 109au fil des paragraphes qui suivent, aux fonctions @emph{syntaxiques}, 110autrement dit des fonctions qui reçoivent des arguments libellés dans la 111syntaxe de LilyPond. 112 113@menu 114* Définition de fonctions Scheme:: 115* Utilisation de fonctions Scheme:: 116* Fonctions Scheme fantômes:: 117@end menu 118 119 120@node Définition de fonctions Scheme 121@subsection Définition de fonctions Scheme 122@translationof Scheme function definitions 123 124@funindex define-scheme-function 125 126D'une manière générale, une fonction Scheme se définit ainsi : 127 128@example 129fonction = 130#(define-scheme-function 131 (@var{arg1} @var{arg2}@dots{}) 132 (@var{type1?} @var{type2?}@dots{}) 133 @var{corps}) 134@end example 135 136@noindent 137où 138 139@multitable @columnfractions .33 .66 140@item @code{@var{argN}} 141@tab @var{n}-ième argument. 142 143@item @code{@var{typeN?}} 144@tab un @emph{type de prédicat} Scheme pour lequel @code{@var{argN}} 145devra retourner @code{#t}. Il existe aussi une forme spécifique -- 146@code{(@emph{prédicat?} @emph{default})} -- qui permet de fournir des 147argument optionnels. En l'absence d'argument réel au moment de l'appel 148à la fonction, c'est la valeur par défaut qui lui sera substituée. Les 149valeurs par défaut sont évaluées dès l'apparition de la définition, y 150compris dans le cas de blocs de code LilyPond ; vous devrez donc, 151si ces valeurs par défaut ne peuvent être déterminées que plus tard, 152mentionner une valeur spéciale que vous reconnaîtrez facilement. 153Lorsque vous mentionnez un prédicat entre parenthèses sans toutefois 154fournir sa valeur par défaut, celle-ci sera considérée comme 155étant @code{#f}. Les valeurs par défaut d'un @code{prédicat?} ne sont 156vérifiées ni au moment de la définition, ni à l'exécution ; il est 157de votre ressort de gérer les valeurs que vous spécifiez. Une valeur 158par défaut constituée d'une expression musicale est recopiée dès la 159définition de @code{origin} à l'emplacement courant du code. 160 161@item @code{@var{corps}} 162@tab une séquence de formules Scheme évaluées dans l'ordre, la dernière 163servant de valeur de retour de la fonction. Il peut contenir des blocs 164de code LilyPond, enchâssés dans des accolades et @emph{hashes} -- 165@w{@code{#@{@dots{}#@}}} -- comme indiqué à la rubrique 166@ref{Blocs de code LilyPond}. Au sein d'un bloc de code LilyPond, un 167@code{#} permet de référencer des arguments de la fonction -- tel 168@samp{#arg1} -- ou d'ouvrir une expression Scheme contenant les 169arguments de la fonction -- par exemple @w{@samp{#(cons arg1 arg2)}}. 170Dans le cas où une expression Scheme introduite par @code{#} ne vous 171permet pas de parvenir à vos fins, vous pourriez devoir revenir à une 172expression Scheme « immédiate » à l'aide d'un @code{$}, comme 173@samp{$music}. 174 175Lorsque votre fonction retourne une expression musicale, lui est 176attribuée la valeur @code{origin}. 177@end multitable 178 179@noindent 180La recevabilité des arguments est déterminée par un appel effectif au 181prédicat après que LilyPond les a déjà convertis en expression Scheme. 182Par voie de conséquence, l'argument peut tout à fait se libeller en 183syntaxe Scheme -- introduite par un @code{#} ou en tant que résultat 184d'un appel à une fonction Scheme. Par ailleurs, LilyPond convertira en 185Scheme un certain nombre de constructions purement LilyPond avant même 186d'en avoir vérifié le prédicat. C'est notamment le cas de la musique, 187des @emph{postévénements}, des chaînes simples (avec ou sans 188guillemets), des nombres, des @emph{markups} et listes de 189@emph{markups}, ainsi que des blocs @emph{score}, @emph{book}, 190@emph{bookpart}, ou qui définissent un contexte ou un format de sortie. 191 192Il existe certaines situations pour lesquelles LilyPond lèvera toute 193ambiguïté grâce aux fonctions de prédicat : un @samp{-3} est-il un 194@emph{postévénement} de type doigté ou un nombre négatif ? Un 195@code{"a" 4} en mode paroles est-il une chaîne suivie d'un nombre ou 196bien un événement syllabe de durée @code{4} ? LilyPond répondra à ces 197questions par des interprétations successives du prédicat de l'argument, 198dans un ordre défini de sorte à minimiser les interprétations erronées 199et le besoin de lecture en avance. 200 201Un prédicat qui accepte par exemple aussi bien une expression musicale 202qu'une hauteur considèrera @code{c''} comme étant une hauteur plutôt 203qu'une expression musicale. Les durées ou @emph{postévénements} qui 204viennent juste après viendront modifier cette interprétation. C'est la 205raison pour laquelle il vaut mieux éviter des prédicats par trop 206permissifs tel que @code{Scheme?} lorsque l'application fait plutôt 207appel à des types d'argument plus spécifiques. 208 209Les différents types de prédicat propres à LilyPond sont recensés à 210l'annexe @ruser{Types de prédicats prédéfinis}. 211 212@morerefs 213Manuel de notation : 214@ruser{Types de prédicats prédéfinis}. 215 216Fichiers d'initialisation : 217@file{lily/music-scheme.cc}, 218@file{scm/c++.scm}, 219@file{scm/lily.scm}. 220 221 222@node Utilisation de fonctions Scheme 223@subsection Utilisation de fonctions Scheme 224@translationof Scheme function usage 225 226Vous pouvez appeler une fonction Scheme pratiquement partout où une 227expression Scheme derrière un @code{#} peut prendre place. Vous appelez 228une fonction Scheme à partir de LilyPond en faisant précéder son nom 229d'un @code{\}, et en le faisant suivre de ses arguments. Lorsqu'un 230prédicat d'argument optionnel ne correspond pas à un argument, LilyPond 231l'ignore ainsi que tous les arguments optionnels qui suivent, les 232remplaçant par leur valeur par défaut, et « sauvegarde » en tant que 233prochain argument obligatoire l'argument qui ne correspondait pas. Dans 234la mesure où l'argument sauvegardé doit servir, les argument optionnels 235ne sont en fait pas considérés comme optionnels, sauf à être suivis d'un 236argument obligatoire. 237 238Une exception cependant à cette règle : le fait de donner un 239@code{\default} en tant qu'argument optionnel aura pour résultat que cet 240argument et tous les autres arguments optionnels qui suivent seront 241ignorés et remplacés par leur valeur par défaut. Il en va de même 242lorsqu'aucun argument obligatoire ne suit, du fait que @code{\default} 243ne requiert pas de sauvegarde. C'est d'ailleurs ainsi que fonctionnent 244les commandes @code{mark} et @code{key}, qui retrouvent leur 245comportement par défaut lorsque vous les faites suivre d'un 246@code{\default}. 247 248En plus de là où une expression Scheme est requise, il y a quelques 249endroits où des expressions @code{#} sont acceptées et évaluées 250uniquement pour leurs effets annexes. Il s'agit, dans la plupart des 251cas, d'endroits où une affectation serait tout à fait envisageable. 252 253Dans la mesure où il n'est pas bon de renvoyer une valeur qui pourrait 254être mal interprétée dans certains contextes, nous vous enjoignons à 255utiliser des fonctions Scheme normales uniquement dans les cas où vous 256renvoyez toujours une valeur utile, et une fonction fantôme -- voir 257@ref{Fonctions Scheme fantômes} -- dans le cas contraire. 258 259Pour des raisons de commodité, il est possible de faire appel à des 260fonctions Scheme directement en Scheme, courcircuitant ainsi l'analyseur 261de LilyPond. Leur nom s'utilise comme n'importe quel nom de fonction. 262Le contrôle de typologie des arguments et l'omission des arguments 263optionnels seront traîtés de la même manière que lorsque l'appel est 264fait à partir de LilyPond, la valeur Scheme @code{*unspecified*} ayant 265le rôle du mot réservé @code{\default} pour omettre explicitement les 266arguments optionnels. 267 268 269@node Fonctions Scheme fantômes 270@subsection Fonctions Scheme fantômes 271@translationof Void scheme functions 272 273@cindex @emph{void}, fonction 274@cindex fantôme, fonction 275 276@funindex define-void-function 277@funindex \void 278 279Il arrive qu'une procédure soit exécutée pour réaliser une action, non 280pour renvoyer une valeur. Certains langages de programmation, tels 281le C et Scheme, utilisent des fonctions dans les deux cas et se 282débarrassent tout bonnement de la valeur renvoyée ; en règle 283générale, il suffit que l'expression fasse office de déclaration, et 284d'ignorer le résultat. C'est futé, mais pas sans risque d'erreur : 285la plupart des compilateurs C actuels déclenchent un avertissement si 286l'on se débarrasse de certaines expressions non @emph{void}. Pour de 287nombreuses fonctions réalisant une action, les standards Scheme 288déclarent que la valeur de retour est indéfinie. L'interpréteur Guile 289qu'utilise le Scheme de LilyPond dispose d'une valeur unique 290@code{*unspecified*} qu'il retourne alors, en règle générale -- notamment 291lorsqu'on utilise @code{set!} directement sur une variable -- mais 292malheureusement pas toujours. 293 294Une fonction LilyPond définie à l'aide de la clause 295@code{define-void-function} vous apporte l'assurance que c'est cette 296valeur spéciale -- la seule valeur qui satisfasse au prédicat 297@code{void?} -- qui sera retournée. 298 299@example 300noPointAndClick = 301#(define-void-function 302 () 303 () 304 (ly:set-option 'point-and-click #f)) 305@dots{} 306\noPointAndClick % desactive le "pointer-cliquer" 307@end example 308 309L'utilisation d'un préfixe @code{\void} permet ainsi d'évaluer une 310expression pour ses effets annexes sans interprétation d'une quelconque 311valeur de retour : 312 313@example 314\void #(hashq-set! une-table une-clé une-valeur) 315@end example 316 317Vous serez alors assuré que LilyPond ne tentera pas d'affecter un sens à 318la valeur de retour, à quelque endroit qu'elle ressorte. Ceci est aussi 319opérationnel dans le cadre de fonctions musicales telles que 320@code{\displayMusic}. 321 322 323@node Fonctions musicales 324@section Fonctions musicales 325@translationof Music functions 326 327@cindex musicale, fonction 328 329Les @emph{fonctions musicales} sont des procédures Scheme capables de 330créer automatiquement des expressions musicales ; elles permettent 331de grandement simplifier un fichier source. 332 333@menu 334* Définition de fonctions musicales:: 335* Utilisation de fonctions musicales:: 336* Fonctions de substitution simple:: 337* Fonctions de substitution intermédiaires:: 338* De l'usage des mathématiques dans les fonctions:: 339* Fonctions dépourvues d'argument:: 340* Fonctions musicales fantômes:: 341@end menu 342 343 344@node Définition de fonctions musicales 345@subsection Définition de fonctions musicales 346@translationof Music function definitions 347 348@cindex fonction musicale, définition 349 350@funindex define-music-function 351 352Une fonction musicale se définit ainsi : 353 354@example 355fonction = 356#(define-music-function 357 (@var{arg1} @var{arg2}@dots{}) 358 (@var{type1?} @var{type2?}@dots{}) 359 @var{corps}) 360@end example 361 362@noindent 363de manière similaire aux @ref{Définition de fonctions Scheme, fonctions 364Scheme}. La plupart du temps, le @var{corps} sera constitué d'un 365@ref{Blocs de code LilyPond, bloc de code LilyPond}. 366 367Les différents types des prédicat sont recensés à l'annexe 368@ruser{Types de prédicats prédéfinis}. 369 370@morerefs 371Manuel de notation : 372@ruser{Types de prédicats prédéfinis}. 373 374Fichiers d'initialisation : 375@file{lily/music-scheme.cc}, 376@file{scm/c++.scm}, 377@file{scm/lily.scm}. 378 379 380@node Utilisation de fonctions musicales 381@subsection Utilisation de fonctions musicales 382@translationof Music function usage 383 384Une « fonction musicale » doit impérativement renvoyer une expression 385répondant au prédicat @code{ly:music?}. Ceci a pour conséquence 386d'autoriser l'appel à une fonction musicale en tant qu'argument de type 387@code{ly:music?} dans le cadre de l'appel à une autre fonction musicale. 388 389Certaines restrictions s'appliqueront selon le contexte où une fonction 390musicale est utilisée, de telle sorte que l'analyse syntaxique soit sans 391ambiguïté. 392 393@itemize 394@item 395Dans une expression musicale de haut niveau, aucun postévénement n'est 396toléré. 397 398@item 399Lorsqu'une fonction musicale -- contrairement à une fonction 400événementielle -- renvoie une expression de type postévénement, LilyPond 401requiert son introduction par un indicateur de positionnement -- à 402savoir @code{-}, @code{^} ou @code{_} -- de telle sorte que le 403postévénement produit par l'appel à cette fonction s'intègre 404correctement dans l'expression environnante. 405 406@item 407En tant que partie d'un accord, l'expression musicale renvoyée doit 408être du type @code{rhythmic-event}, et plus particulièrement un 409@code{NoteEvent}. 410@end itemize 411 412@noindent 413Des fonctions « polymorphes » telles que @code{\tweak} peuvent 414s'appliquer aux postévénements, constituants d'accord et expressions de 415haut niveau. 416 417 418@node Fonctions de substitution simple 419@subsection Fonctions de substitution simple 420@translationof Simple substitution functions 421 422Une fonction de substitution simple renvoie une expression musicale 423écrite au format LilyPond et contient des arguments au format de 424l'expression résultante. Vous en trouverez une description détaillée à 425la rubrique @ruser{Exemples de fonction de substitution}. 426 427 428@node Fonctions de substitution intermédiaires 429@subsection Fonctions de substitution intermédiaires 430@translationof Intermediate substitution functions 431 432Une fonction de substitution intermédiaire est une fonction dont 433l'expression musicale résultante mélangera du code Scheme au code 434LilyPond. 435 436Certaines commandes @code{\override} nécessitent un argument 437supplémentaire constitué d'une paire de nombres, appelée @emph{cons 438cell} en Scheme -- que l'on pourrait traduire par « construction de 439cellule ». 440 441Cette paire peut se mentionner directement dans la fonction musicale à 442l'aide d'une variable @code{pair?} : 443 444@example 445manualBeam = 446#(define-music-function 447 (beg-end) 448 (pair?) 449 #@{ 450 \once \override Beam.positions = #beg-end 451 #@}) 452 453\relative c' @{ 454 \manualBeam #'(3 . 6) c8 d e f 455@} 456@end example 457 458Autre manière de procéder, les nombres formant la paire sont transmis 459comme arguments séparés ; le code Scheme chargé de créer la paire 460pourra alors être inclus dans l'expression musicale : 461 462@lilypond[quote,verbatim,ragged-right] 463manualBeam = 464#(define-music-function 465 (beg end) 466 (number? number?) 467 #{ 468 \once \override Beam.positions = #(cons beg end) 469 #}) 470 471\relative c' { 472 \manualBeam #3 #6 c8 d e f 473} 474@end lilypond 475 476@funindex \temporary 477@cindex temporaire, dérogation (override) 478@cindex dérogation temporaire (override) 479@cindex propriétés, retour à la valeur précédente 480 481L'entretien des propriétés peut se voir comme un empilement par 482propriété par objet par contexte. Les fonctions musicales peuvent 483nécessiter des dérogations pour une ou plusieurs propriétés pour la 484durée de la fonction, puis de revenir aux valeurs précédentes avant de 485quitter. Néanmoins, une dérogation normale va retirer de la pile -- ou 486dépiler -- et supprimer le sommet de la pile de la propriété avant 487d'y ajouter quoi que ce soit -- ou empiler -- ; la valeur précédente de 488la propriété est de fait perdue. Lorsque la valeur antérieure doit être 489préservée, l'instruction @code{\override} devra être préfixée d'un 490@code{\temporary}, comme ceci : 491 492@example 493\temporary \override @dots{} 494@end example 495 496L'utilisation d'un @code{\temporary} a pour effet d'effacer la propriété 497@code{pop-first} (@emph{commence par dépiler} normalement activée) de la 498dérogation ; la valeur antérieure ne sera alors pas supprimée de la pile 499de la propriété avant d'y empiler la nouvelle valeur. Lorsqu'un 500@code{\revert} viendra par la suite supprimer la valeur dérogatoire 501temporaire, réapparaitra la valeur antérieure. 502 503En d'autres termes, un @code{\revert} qui suit un @code{\temporary 504\override} pour la même propriété n'apporte rien. Ce principe est aussi 505valable pour un couple @code{\temporary} et @code{\undo} sur la même 506musique contenant des dérogations. 507 508Voici un exemple de fonction musicale utilisant cette fonctionnalité. 509La présence du @code{\temporary} permet de s'assurer qu'en sortant de la 510fonction, les propriétés @code{cross-staff} et @code{style} retrouveront 511les valeurs qu'elles avaient avant que ne soit appelée la fonction 512@code{crossStaff}. En l'absence de @code{\temporary}, ces propriétés 513auraient retrouvé leurs valeurs par défaut à la sortie de la fonction. 514 515@example 516crossStaff = 517#(define-music-function (notes) (ly:music?) 518 (_i "Create cross-staff stems") 519 #@{ 520 \temporary \override Stem.cross-staff = #cross-staff-connect 521 \temporary \override Flag.style = #'no-flag 522 #notes 523 \revert Stem.cross-staff 524 \revert Flag.style 525#@}) 526@end example 527 528 529@node De l'usage des mathématiques dans les fonctions 530@subsection De l'usage des mathématiques dans les fonctions 531@translationof Mathematics in functions 532 533Une fonction musicale peut requérir, en plus d'une simple substitution, 534une part de programmation en Scheme. 535 536@lilypond[quote,verbatim,ragged-right] 537AltOn = 538#(define-music-function 539 (mag) 540 (number?) 541 #{ 542 \override Stem.length = #(* 7.0 mag) 543 \override NoteHead.font-size = 544 #(inexact->exact (* (/ 6.0 (log 2.0)) (log mag))) 545 #}) 546 547AltOff = { 548 \revert Stem.length 549 \revert NoteHead.font-size 550} 551 552\relative { 553 c'2 \AltOn #0.5 c4 c 554 \AltOn #1.5 c c \AltOff c2 555} 556@end lilypond 557 558@noindent 559Cette fonction pourrait tout à fait être réécrite de telle sorte qu'elle 560s'applique à une expression musicale : 561 562@lilypond[quote,verbatim,ragged-right] 563withAlt = 564#(define-music-function 565 (mag music) 566 (number? ly:music?) 567 #{ 568 \override Stem.length = #(* 7.0 mag) 569 \override NoteHead.font-size = 570 #(inexact->exact (* (/ 6.0 (log 2.0)) (log mag))) 571 #music 572 \revert Stem.length 573 \revert NoteHead.font-size 574 #}) 575 576\relative { 577 c'2 \withAlt #0.5 { c4 c } 578 \withAlt #1.5 { c c } c2 579} 580@end lilypond 581 582 583@node Fonctions dépourvues d'argument 584@subsection Fonctions dépourvues d'argument 585@translationof Functions without arguments 586 587Dans la plupart des cas, une fonction dépourvue d'argument devrait 588être créée à l'aide d'une variable : 589 590@example 591dolce = \markup@{ \italic \bold dolce @} 592@end example 593 594Il peut, dans certains cas particuliers, s'avérer utile de créer une 595fonction sans argument comme ici, 596 597@example 598displayBarNum = 599#(define-music-function 600 () 601 () 602 (if (eq? #t (ly:get-option 'display-bar-numbers)) 603 #@{ \once \override Score.BarNumber.break-visibility = ##f #@} 604 #@{#@})) 605@end example 606 607@noindent 608de manière à pouvoir afficher les numéros de mesure grâce à un appel à 609cette fonction. En pareil cas, vous devrez invoquer @command{lilypond} 610en respectant la syntaxe 611 612@example 613lilypond -d display-bar-numbers MONFICHIER.ly 614@end example 615 616 617@node Fonctions musicales fantômes 618@subsection Fonctions musicales fantômes 619@translationof Void music functions 620 621Une fonction musicale doit renvoyer une expression musicale. Toutefois, 622une fonction musicale peut n'être exécutée que dans le but d'en retenir 623les effets annexes ; vous devrez alors utiliser une procédure 624@code{define-void-function}. Il peut cependant arriver que vous ayez 625besoin d'une fonction qui, selon le cas, produise ou non (comme dans 626l'exemple de la rubrique précédente) une expression musicale. 627L'utilisation d'un @code{#@{ #@}} vous permettra de renvoyer une 628expression musicale @code{void}. 629 630 631@node Fonctions événementielles 632@section Fonctions événementielles 633@translationof Event functions 634 635@funindex define-event-function 636@cindex événementielle, fonction 637 638L'utilisation d'une fonction musicale pour placer un événement requiert 639l'insertion d'un indicateur de position, ce qui peut ne pas correspondre 640à la syntaxe de la construction à remplacer. C'est par exemple le cas 641lorsque vous voulez écrire une commande de nuance, instruction qui 642ne comporte habituellement pas d'indicateur de positionnement, comme 643dans @code{c'\pp}. Voici de quoi vous permettre de mentionner n'importe 644quelle nuance : 645 646@lilypond[quote,verbatim,ragged-right] 647dyn=#(define-event-function (arg) (markup?) 648 (make-dynamic-script arg)) 649\relative { c'\dyn pfsss } 650@end lilypond 651 652Vous pourriez obtenir le même résultat avec une fonction musicale, à 653ceci près que chaque appel à la fonction devra être précédé d'un 654indicateur de positionnement, comme @code{c-\dyn pfsss}. 655 656 657@node Fonctions pour markups 658@section Fonctions pour @emph{markups} 659@translationof Markup functions 660 661Les @emph{markups} sont implémentés au travers de fonctions Scheme 662spécifiques qui produisent des objets @code{Stencil} comprenant un 663certain nombre d'arguments. 664 665@menu 666* Construction d'un markup en Scheme:: 667* Fonctionnement interne des markups:: 668* Définition d'une nouvelle commande de markup:: 669* Définition d'une nouvelle commande de liste de markups:: 670@end menu 671 672 673@node Construction d'un markup en Scheme 674@subsection Construction d'un @emph{markup} en Scheme 675@translationof Markup construction in Scheme 676 677@cindex définition d'une commande markup 678@cindex markup, définition d'une commande 679 680@funindex \displayScheme 681 682Les expressions @emph{markup} sont représentées en Scheme de manière 683interne par la macro @code{markup} : 684 685@example 686(markup @var{expression}) 687@end example 688 689La commande @code{\displayScheme} permet d'obtenir la représentation en 690Scheme d'une expression @emph{markup} : 691 692@example 693\displayScheme 694\markup @{ 695 \column @{ 696 \line @{ \bold \italic "hello" \raise #0.4 "world" @} 697 \larger \line @{ foo bar baz @} 698 @} 699@} 700@end example 701 702@noindent 703Compiler ce code renverra en console les lignes suivantes : 704 705@example 706(markup 707 #:line 708 (#:column 709 (#:line 710 (#:bold (#:italic "hello") #:raise 0.4 "world") 711 #:larger 712 (#:line 713 (#:simple "foo" #:simple "bar" #:simple "baz"))))) 714@end example 715 716L'impression du @emph{markup} sera suspendue dès lors qu'apparaîtra un 717@w{@samp{\void \displayScheme @var{markup}}}. Tout comme pour la 718commande @code{\displayMusic}, le résultat de @code{\displayScheme} peut 719être sauvegardé dans un fichier séparé. Voir à ce sujet 720@ref{Affichage d'expressions musicales}. 721 722@noindent 723Vous pouvez constater les principales règles de traduction entre les 724syntaxes respectives de LilyPond et de Scheme en matière de 725@emph{markup}. Bien que le passage en syntaxe LilyPond grâce à 726@code{#@{ @dots{} #@}} apporte de la souplesse, nous allons voir comment 727utiliser la macro @code{markup} en Scheme exclusivement. 728 729@quotation 730@multitable @columnfractions .3 .3 731@item @b{LilyPond} @tab @b{Scheme} 732@item @code{\markup markup1} @tab @code{(markup markup1)} 733@item @code{\markup @{ markup1 markup2@dots{} @}} @tab 734 @code{(markup markup1 markup2@dots{} )} 735@item @code{\commande-markup} @tab @code{#:commande-markup} 736@item @code{\variable} @tab @code{variable} 737@item @code{\center-column @{ @dots{} @}} @tab 738 @code{#:center-column ( @dots{} )} 739@item @code{chaîne} @tab @code{"chaîne"} 740@item @code{#argument-scheme} @tab @code{argument-scheme} 741@end multitable 742@end quotation 743 744L'intégralité du langage Scheme est accessible à l'intérieur même de la 745macro @code{markup}. Vous pouvez ainsi appeler des fonctions à partir 746de @code{markup} pour manipuler des chaînes de caractères, ce qui est 747particulièrement pratique lorsque vous créez votre propre commande de 748@emph{markup} -- voir 749@ref{Définition d'une nouvelle commande de markup}. 750 751@knownissues 752L'argument @var{markup-list} des commandes @code{#:line}, 753@code{#:center} ou @code{#:column} ne saurait être une variable ni le 754résultat de l'appel à une fonction. 755 756@lisp 757(markup #:line (fonction-qui-retourne-des-markups)) 758@end lisp 759 760@noindent 761n'est pas valide. Il vaut mieux, en pareil cas, utiliser les fonctions 762@code{make-line-markup}, @code{make-center-markup} ou 763@code{make-column-markup} : 764 765@lisp 766(markup (make-line-markup (fonction-qui-retourne-des-markups))) 767@end lisp 768 769 770@node Fonctionnement interne des markups 771@subsection Fonctionnement interne des @emph{markups} 772@translationof How markups work internally 773 774Dans un @emph{markup} tel que 775 776@example 777\raise #0.5 "text example" 778@end example 779 780@noindent 781@code{\raise} représente en fait la fonction @code{raise-markup}. 782L'expression @emph{markup} est enregistrée sous la forme 783 784@example 785(list raise-markup 0.5 (list simple-markup "text example")) 786@end example 787 788Lorsque ce @emph{markup} est converti en objets imprimables (stencils), 789la fonction @code{raise-markup} est appelée ainsi : 790 791@example 792(apply raise-markup 793 @var{\layout objet} 794 @var{liste des alists de propriété} 795 0.5 796 @var{le @emph{markup} "text example"}) 797@end example 798 799La fonction @code{raise-markup} commence par créer le stencil pour la 800chaîne @code{text example}, puis remonte ce stencil d'un demi espace de 801portée. Il s'agit là d'un exemple relativement simple, et nous en 802aborderons de plus complexes au fil des paragraphes suivants ; 803d'autres exemples se trouvent directement dans le fichier 804@file{scm/define-markup-commands.scm}. 805 806 807@node Définition d'une nouvelle commande de markup 808@subsection Définition d'une nouvelle commande de @emph{markup} 809@translationof New markup command definition 810 811Nous allons étudier dans ce qui suit la manière de définir une nouvelle 812commande de @emph{markup}. 813 814@menu 815* Syntaxe d'une commande markup:: 816* Attribution de propriétés:: 817* Exemple commenté:: 818* Adaptation d'une commande incorporée:: 819@end menu 820 821 822@node Syntaxe d'une commande markup 823@unnumberedsubsubsec Syntaxe d'une commande @emph{markup} 824@translationof Markup command definition syntax 825 826Une commande de @emph{markup} personnalisée se définit à l'aide de la 827macro Scheme @code{define-markup-command}, placée en tête de fichier. 828 829@lisp 830(define-markup-command (@var{nom-commande} @var{layout} @var{props} @var{arg1} @var{arg2}@dots{}) 831 (@var{arg1-type?} @var{arg2-type?}@dots{}) 832 [ #:properties ((@var{propriété1} @var{valeur-par-défaut1}) 833 @dots{}) ] 834 @dots{}corps de la commande@dots{}) 835@end lisp 836 837Quelques commentaires sur les arguments : 838 839@table @code 840@item @var{nom-commande} 841le nom que vous attribuez à votre commande de @emph{markup}. 842@item layout 843la définition du « layout » -- son formatage. 844@item props 845une liste de listes associatives, comprenant toutes les propriétés actives. 846@item @var{argi} 847le @var{ième} argument de la commande. 848@item @var{argi-type?} 849un type de prédicat pour le @var{ième} argument. 850@end table 851 852Si la commande utilise des propriétés à partir des arguments 853@code{props}, le mot-clé @code{#:properties} permet de spécifier ces 854différentes propriétés ainsi que leur valeur par défaut. 855 856Les arguments se distinguent selon leur type : 857@itemize 858@item un @emph{markup}, correspondant au type de prédicat 859@code{markup?} ; 860@item une liste de @emph{markups}, correspondant au type de prédicat 861@code{markup-list?} ; 862@item tout autre objet Scheme, correspondant au types de prédicat tels 863que @code{list?}, @code{number?}, @code{boolean?}, etc. 864@end itemize 865 866Il n'existe aucune restriction quant à l'ordre des arguments fournis à 867la suite des arguments @code{layout} et @code{props}. Néanmoins, les 868fonctions @emph{markup} qui ont en dernier argument un @emph{markup} ont 869ceci de particulier qu'elles peuvent s'appliquer à des listes de 870@emph{markups} ; ceci résultera en une liste de @emph{markups} où 871tous les éléments de la liste originelle se verront appliquer cette 872fonction @emph{markup} avec ses arguments de tête. 873 874La réplication des arguments de tête dans le but d'appliquer une 875fonction @emph{markup} à une liste de markups est économique, 876principalement lorsqu'il s'agit d'arguments Scheme. Vous éviterez 877ainsi d'éventuelles pertes de performance en utilisant des arguments 878Scheme en tant qu'arguments principaux d'une fonction @emph{markup} dont 879le dernier argument est un @emph{markup}. 880 881@cindex markup macro 882@cindex macro de markup 883@funindex \markup 884@funindex interpret-markup 885 886Les commandes de @emph{markup} ont un cycle de vie relativement 887complexe. Le corps de la définition d'une commande de @emph{markup} est 888chargé de convertir les arguments de la commande en expression stencil 889qui sera alors renvoyée. Bien souvent, ceci s'accomplit par un appel à 890la fonction @code{interpret-markup}, en lui passant les arguments 891@var{layout} et @var{props}. Ces arguments ne seront en principe connus 892que bien plus tardivement dans le processus typographique. Lors de 893l'expansion d'une expression LilyPond @code{\markup} ou d'une macro 894Scheme @code{markup}, les expressions @emph{markup} auront déjà vu leurs 895composants assemblés en expressions @emph{markup}. L'évaluation et le 896contrôle du type des arguments à une commande de @emph{markup} 897n'interviennent qu'au moment de l'interprétation de @code{\markup} ou 898@code{markup}. 899 900Seule l'application de @code{interpret-markup} sur une expression 901@emph{markup} réalisera effectivement la conversion des expressions 902@emph{markup} en stencil, au travers de l'exécution du corps des 903fonctions @emph{markup}. 904 905 906@node Attribution de propriétés 907@unnumberedsubsubsec Attribution de propriétés 908@translationof On properties 909 910Les arguments @code{layout} et @code{props} d'une commande de 911@emph{markup} fournissent un contexte à l'interprétation du 912@emph{markup} : taille de fonte, longueur de ligne, etc. 913 914L'argument @code{layout} permet d'accéder aux propriétés définies dans 915les blocs @code{\paper}, grâce à la fonction 916@code{ly:output-def-lookup}. Par exemple, la longueur de ligne, 917identique à celle de la partition, est lue au travers de 918 919@example 920(ly:output-def-lookup layout 'line-width) 921@end example 922 923L'argument @code{props} rend certaines propriétés accessibles aux 924commandes de @emph{markup}. Il en va ainsi lors de l'interprétation 925d'un @emph{markup} de titre d'ouvrage : toutes les variables 926définies dans le bloc @code{\header} sont automatiquement ajoutées aux 927@code{props}, de telle sorte que le @emph{markup} de titrage de 928l'ouvrage pourra accéder aux différents champs titre, compositeur, etc. 929Ceci permet aussi de configurer le comportement d'une commande de 930@emph{markup} : la taille des fontes, par exemple, est lue à 931partir de @code{props} plutôt que grâce à un argument @code{font-size}. 932La fonction appelant une commande de @emph{markup} peut altérer la 933valeur de la propriété taille des fontes et donc en modifier le 934comportement. L'utilisation du mot-clé @code{#:properties}, attaché à 935@code{define-markup-command}, permet de spécifier les propriétés devant 936être lues parmi les arguments @code{props}. 937 938L'exemple proposé à la rubrique suivante illustre comment, au sein d'une 939commande de @emph{markup}, accéder aux différentes propriétés et les 940modifier. 941 942 943@node Exemple commenté 944@unnumberedsubsubsec Exemple commenté 945@translationof A complete example 946 947Nous allons, dans cet exemple, nous attacher à encadrer du texte avec un 948double liseré. 949 950Commençons par construire quelque chose d'approximatif à l'aide d'un 951simple @emph{markup}. La lecture de @ruser{Commandes pour markup} nous 952indique la commande @code{\box}, qui semble ici appropriée. 953 954@lilypond[quote,verbatim,ragged-right] 955\markup \box \box HELLO 956@end lilypond 957 958Dans un souci d'esthétique, nous aimerions que le texte et les 959encadrements ne soient pas autant accolés. Selon la documentation de 960@code{\box}, cette commande utilise la propriété @code{box-padding}, 961fixée par défaut à 0,2. Cette même documentation nous indique 962aussi comment la modifier : 963 964@lilypond[quote,verbatim,ragged-right] 965\markup \box \override #'(box-padding . 0.6) \box A 966@end lilypond 967 968L'espacement des deux liserés est cependant toujours trop réduit ; 969modifions le à son tour : 970 971@lilypond[quote,verbatim,ragged-right] 972\markup \override #'(box-padding . 0.4) \box 973 \override #'(box-padding . 0.6) \box A 974@end lilypond 975 976Vous conviendrez que recopier une telle définition de @emph{markup} 977deviendra vite fastidieux. C'est pourquoi nous écrivons la commande de 978@emph{markup} @code{double-box} qui prendra un seul argument -- le 979texte. Cette commande se chargera de dessiner les encadrements, en 980tenant compte des espacements. 981 982@lisp 983#(define-markup-command (double-box layout props text) (markup?) 984 "Dessine un double encadrement autour du texte." 985 (interpret-markup layout props 986 #@{\markup \override #'(box-padding . 0.4) \box 987 \override #'(box-padding . 0.6) \box @{ #text @}#@})) 988@end lisp 989 990@noindent 991ou bien son équivalent 992 993@lisp 994#(define-markup-command (double-box layout props text) (markup?) 995 "Dessine un double encadrement autour du texte." 996 (interpret-markup layout props 997 (markup #:override '(box-padding . 0.4) #:box 998 #:override '(box-padding . 0.6) #:box text))) 999@end lisp 1000 1001@code{text} est le nom de l'argument de notre commande, et 1002@code{markup?} son type -- l'argument sera identifié comme étant un 1003@emph{markup}. La fonction @code{interpret-markup}, utilisée dans la 1004plupart des commandes de @emph{markup}, construira un stencil à partir 1005de @code{layout}, @code{props} et un @emph{markup}. Dans la seconde 1006variante, ce @emph{markup} sera construit à l'aide de la macro Scheme 1007@code{markup} -- voir @ref{Construction d'un markup en Scheme}. La 1008transformation d'une expression @code{\markup} en expression Scheme est 1009des plus triviales. 1010 1011Notre commande personnalisée s'utilise ainsi : 1012 1013@example 1014\markup \double-box A 1015@end example 1016 1017Il serait intéressant de rendre cette commande @code{double-box} plus 1018souple : les valeurs de @code{box-padding} sont figées et ne 1019peuvent être modifiées à l'envie. Pareillement, il serait bien de 1020distinguer l'espacement entre les encadrements de l'espacement entre le 1021texte et ses encadrements. Nous allons donc introduire une propriété 1022supplémentaire, que nous appellerons @code{inter-box-padding}, chargée 1023de gérer l'espacement des encadrements ; @code{box-padding} ne 1024servira alors que pour l'espacement intérieur. Voici le code adapté à 1025ces évolutions : 1026 1027@lisp 1028#(define-markup-command (double-box layout props text) (markup?) 1029 #:properties ((inter-box-padding 0.4) 1030 (box-padding 0.6)) 1031 "Dessine un double encadrement autour du texte." 1032 (interpret-markup layout props 1033 #@{\markup \override #`(box-padding . ,inter-box-padding) \box 1034 \override #`(box-padding . ,box-padding) \box 1035 @{ #text @} #@})) 1036@end lisp 1037 1038Ainsi que son équivalent à partir de la macro @emph{markup} : 1039 1040@lisp 1041#(define-markup-command (double-box layout props text) (markup?) 1042 #:properties ((inter-box-padding 0.4) 1043 (box-padding 0.6)) 1044 "Dessine un double encadrement autour du texte." 1045 (interpret-markup layout props 1046 (markup #:override `(box-padding . ,inter-box-padding) #:box 1047 #:override `(box-padding . ,box-padding) #:box text))) 1048@end lisp 1049 1050C'est ici le mot-clé @code{#:properties} qui permet de lire les 1051propriétés @code{inter-box-padding} et @code{box-padding} à partir de 1052l'argumenet @code{props} ; on leur a d'ailleurs fourni des valeurs 1053par défaut au cas où elles ne seraient pas définies. 1054 1055Ces valeurs permettront alors d'adapter les propriétés de 1056@code{box-padding} utilisées par les deux commandes @code{\box}. Vous 1057aurez remarqué, dans l'argument @code{\override}, la présence de 1058l'apostrophe inversée (@code{`}) et de la virgule ; elles vous 1059permettent d'insérer une valeur variable au sein d'une expression 1060littérale. 1061 1062Notre commande est maintenant prête à servir dans un @emph{markup}, et 1063les encadrements sont repositionnables. 1064 1065@lilypond[quote,verbatim,ragged-right] 1066#(define-markup-command (double-box layout props text) (markup?) 1067 #:properties ((inter-box-padding 0.4) 1068 (box-padding 0.6)) 1069 "Draw a double box around text." 1070 (interpret-markup layout props 1071 #{\markup \override #`(box-padding . ,inter-box-padding) \box 1072 \override #`(box-padding . ,box-padding) \box 1073 { #text } #})) 1074 1075\markup \double-box A 1076\markup \override #'(inter-box-padding . 0.8) \double-box A 1077\markup \override #'(box-padding . 1.0) \double-box A 1078@end lilypond 1079 1080 1081@node Adaptation d'une commande incorporée 1082@unnumberedsubsubsec Adaptation d'une commande incorporée 1083@translationof Adapting builtin commands 1084 1085Le meilleur moyen de construire ses propres commandes de @emph{markup} 1086consiste à prendre exemple sur les commandes déjà incorporées. La 1087plupart des commandes de @emph{markup} fournies avec LilyPond sont 1088répertoriées dans le fichier @file{scm/define-markup-commands.scm}. 1089 1090Nous pourrions, par exemple, envisager d'adapter la commande 1091@code{\draw-line} pour dessiner plutôt une ligne double. Voici comment 1092est définie la commande @code{\draw-line}, expurgée de sa 1093documentation : 1094 1095@lisp 1096(define-markup-command (draw-line layout props dest) 1097 (number-pair?) 1098 #:category graphic 1099 #:properties ((thickness 1)) 1100 "@dots{}documentation@dots{}" 1101 (let ((th (* (ly:output-def-lookup layout 'line-thickness) 1102 thickness)) 1103 (x (car dest)) 1104 (y (cdr dest))) 1105 (make-line-stencil th 0 0 x y))) 1106@end lisp 1107 1108Avant de définir notre propre commande basée sur l'une de celles 1109fournies par LilyPond, commençons par en recopier la définition, puis 1110attribuons lui un autre nom. Le mot-clé @code{#:category} peut être 1111supprimé sans risque ; il ne sert que lors de la génération de la 1112documentation et n'est d'aucune utilité pour une commande personnalisée. 1113 1114@lisp 1115(define-markup-command (draw-double-line layout props dest) 1116 (number-pair?) 1117 #:properties ((thickness 1)) 1118 "@dots{}documentation@dots{}" 1119 (let ((th (* (ly:output-def-lookup layout 'line-thickness) 1120 thickness)) 1121 (x (car dest)) 1122 (y (cdr dest))) 1123 (make-line-stencil th 0 0 x y))) 1124@end lisp 1125 1126Nous ajoutons ensuite une propriété pour gérer l'écart entre les deux 1127lignes, que nous appelons @code{line-gap}, et lui attribuons une valeur 1128par défaut de 6 dixièmes : 1129 1130@lisp 1131(define-markup-command (draw-double-line layout props dest) 1132 (number-pair?) 1133 #:properties ((thickness 1) 1134 (line-gap 0.6)) 1135 "@dots{}documentation@dots{}" 1136 @dots{} 1137@end lisp 1138 1139Nous ajoutons enfin le code qui dessinera nos deux lignes. Deux appels 1140à @code{make-line-stencil} permettrons de dessiner les lignes dont nous 1141regrouperons les stencils à l'aide de @code{ly:stencil-add} : 1142 1143@lilypond[quote,verbatim,ragged-right] 1144#(define-markup-command (my-draw-line layout props dest) 1145 (number-pair?) 1146 #:properties ((thickness 1) 1147 (line-gap 0.6)) 1148 "..documentation.." 1149 (let* ((th (* (ly:output-def-lookup layout 'line-thickness) 1150 thickness)) 1151 (dx (car dest)) 1152 (dy (cdr dest)) 1153 (w (/ line-gap 2.0)) 1154 (x (cond ((= dx 0) w) 1155 ((= dy 0) 0) 1156 (else (/ w (sqrt (+ 1 (* (/ dx dy) (/ dx dy)))))))) 1157 (y (* (if (< (* dx dy) 0) 1 -1) 1158 (cond ((= dy 0) w) 1159 ((= dx 0) 0) 1160 (else (/ w (sqrt (+ 1 (* (/ dy dx) (/ dy dx)))))))))) 1161 (ly:stencil-add (make-line-stencil th x y (+ dx x) (+ dy y)) 1162 (make-line-stencil th (- x) (- y) (- dx x) (- dy y))))) 1163 1164\markup \my-draw-line #'(4 . 3) 1165\markup \override #'(line-gap . 1.2) \my-draw-line #'(4 . 3) 1166@end lilypond 1167 1168 1169@node Définition d'une nouvelle commande de liste de markups 1170@subsection Définition d'une nouvelle commande de liste de @emph{markups} 1171@translationof New markup list command definition 1172 1173@cindex liste de markup, définition de commande 1174@funindex define-markup-list-command 1175@funindex interpret-markup-list 1176 1177Une commande traitant une liste de @emph{markups} se définit à l'aide de 1178la macro Scheme @code{define-markup-list-command}, de manière analogue à 1179la macro @code{define-markup-command} abordée à la rubrique 1180@ref{Définition d'une nouvelle commande de markup}, à ceci près que 1181cette dernière renvoie un seul stencil, non une liste de stencils. 1182 1183La fonction @code{interpret-markup-list}, à l'instar de la fonction 1184@code{interpret-markup}, permet de convertir une liste de @emph{markups} 1185en liste de stencils. 1186 1187Dans l'exemple suivant, nous définissons @code{\paragraph}, une commande 1188de liste de @emph{markups}, qui renverra une liste de lignes justifiées 1189dont la première sera indentée. La largeur de l'alinéa sera récupérée 1190par l'argument @code{props}. 1191 1192@example 1193#(define-markup-list-command (paragraph layout props args) (markup-list?) 1194 #:properties ((par-indent 2)) 1195 (interpret-markup-list layout props 1196 #@{\markuplist \justified-lines @{ \hspace #par-indent #args @} #@})) 1197@end example 1198 1199La version purement Scheme est un peu plus complexe : 1200@example 1201#(define-markup-list-command (paragraph layout props args) (markup-list?) 1202 #:properties ((par-indent 2)) 1203 (interpret-markup-list layout props 1204 (make-justified-lines-markup-list (cons (make-hspace-markup par-indent) 1205 args)))) 1206@end example 1207 1208En dehors des habituels arguments @code{layout} et @code{props}, la 1209commande de liste de @emph{markups} @code{paragraph} prend en argument 1210une liste de @emph{markups} appelée @code{args}. Le prédicat des listes 1211de @emph{markups} est @code{markup-list?}. 1212 1213Pour commencer, la fonction récupère la taille de l'alinéa, propriété 1214ici dénommée @code{par-indent}, à partir de la liste de propriétés 1215@code{props}. En cas d'absence, la valeur par défaut sera 1216de @code{2}. Ensuite est créée une liste de lignes justifiées 1217grâce à la commande prédéfinie @code{\justified-lines}, liée à la 1218fonction @code{make-justified-lines-markup-list}. Un espace horizontal 1219est ajouté en tête, grâce à @code{\hspace} ou à la fonction 1220@code{make-hspace-markup}. Enfin, la liste de @emph{markups} est 1221interprétée par la fonction @code{interpret-markup-list}. 1222 1223Voici comment utiliser cette nouvelle commande de liste de 1224@emph{markups} : 1225 1226@example 1227\markuplist @{ 1228 \paragraph @{ 1229 The art of music typography is called \italic @{(plate) engraving.@} 1230 The term derives from the traditional process of music printing. 1231 Just a few decades ago, sheet music was made by cutting and stamping 1232 the music into a zinc or pewter plate in mirror image. 1233 @} 1234 \override-lines #'(par-indent . 4) \paragraph @{ 1235 The plate would be inked, the depressions caused by the cutting 1236 and stamping would hold ink. An image was formed by pressing paper 1237 to the plate. The stamping and cutting was completely done by 1238 hand. 1239 @} 1240@} 1241@end example 1242 1243 1244@node Contextes pour programmeurs 1245@section Contextes pour programmeurs 1246@translationof Contexts for programmers 1247 1248@menu 1249* Évaluation d'un contexte:: 1250* Application d'une fonction à tous les objets de mise en forme:: 1251@end menu 1252 1253 1254@node Évaluation d'un contexte 1255@subsection Évaluation d'un contexte 1256@translationof Context evaluation 1257 1258@cindex appel de code durant l'interprétation 1259@funindex \applyContext 1260@funindex make-apply-context 1261@funindex ly:context-property 1262@funindex ly:context-set-property! 1263@funindex ly:context-grob-definition 1264@funindex ly:assoc-get 1265@funindex ly:context-pushpop-property 1266 1267Un contexte peut être modifié, au moment même de son interprétation, par 1268du code Scheme. La syntaxe consacrée au sein d'un bloc LilyPond est 1269 1270@example 1271\applyContext @var{fonction} 1272@end example 1273 1274@noindent 1275et, dans le cadre d'un code Scheme : 1276 1277@example 1278(make-apply-context @var{fonction}) 1279@end example 1280 1281@code{@var{fonction}} est constitué d'une fonction Scheme comportant un 1282unique argument : le contexte au sein duquel la commande 1283@code{\applyContext} est appelée. Cette fonction peut accéder aussi 1284bien aux propriétés de @emph{grob} (y compris modifiées par 1285@code{\override} ou @code{\set}) qu'aux propriétés de contexte. Toute 1286action entreprise par la fonction et qui dépendrait de l'état du 1287contexte sera limitée à l'état de ce contexte @b{au moment de l'appel à 1288la fonction}. Par ailleurs, les adaptations résultant d'un appel à 1289@code{\applyContext} seront effectives jusqu'à ce qu'elles soient à 1290nouveau directement modifiées ou bien annulées, quand bien même les 1291conditions initiales dont elles dépendent auraient changé. 1292 1293Voici quelques fonctions Scheme utiles avec @code{\applyContext} : 1294 1295@table @code 1296@item ly:context-property 1297recherche la valeur d'une propriété de contexte, 1298 1299@item ly:context-set-property! 1300détermine une propriété de contexte, 1301 1302@item ly:context-grob-definition 1303@itemx ly:assoc-get 1304recherche la valeur d'une propriété de @emph{grob}, 1305 1306@item ly:context-pushpop-property 1307réalise un @code{\temporary \override} ou un @code{\revert} sur une 1308propriété de @emph{grob}. 1309@end table 1310 1311L'exemple suivant recherche la valeur en cours de @code{fontSize} puis 1312la double : 1313 1314@lilypond[quote,verbatim] 1315doubleFontSize = 1316\applyContext 1317 #(lambda (context) 1318 (let ((fontSize (ly:context-property context 'fontSize))) 1319 (ly:context-set-property! context 'fontSize (+ fontSize 6)))) 1320 1321{ 1322 \set fontSize = -3 1323 b'4 1324 \doubleFontSize 1325 b' 1326} 1327@end lilypond 1328 1329L'exemple suivant recherche la couleur des objets @code{NoteHead}, 1330@code{Stem} et @code{Beam}, puis diminue pour chacun d'eux le degré de 1331saturation. 1332 1333@lilypond[quote,verbatim] 1334desaturate = 1335\applyContext 1336 #(lambda (context) 1337 (define (desaturate-grob grob) 1338 (let* ((grob-def (ly:context-grob-definition context grob)) 1339 (color (ly:assoc-get 'color grob-def black)) 1340 (new-color (map (lambda (x) (min 1 (/ (1+ x) 2))) color))) 1341 (ly:context-pushpop-property context grob 'color new-color))) 1342 (for-each desaturate-grob '(NoteHead Stem Beam))) 1343 1344\relative { 1345 \time 3/4 1346 g'8[ g] \desaturate g[ g] \desaturate g[ g] 1347 \override NoteHead.color = #darkred 1348 \override Stem.color = #darkred 1349 \override Beam.color = #darkred 1350 g[ g] \desaturate g[ g] \desaturate g[ g] 1351} 1352@end lilypond 1353 1354Ceci pourrait tout à fait s'implémenter sous la forme d'une fonction 1355musicale, afin d'en réduire les effets à un seul bloc de musique. Notez 1356comment @code{ly:context-pushpop-property} est utilisé à la fois pour un 1357@code{\temporary \override} et pour un @code{\revert} : 1358 1359@lilypond[quote,verbatim] 1360desaturate = 1361#(define-music-function 1362 (music) (ly:music?) 1363 #{ 1364 \applyContext 1365 #(lambda (context) 1366 (define (desaturate-grob grob) 1367 (let* ((grob-def (ly:context-grob-definition context grob)) 1368 (color (ly:assoc-get 'color grob-def black)) 1369 (new-color (map (lambda (x) (min 1 (/ (1+ x) 2))) color))) 1370 (ly:context-pushpop-property context grob 'color new-color))) 1371 (for-each desaturate-grob '(NoteHead Stem Beam))) 1372 #music 1373 \applyContext 1374 #(lambda (context) 1375 (define (revert-color grob) 1376 (ly:context-pushpop-property context grob 'color)) 1377 (for-each revert-color '(NoteHead Stem Beam))) 1378 #}) 1379 1380\relative { 1381 \override NoteHead.color = #darkblue 1382 \override Stem.color = #darkblue 1383 \override Beam.color = #darkblue 1384 g'8 a b c 1385 \desaturate { d c b a } 1386 g b d b g2 1387} 1388@end lilypond 1389 1390 1391@node Application d'une fonction à tous les objets de mise en forme 1392@subsection Application d'une fonction à tous les objets de mise en forme 1393@translationof Running a function on all layout objects 1394 1395@cindex appel de code sur des objets de mise en forme 1396@cindex objets de mise en forme, appel de code 1397@funindex \applyOutput 1398 1399La manière la plus souple d'affiner un objet consiste à utiliser la 1400commande @code{\applyOutput}. Celle-ci va insérer un événement 1401(@rinternals{ApplyOutputEvent}) dans le contexte spécifié. Elle répond 1402aussi bien à la syntaxe 1403@example 1404\applyOutput @var{Contexte} @var{procédure} 1405@end example 1406@noindent 1407que 1408@example 1409\applyOutput @var{Contexte}.@var{Grob} @var{procédure} 1410@end example 1411 1412@noindent 1413où @code{@var{procédure}} est une fonction Scheme à trois arguments. 1414 1415Lors de l'interprétation de cette commande, la fonction 1416@code{@var{procédure}} est appelée pout tout objet de rendu (nommé 1417@var{Grob} si celui-ci est spécifié) appartenant au contexte 1418@code{@var{Contexte}} à cet instant précis, avec les arguments 1419suivants : 1420@itemize 1421@item l'objet de rendu en lui-même, 1422@item le contexte au sein duquel cet objet est créé, 1423@item le contexte dans lequel @code{\applyOutput} est effectué. 1424@end itemize 1425 1426De plus, ce qui est à l'origine de l'objet de rendu -- l'expression 1427musicale ou l'objet qui l'a générée -- se retrouve en tant que propriété 1428d'objet @code{cause}. Il s'agit, pour une tête de note, d'un événement 1429@rinternals{NoteHead}, et d'un objet @rinternals{Stem} pour une hampe. 1430 1431Voici une fonction utilisable avec la commande 1432@code{\applyOutput} : elle « blanchit » la tête des notes se trouvant 1433sur la ligne médiane ou bien directement à son contact. 1434 1435@lilypond[quote,verbatim,ragged-right] 1436#(define (blanker grob grob-origin context) 1437 (if (< (abs (ly:grob-property grob 'staff-position)) 2) 1438 (set! (ly:grob-property grob 'transparent) #t))) 1439 1440\relative { 1441 a'4 e8 <<\applyOutput Voice.NoteHead #blanker a c d>> b2 1442} 1443@end lilypond 1444 1445La @var{procédure} sera interprétée au niveau @code{Score} (partition) 1446ou @code{Staff} (portée) dès lors que vous utiliserez l'une des syntaxes 1447 1448@example 1449\applyOutput Score@dots{} 1450\applyOutput Staff@dots{} 1451@end example 1452 1453 1454@node Fonctions de rappel 1455@section Fonctions de rappel 1456@translationof Callback functions 1457 1458Certaines propriétés, entre autres @code{thickness} ou @code{direction}, 1459peuvent voir leur valeur figée à l'aide d'un @code{\override} comme 1460ici : 1461 1462@example 1463\override Stem.thickness = #2.0 1464@end example 1465 1466Une procédure Scheme peut aussi se charger de modifier des propriétés : 1467 1468@lilypond[fragment,verbatim,quote] 1469\override Stem.thickness = #(lambda (grob) 1470 (if (= UP (ly:grob-property grob 'direction)) 1471 2.0 1472 7.0)) 1473\relative { c'' b a g b a g b } 1474@end lilypond 1475 1476@noindent 1477Dans ce cas, la procédure est exécutée dès que la valeur de la propriété 1478est nécessaire au processus de mise en forme. 1479 1480La majeure partie du procédé typographique consiste en la réalisation de 1481tels rappels (@emph{callbacks} en anglais). Entre autres propriétés 1482utilisant particulièrement des rappels, nous mentionnerons 1483 1484@table @code 1485@item stencil 1486 Routine d'impression, construisant le dessin du symbole 1487@item X-offset 1488 Routine effectuant le positionnement horizontal 1489@item X-extent 1490 Routine calculant la largeur d'un objet 1491@end table 1492 1493La procédure prend un unique argument, en l'occurrence l'objet graphique 1494(le @emph{grob}). 1495 1496Cette procédure, grâce à un appel à la fonction de rappel dévolue à 1497cette propriété -- mentionnée dans la référence des propriétés internes 1498et dans le fichier @file{define-grobs.scm} --, pourra accéder à la 1499valeur usuelle de la propriété : 1500 1501@example 1502\relative @{ 1503 \override Flag.X-offset = #(lambda (flag) 1504 (let ((default (ly:flag::calc-x-offset flag))) 1505 (* default 4.0))) 1506 c''4. d8 a4. g8 1507@} 1508@end example 1509 1510La valeur par défaut est aussi accessible à l'aide de la fonction 1511@code{grob-transformer} : 1512 1513@lilypond[verbatim,quote] 1514\relative { 1515 \override Flag.X-offset = #(grob-transformer 'X-offset 1516 (lambda (flag default) (* default 4.0))) 1517 c''4. d8 a4. g8 1518} 1519@end lilypond 1520 1521Au sein d'un @emph{callback}, le meilleur moyen d'évaluer un 1522@emph{markup} consiste à utiliser la fonction 1523@code{grob-interpret-markup}, comme ici : 1524 1525@example 1526my-callback = #(lambda (grob) 1527 (grob-interpret-markup grob (markup "foo"))) 1528@end example 1529 1530 1531@ignore 1532@n ode Code Scheme intégré 1533@s ection Code Scheme intégré 1534@t ranslationof Inline Scheme code 1535 1536À REVOIR : depuis la rédaction de cette section, LilyPond en est 1537arrivé à un point tel que trouver un exemple @emph{simple} où l'on se 1538retrouve obligé d'en venir à utiliser du code Scheme devient chose 1539ardue. 1540 1541En attendant un remaniement de cette section, faisons comme si nous 1542l'ignorions. 1543 1544L'inconvénient principal de la commande @code{\tweak} est la rigidité de 1545sa syntaxe. Par exemple, le code suivant produit une erreur de syntaxe 1546(du moins, c'était le cas auparavant). 1547 1548@example 1549F = \tweak font-size #-3 -\flageolet 1550 1551\relative @{ 1552 c''4^\F c4_\F 1553@} 1554@end example 1555 1556@noindent 1557C'est en se servant du langage Scheme que l'on peut résoudre ce 1558problème. Dans cet exemple, on a recours aux méthodes décrites dans 1559@ref{Ajout d'articulation à des notes (exemple)}, en 1560particulier quant à l'emploi de @code{\displayMusic}. 1561 1562@example 1563F = #(let ((m (make-music 'ArticulationEvent 1564 'articulation-type "flageolet"))) 1565 (set! (ly:music-property m 'tweaks) 1566 (acons 'font-size -3 1567 (ly:music-property m 'tweaks))) 1568 m) 1569 1570\relative @{ 1571 c''4^\F c4_\F 1572@} 1573@end example 1574 1575@noindent 1576Ici les propriétés @code{tweak} de l'objet flageolet nommé @samp{m} 1577(créé au moyen de @code{make-music}) sont extraites par 1578@code{ly:music-property}, une nouvelle valeur de la taille de fonte 1579est ajoutée à la liste de ses propriétés (grâce à la fonction Scheme 1580@code{acons}), et le résultat de cette opération est renvoyé par 1581@code{set!}. Le dernier élément, dans ce bloc @code{let}, est la valeur 1582finale de @samp{m} lui-même. 1583 1584@end ignore 1585 1586 1587@node Retouches complexes 1588@section Retouches complexes 1589@translationof Difficult tweaks 1590 1591Certains réglages sont plus délicats que d'autres. 1592 1593@itemize 1594@item 1595L'un d'entre eux est l'apparence des objets dits « extenseurs » 1596(@emph{spanner}), qui s'étendent horizontalement, tels que les liaisons. 1597Si, en principe, un seul de ces objets est créé à la fois et peut donc 1598être modifié de façon habituelle, lorsque ces objets doivent enjamber un 1599changement de ligne, ils sont dupliqués au début du ou des systèmes 1600suivants. Comme ces objets sont des clones de l'objet d'origine, ils en 1601héritent toutes les propriétés, y compris les éventuelles commandes 1602@code{\override}. 1603 1604En d'autres termes, une commande @code{\override} affecte toujours les 1605deux extrémités d'un objet @emph{spanner}. Pour ne modifier que la 1606partie précédant ou suivant le changement de ligne, il faut intervenir 1607directement dans le processus de mise en page. 1608La fonction de rappel @code{after-line-breaking} contient toute 1609l'opération Scheme effectuée lorsque les sauts de lignes ont été 1610déterminés, et que des objets graphiques ont été divisés sur des 1611systèmes différents. 1612 1613Dans l'exemple suivant, on définit une nouvelle opération nommée 1614@code{my-callback}. Cette opération 1615 1616@itemize 1617@item 1618détermine si l'objet a été divisé à l'occasion d'un changement de ligne 1619@item 1620dans l'affirmative, recherche les différents tronçons de l'objet 1621@item 1622vérifie si l'objet considéré est bien la deuxième moitié d'un objet 1623divisé 1624@item 1625dans l'affirmative, applique un espacement supplémentaire 1626(@code{extra-offset}). 1627@end itemize 1628 1629On ajoute cette procédure à l'objet @rinternals{Tie} (liaison de tenue), 1630de façon à ce que le deuxième tronçon d'une liaison divisée soit 1631rehaussé. 1632 1633@c KEEP LY 1634@lilypond[quote,verbatim,ragged-right] 1635#(define (my-callback grob) 1636 (let* ( 1637 ;; l'objet a-t-il été divisé ? 1638 (orig (ly:grob-original grob)) 1639 1640 ;; si oui, rechercher les tronçons frères (siblings) 1641 (siblings (if (ly:grob? orig) 1642 (ly:spanner-broken-into orig) 1643 '()))) 1644 1645 (if (and (>= (length siblings) 2) 1646 (eq? (car (last-pair siblings)) grob)) 1647 (ly:grob-set-property! grob 'extra-offset '(-2 . 5))))) 1648 1649\relative { 1650 \override Tie.after-line-breaking = 1651 #my-callback 1652 c''1 ~ \break 1653 c2 ~ 2 1654} 1655@end lilypond 1656 1657@noindent 1658Lorsque cette astuce va être appliquée, notre nouvelle fonction de 1659rappel @code{after-line-breaking} devra également appeler celle 1660d'origine (@code{after-line-breaking}), si elle existe. Ainsi, pour 1661l'utiliser dans le cas d'un crescendo (objet @code{Hairpin}), il faudra 1662également appeler @code{ly:spanner::kill-zero-spanned-time}. 1663 1664 1665@item 1666Pour des raisons d'ordre technique, certains objets ne peuvent être 1667modifiés par @code{\override}. Parmi ceux-là, les objets 1668@code{NonMusicalPaperColumn} et @code{PaperColumn}. La commande 1669@code{\overrideProperty} sert à les modifier, de façon similaire à 1670@code{\once \override}, mais avec une syntaxe différente : 1671 1672@example 1673\overrideProperty 1674Score.NonMusicalPaperColumn % Nom de l'objet 1675 . line-break-system-details % Nom de la propriété 1676 . next-padding % Nom de la sous-propriété (optionnel) 1677 . #20 % Valeur 1678@end example 1679 1680Notez toutefois que la commande @code{\override} peut tout de même être 1681appliquée à @code{NonMusicalPaperColumn} et @code{PaperColumn} dans un 1682bloc @code{\context}. 1683 1684@end itemize 1685 1686 1687@node Interfaces LilyPond Scheme 1688@chapter Interfaces LilyPond Scheme 1689@translationof LilyPond Scheme interfaces 1690 1691Ce chapitre aborde les différents outils fournis par LilyPond à 1692l'intention des programmeurs en Scheme désireux d'obtenir des 1693informations à partir et autour des fluxs de musique. 1694 1695TODO -- figure out what goes in here and how to organize it 1696