@c -*- coding: utf-8; mode: texinfo; documentlanguage: fr -*-
@ignore
- Translation of GIT committish: 0cde75024b6f1210b059c48b624e1026836c96aa
+ Translation of GIT committish: 5a6340b7f319802a7313c0e6b82eef96909cde42
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.17.6"
+@c \version "2.19.21"
@c Translators: Valentin Villenave, Jean-Charles Malahieude
@c Translation checkers: Gilles Thibault
* Fonctions pour markups::
* Contextes pour programmeurs::
* Fonctions de rappel::
-* Code Scheme intégré::
* Retouches complexes::
@end menu
@node Blocs de code LilyPond
@section Blocs de code LilyPond
-@translationof Lilypond code blocks
+@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
-Ils 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{#}.
+
+En voici un exemple basique :
+
+@lilypond[verbatim,quote]
+ritpp = #(define-event-function (parser location) ()
+ #{ ^"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
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. Lorsque l'@code{emplacement} 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
-@code{emplacement}.
+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
@example
fonction =
#(define-scheme-function
- (parser location @var{arg1} @var{arg2} @dots{})
- (@var{type1?} @var{type2?} @dots{})
+ (parser location @var{arg1} @var{arg2}@dots{})
+ (@var{type1?} @var{type2?}@dots{})
@var{corps})
@end example
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}. Certains de ces prédicats, comme nous le
-verrons plus loin, bénéficient d'un traitement particulier de la part du
-@emph{parser}. De même existe une forme spécifique --
-@code{(@emph{prédicat?} @emph{default})} -- qui permet de fournir des
+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
-de la fonction, c'est la valeur par défaut qui lui sera substituée. Les
+à 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
+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
@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
+@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 @qq{immédiate} à l'aide d'un @code{$}, comme
+expression Scheme « immédiate » à l'aide d'un @code{$}, comme
@samp{$music}.
Lorsque votre fonction retourne une expression musicale, lui est
@end multitable
@noindent
-Certains types de prédicat font l'objet d'un traitement spécial de la
-part de l'analyseur grammatical, dans la mesure où il n'a aucun autre
-moyen de reconnaître efficacement les arguments. Il s'agit, à l'heure
-actuelle, de @code{ly:pitch?} et @code{ly:duration?}.
-
-Pour tous les autres prédicats, la recevabilité des arguments est
-déterminée par un appel effectif au prédicat après que LilyPond les a
-déjà converti 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 formes d'expression, comme la plupart du temps où la
-musique n'est pas bornée par des accolades, où LilyPond doit lire
-au-delà de cette même expression afin d'en déterminer la fin. Si une
-telle expression devait, après évaluation du prédicat, faire l'objet
-d'un argument optionnel, LilyPond n'aurait aucun moyen, à partir du
-moment où il aura décidé que l'expression ne correspond pas au
-paramètre, de @qq{revenir en arrière}. C'est la raison pour laquelle
-certaines formes musicales devraient être bornées par des accolades pour
-que LilyPond puisse les reconnaître efficacement. Il existe d'autres
-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@tie{}? 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
-après consultation du prédicat. Pour toutes ces raisons, nous vous
-enjoignons à éviter d'utiliser des prédicats permissifs tel que
-@code{scheme?}, dès que vous voulez les utiliser dans un but particulier
-plutôt que dans une fonction de portée générale.
-
-Les différents types des prédicat propres à LilyPond sont recensés à
+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
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
+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 @qq{sauvegarde} en tant que prochain argument
+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
(parser location)
()
(ly:set-option 'point-and-click #f))
-...
+@dots{}
\noPointAndClick % desactive le "pointer-cliquer"
@end example
@example
fonction =
#(define-music-function
- (parser location @var{arg1} @var{arg2} @dots{})
- (@var{type1?} @var{type2?} @dots{})
+ (parser location @var{arg1} @var{arg2}@dots{})
+ (@var{type1?} @var{type2?}@dots{})
@var{corps})
@end example
@subsection Utilisation de fonctions musicales
@translationof Music function usage
-Une fonction musicale peut prendre place en différents endroits.
-Certaines restrictions s'appliqueront selon l'endroit où elle est
-utilisée, de telle sorte que l'analyse syntaxique soit sans ambiguïté.
-Le résultat renvoyé par une fonction musicale doit être compatible avec
-le contexte dans lequel elle est appelée.
+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@tie{}: aucune restriction.
+Dans une expression musicale de haut niveau, aucun postévénement n'est
+toléré.
@item
-En tant que post-événement, explicitement introduit par un indicateur de
-positionnement -- à savoir @code{-}, @code{^}, ou@tie{}@code{_}. Notez
-bien que le renvoi d'un post-événement est valide lorsque la fonction
-musicale est appelée comme de la musique normale ; ceci amène à un
-résultat ressemblant à
-@example
-s 1*0-\fonction
-@end example
-
-Dans ce cas particulier, vous ne pouvez utiliser une expression musicale
-@emph{ouverte} en tant que dernier argument -- argument qui se
-composerait d'une expression musicale susceptible d'accepter des
-post-événements additionnels.
+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
+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
-Les règles spécifiques en matière d'arguments de fin rendent possible
-l'écriture de fonctions polymorphes telles que @code{\tweak}, qui
-peuvent s'appliquer à différentes constructions.
+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
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 @qq{construction de
-cellule}.
+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?} :
}
@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 (parser location 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
\revert NoteHead.font-size
}
-\relative c' {
- c2 \AltOn #0.5 c4 c
+\relative {
+ c'2 \AltOn #0.5 c4 c
\AltOn #1.5 c c \AltOff c2
}
@end lilypond
\revert NoteHead.font-size
#})
-\relative c' {
- c2 \withAlt #0.5 { c4 c }
+\relative {
+ c'2 \withAlt #0.5 { c4 c }
\withAlt #1.5 { c c } c2
}
@end lilypond
@lilypond[quote,verbatim,ragged-right]
dyn=#(define-event-function (parser location arg) (markup?)
(make-dynamic-script arg))
-\relative c' { c\dyn pfsss }
+\relative { c'\dyn pfsss }
@end lilypond
Vous pourriez obtenir le même résultat avec une fonction musicale, à
@cindex définition d'une commande markup
-La macro @code{markup} construit en Scheme des expressions @emph{markup}
-tout en disposant d'une syntaxe proche de celle de LilyPond. Par exemple,
+@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
-(markup #:column (#:line (#:bold #:italic "hello" #:raise 0.4 "world")
- #:larger #:line ("foo" "bar" "baz")))
+\displayScheme
+\markup @{
+ \column @{
+ \line @{ \bold \italic "hello" \raise #0.4 "world" @}
+ \larger \line @{ foo bar baz @}
+ @}
+@}
@end example
@noindent
-est équivalent à
+Compiler ce code renverra en console les lignes suivantes :
+
@example
-#@{ \markup \column @{ \line @{ \bold \italic "hello" \raise #0.4 "world" @}
- \larger \line @{ foo bar baz @} @} #@}
+(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}.
+
@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
+@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 ... @}} @tab
- @code{(markup markup1 markup2 ... )}
+@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 @{ ... @}} @tab @code{#:center-column ( ... )}
+@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
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}.
+@ref{Définition d'une nouvelle commande de markup}.
@knownissues
L'argument @var{markup-list} des commandes @code{#:line},
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} ...)
- (@var{arg1-type?} @var{arg2-type?} ...)
+(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})
- ...) ]
- ..corps de la commande..)
+ @dots{}) ]
+ @dots{}corps de la commande@dots{})
@end lisp
Quelques commentaires sur les arguments :
@item @var{nom-commande}
le nom que vous attribuez à votre commande de @emph{markup}.
@item layout
-la définition du @qq{layout} -- son formatage.
+la définition du « layout » -- son formatage.
@item props
une liste de listes associatives, comprenant toutes les propriétés actives.
@item @var{argi}
Les arguments se distinguent selon leur type :
@itemize
@item un @emph{markup}, correspondant au type de prédicat
-@code{markup?}@tie{};
+@code{markup?} ;
@item une liste de @emph{markups}, correspondant au type de prédicat
-@code{markup-list?}@tie{};
+@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
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
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.
+@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
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.
+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}.
@end example
Il serait intéressant de rendre cette commande @code{double-box} plus
-souple@tie{}: les valeurs de @code{box-padding} sont figées et ne
+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é
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}@tie{}; on leur a d'ailleurs fourni des valeurs
+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
(number-pair?)
#:category graphic
#:properties ((thickness 1))
- "..documentation.."
+ "@dots{}documentation@dots{}"
(let ((th (* (ly:output-def-lookup layout 'line-thickness)
thickness))
(x (car dest))
(define-markup-command (draw-double-line layout props dest)
(number-pair?)
#:properties ((thickness 1))
- "..documentation.."
+ "@dots{}documentation@dots{}"
(let ((th (* (ly:output-def-lookup layout 'line-thickness)
thickness))
(x (car dest))
(number-pair?)
#:properties ((thickness 1)
(line-gap 0.6))
- "..documentation.."
- ...
+ "@dots{}documentation@dots{}"
+ @dots{}
@end lisp
Nous ajoutons enfin le code qui dessinera nos deux lignes. Deux appels
@subsection Définition d'une nouvelle commande de liste de @emph{markups}
@translationof New markup list command definition
+@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.
+@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
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é @code{args}. Le prédicat des listes
+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é
interprétée par la fonction @code{interpret-markup-list}.
Voici comment utiliser cette nouvelle commande de liste de
-@emph{markups}@tie{}:
+@emph{markups} :
+
@example
\markuplist @{
\paragraph @{
@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 en pareil cas est
+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. Les lignes de code qui suivent auront
-pour effet d'afficher à l'écran, en cours de compilation, le numéro de
-mesure en cours.
+@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} :
-@example
+@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 (x)
- (format #t "\nNous en sommes à la mesure ~a.\n"
- (ly:context-property x 'currentBarNumber)))
-@end example
+ #(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
+ (parser location 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 g' {
+ \override NoteHead.color = #darkblue
+ \override Stem.color = #darkblue
+ \override Beam.color = #darkblue
+ g8 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
@translationof Running a function on all layout objects
@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
@itemize
@item l'objet de rendu en lui-même,
@item le contexte au sein duquel cet objet est créé,
-@item et le contexte dans lequel @code{\applyOutput} est effectué.
+@item le contexte dans lequel @code{\applyOutput} est effectué.
@end itemize
De plus, ce qui est à l'origine de l'objet de rendu -- l'expression
@rinternals{NoteHead}, et d'un objet @rinternals{Stem} pour une hampe.
Voici une fonction utilisable avec la commande
-@code{\applyOutput} : elle @qq{blanchit} la tête des notes se
-trouvant sur la ligne médiane ou bien directement à son contact.
+@code{\applyOutput} : elle « blanchit » la tête des notes se trouvant
+sur la ligne médiane ou bien directement à son contact.
@lilypond[quote,verbatim,ragged-right]
#(define (blanker grob grob-origin context)
(< (abs (ly:grob-property grob 'staff-position)) 2))
(set! (ly:grob-property grob 'transparent) #t)))
-\relative c' {
+\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} dès lors que vous utiliserez l'une des
-syntaxes
+(partition) ou @code{Staff} (portée) dès lors que vous utiliserez l'une
+des syntaxes
@example
\applyOutput #'Score #@var{procédure}
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@tie{}:
+ici :
@example
\override Stem.thickness = #2.0
@end example
-Une procédure Scheme peut aussi se charger de modifier des
-propriétés@tie{}:
+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)
La procédure prend un unique argument, en l'occurrence l'objet graphique
(le @emph{grob}).
-Dans le cas où la routine doit faire appel à plusieurs arguments, le
-@emph{grob} en cours peut s'insérer à l'aide d'un @emph{grob} enchâssé.
-Voici, à titre d'illustration, un réglage pour
-@code{AccidentalSuggestion} :
-
-@example
-`(X-offset .
- ,(ly:make-simple-closure
- `(,+
- ,(ly:make-simple-closure
- (list ly:self-alignment-interface::centered-on-x-parent))
- ,(ly:make-simple-closure
- (list ly:self-alignment-interface::x-aligned-on-self)))))
-@end example
-
-@noindent
-Ici, aussi bien @code{ly:self-alignment-interface::x-aligned-on-self}
-que @code{ly:self-alignment-interface::centered-on-x-parent} font appel
-à l'argument @emph{grob}. La fonction @code{+} a pour effet
-d'additionner les résultats. L'ensemble est inclus dans un
-@code{ly:make-simple-closure} de telle sorte que l'addition s'exécute de
-façon correcte
-
-Dans les faits, l'utilisation d'une unique procédure en tant que valeur
-d'une propriété revient à écrire
+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
-(ly:make-simple-closure (ly:make-simple-closure (list @var{proc})))
+\relative c'' @{
+ \override Flag.X-offset = #(lambda (flag)
+ (let ((default (ly:flag::calc-x-offset flag)))
+ (* default 4.0)))
+ c4. d8 a4. g8
+@}
@end example
-@noindent
-Le @code{ly:make-simple-closure} intérieur fournit le @emph{grob} en
-argument à la procédure @var{proc}, l'extérieur s'assure que le résultat
-de la fonction sera bien renvoyé, non pas l'objet @code{simple-closure}.
-
Au sein d'un @emph{callback}, le meilleur moyen d'évaluer un
@emph{markup} consiste à utiliser la fonction
@code{grob-interpret-markup}, comme ici :
@end example
-@node Code Scheme intégré
-@section Code Scheme intégré
-@translationof Inline Scheme code
+@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.
-À REVOIR : l'exemple de cette rubrique n'est pas des plus judicieux puisque
-@example
-F = -\tweak font-size #-3 -\flageolet
-@end example
-(notez le @samp{-} qui qualifie d'événement postérieur) fonctionne
-correctement dans ce cas d'espèce. En attendant un remaniement de cette
- section, faisons comme si nous l'ignorions.
+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
-\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 : 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{Ajout d'articulation à des notes (exemple)}, en
(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
@itemize
@item
-L'un d'entre eux est l'apparence des objets dits @qq{extenseurs}
+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
@item
détermine si l'objet a été divisé à l'occasion d'un changement de ligne
@item
-dans l'affirmative, 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é
@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
;; l'objet a-t-il été divisé ?
(orig (ly:grob-original grob))
- ;; si oui, rechercher les morceaux frères (siblings)
+ ;; si oui, rechercher les tronçons frères (siblings)
(siblings (if (ly:grob? orig)
(ly:spanner-broken-into orig)
'())))
\override Tie.after-line-breaking =
#my-callback
c1 ~ \break
- c2 ~ c
+ c2 ~ 2
}
@end lilypond
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 :
+@code{\once \override}, mais avec une syntaxe différente :
@example
\overrideProperty