Guide, node Updating translation committishes..
@end ignore
-@c \version "2.17.6"
+@c \version "2.19.2"
@node Interfaces for programmers
@chapter Interfaces for programmers
* Markup functions::
* Contexts for programmers::
* Callback functions::
-* Inline Scheme code::
* Difficult tweaks::
@end menu
@item @code{@var{typeN?}}
@tab a Scheme @emph{type predicate} for which @code{@var{argN}}
-must return @code{#t}. Some of these predicates are specially
-recognized by the parser, see below. There is also a special form
+must return @code{#t}. There is also a special form
@code{(@emph{predicate?} @emph{default})} for specifying optional
arguments. If the actual argument is missing when the function is being
called, the default value is substituted instead. Default values are
@end multitable
@noindent
-Some type predicates are specially handled by the parser since it
-can't recognize the arguments reliably otherwise. Currently these are
-@code{ly:pitch?} and @code{ly:duration?}.
-
-Suitability of arguments for all other predicates is determined by
+Suitability of arguments for the predicates is determined by
actually calling the predicate after LilyPond has already converted them
into a Scheme expression. As a consequence, the argument can be
specified in Scheme syntax if desired (introduced with @code{#} or as
lists, score, book, bookpart, context definition and output definition
blocks.
-For some kinds of expression (like most music not enclosed in braces)
-LilyPond needs to look further than the expression itself in order to
-determine its end. If such an expression were considered for an
-optional argument by evaluating its predicate, LilyPond would not be
-able to ``backup'' when it decides the expression does not fit the
-parameter. So some forms of music might need to be enclosed in braces
-to make them acceptable to LilyPond. There are also some other
-ambiguities that LilyPond sorts out by checking with predicate
+Some
+ambiguities LilyPond sorts out by checking with predicate
functions: is @samp{-3} a fingering postevent or a negative number? Is
@code{"a" 4} in lyric mode a string followed by a number, or a lyric
-event of duration @code{4}? LilyPond decides by asking the predicates.
-That means that you should avoid permissive predicates like
-@code{scheme?} if you have a particular use in mind instead of a general
-purpose function.
+event of duration @code{4}? LilyPond tries the argument
+predicate on successive interpretations until success, with an
+order designed to minimize inconsistent interpretations and
+lookahead.
+
+For example, a predicate accepting both music expressions and
+pitches will consider @code{c''} to be a pitch rather than a music
+expression. Immediately following durations or postevents will
+change that interpretation. It's best to avoid overly
+permissive predicates like @code{scheme?} when the application
+rather calls for more specific argument types.
For a list of available predefined type predicates, see
@ruser{Predefined type predicates}.
@node Music function usage
@subsection Music function usage
-Music functions may currently be used in several places. Depending on
-where they are used, restrictions apply in order to be able to parse
-them unambiguously. The result a music function returns must be
-compatible with the context in which it is called.
+A @q{music function} has to return an expression matching the predicate
+@code{ly:music?}. This makes music function calls suitable as arguments
+of type @code{ly:music?} for another music function call.
+
+When using a music function call in other contexts, the context may
+cause further semantic restrictions.
@itemize
@item
-At top level in a music expression. No restriction apply here.
+At the top level in a music expression a post-event is not accepted.
@item
-As a post-event, explicitly started with a direction indicator (one of
-@code{-}, @code{^}, @w{and @code{_}}). Note that returning a post-event
-will be acceptable for music functions called as normal music, leading
-to a result roughly equivalent to
-@example
-s 1*0-\fun
-@end example
-
-In this case, you can't use an @emph{open} music expression as the last
-argument, one that would end with a music expression able to accept
-additional postevents.
+When a music function (as opposed to an event function) returns an
+expression of type post-event, LilyPond requires one of the named
+direction indicators (@code{-}, @code{^}, @w{and @code{_}})) in order to
+properly integrate the post-event produced by the music function call
+into the surrounding expression.
@item
-As a chord constituent. The returned expression must be of
+As a chord constituent. The returned expression must be of a
@code{rhythmic-event} type, most likely a @code{NoteEvent}.
@end itemize
@noindent
-The special rules for trailing arguments make it possible to write
-polymorphic functions like @code{\tweak} that can be applied to
-different constructs.
+@q{Polymorphic} functions, like @code{\tweak}, can be applied to
+post-events, chord constituent and top level music expressions.
@node Simple substitution functions
@subsection Simple substitution functions
@cindex calling code during interpreting
@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
+
+Contexts can be modified during interpretation with Scheme code.
+In a LilyPond code block, the syntax for this is:
-Contexts can be modified during interpretation with Scheme code. The
-syntax for this is
@example
\applyContext @var{function}
@end example
+In Scheme code, the syntax is:
+
+@example
+(make-apply-context @var{function})
+@end example
+
@code{@var{function}} should be a Scheme function that takes a
single argument: the context in which the @code{\applyContext}
-command is being called. The following code will print the
-current bar number on the standard output during the compile:
+command is being called. The function can access as well as
+override/set grob properties and context properties. Any actions
+taken by the function that depend on the state of the context are
+limited to the state of the context @emph{when the function is
+called}. Also, changes effected by a call to @code{\applyContext}
+remain in effect until they are directly modified again, or
+reverted, even if the initial conditions that they depended on
+have changed.
+
+The following scheme functions are useful when using
+@code{\applyContext}:
-@example
+@table @code
+@item ly:context-property
+look up a context property value
+
+@item ly:context-set-property!
+set a context property
+
+@item ly:context-grob-definition
+@itemx ly:assoc-get
+look up a grob property value
+
+@item ly:context-pushpop-property
+do a @code{\temporary@tie{}\override}
+or a @code{\revert} on a grob property
+@end table
+
+
+The following example looks up the current @code{fontSize} value, and
+then doubles it:
+
+@lilypond[quote,verbatim]
+doubleFontSize =
\applyContext
- #(lambda (x)
- (format #t "\nWe were called in barnumber ~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
+The following example looks up the current colors of the
+@code{NoteHead}, @code{Stem}, and @code{Beam} grobs, and then changes
+each to a less saturated shade.
+
+@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 g' {
+ \time 3/4
+ g8[ 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
+
+
+This also could be implemented as a music function, in order to
+restrict the modifications to a single music block. Notice how
+@code{ly:context-pushpop-property} is used both as a
+@code{\temporary@tie{}\override} and as a @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 Running a function on all layout objects
@subsection Running a function on all layout objects
The procedure always takes a single argument, being the grob.
+That procedure may access the usual value of the property, by first
+calling the function that is the usual callback for that property, which
+can by found in the Internals Reference or the file 'define-grobs.scm':
+
+@example
+\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
+
If routines with multiple arguments must be called, the current grob
can be inserted with a grob closure. Here is a setting from
-@code{AccidentalSuggestion},
+@code{RehearsalMark},
@example
`(X-offset .
- ,(ly:make-simple-closure
- `(,+
+ ,(ly:make-simple-closure
+ `(,+
+ ,(ly:make-simple-closure
+ (list ly:break-alignable-interface::self-align-callback))
,(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)))))
+ (list ly:self-alignment-interface::x-aligned-on-self)))))
@end example
@noindent
-In this example, both @code{ly:self-alignment-interface::x-aligned-on-self} and
-@code{ly:self-alignment-interface::centered-on-x-parent} are called
+In this example, both @code{ly:break-alignable-interface::self-align-callback} and
+@code{ly:self-alignment-interface::x-aligned-on-self} are called
with the grob as argument. The results are added with the @code{+}
function. To ensure that this addition is properly executed, the whole
thing is enclosed in @code{ly:make-simple-closure}.
(grob-interpret-markup grob (markup "foo")))
@end example
-@node Inline Scheme code
-@section Inline Scheme code
+@ignore
+
+@n ode Inline Scheme code
+@s ection Inline Scheme code
TODO: after this section had been written, LilyPond has improved
to the point that finding a @emph{simple} example where one would
written back with @code{set!}. The last element of the
@code{let} block is the return value, @code{m} itself.
+@end ignore
@node Difficult tweaks
\override Tie.after-line-breaking =
#my-callback
c1 ~ \break
- c2 ~ c
+ c2 ~ 2
}
@end lilypond