Guide, node Updating translation committishes..
@end ignore
-@c \version "2.19.2"
+@c \version "2.19.22"
@node Interfaces for programmers
@chapter Interfaces for programmers
Here is a trivial example:
@lilypond[verbatim,quote]
-ritpp = #(define-event-function (parser location) ()
+ritpp = #(define-event-function () ()
#{ ^"rit." \pp #}
)
LilyPond code blocks and can deal with embedded Scheme expressions
starting with @code{$} and@w{ }@code{#}.
-@cindex parser (function argument)
-@cindex location
-
The reader extracts the LilyPond code block and generates a runtime
-call to the LilyPond @code{parser} to interpret the LilyPond code.
+call to the LilyPond parser to interpret the LilyPond code.
Scheme expressions embedded in the LilyPond code are evaluated in the
lexical environment of the LilyPond code block, so all local variables
and function parameters available at the point the LilyPond code block
with@tie{}@code{#}, but they are accessible as LilyPond variables, i.e.
prefixed with@tie{}@code{\}.
-If @code{location} (see @ref{Scheme functions}) refers to a valid
-input location (which it usually does inside of music/@/Scheme
-functions), all music generated inside the code block has its
-@samp{origin} set to @code{location}.
+All music generated inside the code block has its
+@samp{origin} set to the current input location.
A LilyPond code block may contain anything that you can use on the
right side of an assignment. In addition, an empty LilyPond block
@example
function =
#(define-scheme-function
- (parser location @var{arg1} @var{arg2} @dots{})
+ (@var{arg1} @var{arg2} @dots{})
(@var{type1?} @var{type2?} @dots{})
@var{body})
@end example
where
@multitable @columnfractions .33 .66
-@item @code{parser}
-@tab needs to be literally @code{parser} in order to give LilyPond code
-blocks (@code{#@{}@dots{}@code{#@}}) access to the parser.
-
-@item @code{location}
-@tab needs to be literally @code{location} in order to provide access
-to the input location object, which is used to provide error messages
-with file names and line numbers.
-
@item @code{@var{argN}}
@tab @var{n}th argument
Default values are not verified with @emph{predicate?} at either
definition or run time: it is your responsibility to deal with the
values you specify. Default values that happen to be music expressions
-are copied while setting @code{origin} to the @code{location} parameter.
+are copied while setting @code{origin} to the current input location.
@item @code{@var{body}}
@tab A sequence of Scheme forms evaluated in order, the last one being
@example
noPointAndClick =
#(define-void-function
- (parser location)
+ ()
()
(ly:set-option 'point-and-click #f))
@dots{}
@example
function =
#(define-music-function
- (parser location @var{arg1} @var{arg2} @dots{})
+ (@var{arg1} @var{arg2} @dots{})
(@var{type1?} @var{type2?} @dots{})
@var{body})
@end example
@example
manualBeam =
#(define-music-function
- (parser location beg-end)
+ (beg-end)
(pair?)
#@{
\once \override Beam.positions = #beg-end
@lilypond[quote,verbatim,ragged-right]
manualBeam =
#(define-music-function
- (parser location beg end)
+ (beg end)
(number? number?)
#{
\once \override Beam.positions = #(cons beg end)
@example
crossStaff =
-#(define-music-function (parser location notes) (ly:music?)
+#(define-music-function (notes) (ly:music?)
(_i "Create cross-staff stems")
#@{
\temporary \override Stem.cross-staff = #cross-staff-connect
@lilypond[quote,verbatim,ragged-right]
AltOn =
#(define-music-function
- (parser location mag)
+ (mag)
(number?)
#{
\override Stem.length = #(* 7.0 mag)
\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
@lilypond[quote,verbatim,ragged-right]
withAlt =
#(define-music-function
- (parser location mag music)
+ (mag music)
(number? ly:music?)
#{
\override Stem.length = #(* 7.0 mag)
\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
@example
displayBarNum =
#(define-music-function
- (parser location)
+ ()
()
(if (eq? #t (ly:get-option 'display-bar-numbers))
#@{ \once \override Score.BarNumber.break-visibility = ##f #@}
indicator, like @code{c'\pp}. Here is a way to write arbitrary
dynamics:
@lilypond[quote,verbatim,ragged-right]
-dyn=#(define-event-function (parser location arg) (markup?)
+dyn=#(define-event-function (arg) (markup?)
(make-dynamic-script arg))
-\relative c' { c\dyn pfsss }
+\relative { c'\dyn pfsss }
@end lilypond
You could do the same using a music function, but then you always would
have to write a direction indicator before calling it, like
@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 {
+ \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
+
+
+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
+ (music) (ly:music?)
+ #{
+ \applyContext
+ #(lambda (context)
+ (define (desaturate-grob grob)
+ (let* ((grob-def (ly:context-grob-definition context grob))
+ (color (ly:assoc-get 'color grob-def black))
+ (new-color (map (lambda (x) (min 1 (/ (1+ x) 2))) color)))
+ (ly:context-pushpop-property context grob 'color new-color)))
+ (for-each desaturate-grob '(NoteHead Stem Beam)))
+ #music
+ \applyContext
+ #(lambda (context)
+ (define (revert-color grob)
+ (ly:context-pushpop-property context grob 'color))
+ (for-each revert-color '(NoteHead Stem Beam)))
+ #})
+
+\relative {
+ \override NoteHead.color = #darkblue
+ \override Stem.color = #darkblue
+ \override Beam.color = #darkblue
+ g'8 a b c
+ \desaturate { d c b a }
+ g b d b g2
+}
+@end lilypond
+
@node Running a function on all layout objects
@subsection Running a function on all layout objects
(< (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
can by found in the Internals Reference or the file 'define-grobs.scm':
@example
-\relative c'' @{
- \override Flag #'X-offset = #(lambda (flag)
+\relative @{
+ \override Flag.X-offset = #(lambda (flag)
(let ((default (ly:flag::calc-x-offset flag)))
(* default 4.0)))
- c4. d8 a4. g8
+ c''4. 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},
-
-@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
-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
-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}.
-
-In fact, using a single procedure as property value is equivalent to
-
-@example
-(ly:make-simple-closure (ly:make-simple-closure (list @var{proc})))
-@end example
-
-@noindent
-The inner @code{ly:make-simple-closure} supplies the grob as argument
-to @var{proc}, the outer ensures that result of the function is
-returned, rather than the @code{simple-closure} object.
-
From within a callback, the easiest method for evaluating a markup is
to use grob-interpret-markup. For example:
@example
F = \tweak font-size #-3 -\flageolet
-\relative c'' @{
- c4^\F c4_\F
+\relative @{
+ c''4^\F c4_\F
@}
@end example
(ly:music-property m 'tweaks)))
m)
-\relative c'' @{
- c4^\F c4_\F
+\relative @{
+ c''4^\F c4_\F
@}
@end example
(eq? (car (last-pair siblings)) grob))
(ly:grob-set-property! grob 'extra-offset '(-2 . 5)))))
-\relative c'' {
+\relative {
\override Tie.after-line-breaking =
#my-callback
- c1 ~ \break
+ c''1 ~ \break
c2 ~ 2
}
@end lilypond
Scheme programmers get information into and out of the music streams.
TODO -- figure out what goes in here and how to organize it
-