Guide, node Updating translation committishes..
@end ignore
-@c \version "2.19.2"
+@c \version "2.19.24"
@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
+@tab @var{n}th argument.
@item @code{@var{typeN?}}
-@tab a Scheme @emph{type predicate} for which @code{@var{argN}}
+@tab A Scheme @emph{type predicate} for which @code{@var{argN}}
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
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
@subsection Scheme function usage
Scheme functions can be called pretty much anywhere where a Scheme
-expression starting with @code{#} can be written. You call a scheme
-function by writing its name preceded by @code{\}, followed by its
-arguments. Once an optional argument predicate does not match an
-argument, LilyPond skips this and all following optional arguments,
-replacing them with their specified default, and @q{backs up} the
-argument that did not match to the place of the next mandatory argument.
-Since the backed up argument needs to go somewhere, optional arguments
-are not actually considered optional unless followed by a mandatory
+expression starting with @code{#} can be written. You call a
+scheme function from LilyPond by writing its name preceded by
+@code{\}, followed by its arguments. Once an optional argument
+predicate does not match an argument, LilyPond skips this and all
+following optional arguments, replacing them with their specified
+default, and @q{backs up} the argument that did not match to the
+place of the next mandatory argument. Since the backed up
+argument needs to go somewhere, optional arguments are not
+actually considered optional unless followed by a mandatory
argument.
There is one exception: if you write @code{\default} in the place of an
cases where you always return a useful value, and use void scheme
functions (@pxref{Void scheme functions}) otherwise.
+For convenience, scheme functions may also be called directly from
+Scheme bypassing the LilyPond parser. Their name can be used like
+the name of an ordinary function. Typechecking of the arguments
+and skipping optional arguments will happen in the same manner as
+when called from within LilyPond, with the Scheme value
+@code{*unspecified*} taking the role of the @code{\default}
+reserved word for explicitly skipping optional arguments.
+
@node Void scheme functions
@subsection Void scheme functions
@funindex define-void-function
@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
@item
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
+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.
@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
(ly:context-pushpop-property context grob 'color new-color)))
(for-each desaturate-grob '(NoteHead Stem Beam)))
-\relative g' {
+\relative {
\time 3/4
- g8[ g] \desaturate g[ g] \desaturate g[ g]
+ g'8[ g] \desaturate g[ g] \desaturate g[ g]
\override NoteHead.color = #darkred
\override Stem.color = #darkred
\override Beam.color = #darkred
@lilypond[quote,verbatim]
desaturate =
#(define-music-function
- (parser location music) (ly:music?)
+ (music) (ly:music?)
#{
\applyContext
#(lambda (context)
(for-each revert-color '(NoteHead Stem Beam)))
#})
-\relative g' {
+\relative {
\override NoteHead.color = #darkblue
\override Stem.color = #darkblue
\override Beam.color = #darkblue
- g8 a b c
+ g'8 a b c
\desaturate { d c b a }
g b d b g2
}
The most versatile way of tuning an object is @code{\applyOutput} which
works by inserting an event into the specified context
-(@rinternals{ApplyOutputEvent}). Its syntax is
+(@rinternals{ApplyOutputEvent}). Its syntax is either
@example
\applyOutput @var{Context} @var{proc}
@end example
+or
+@example
+\applyOutput @var{Context}.@var{Grob} @var{proc}
+@end example
@noindent
where @code{@var{proc}} is a Scheme function, taking three arguments.
When interpreted, the function @code{@var{proc}} is called for
-every layout object found in the context @code{@var{Context}} at
-the current time step, with the following arguments:
+every layout object (with grob name @var{Grob} if specified) found
+in the context @code{@var{Context}} at the current time step, with
+the following arguments:
@itemize
@item the layout object itself,
@item the context where the layout object was created, and
@lilypond[quote,verbatim,ragged-right]
#(define (blanker grob grob-origin context)
- (if (and (memq 'note-head-interface (ly:grob-interfaces grob))
- (< (abs (ly:grob-property grob 'staff-position)) 2))
+ (if (< (abs (ly:grob-property grob 'staff-position)) 2)
(set! (ly:grob-property grob 'transparent) #t)))
-\relative c' {
- a'4 e8 <<\applyOutput #'Voice #blanker a c d>> b2
+\relative {
+ a'4 e8 <<\applyOutput Voice.NoteHead #blanker a c d>> b2
}
@end lilypond
level use these forms
@example
-\applyOutput #'Score #@var{function}
-\applyOutput #'Staff #@var{function}
+\applyOutput Score@dots{}
+\applyOutput Staff@dots{}
@end example
\override Stem.thickness = #2.0
@end example
-Properties can also be set to a Scheme procedure,
+Properties can also be set to a Scheme procedure:
-@lilypond[fragment,verbatim,quote,relative=2]
+@lilypond[fragment,verbatim,quote]
\override Stem.thickness = #(lambda (grob)
(if (= UP (ly:grob-property grob 'direction))
2.0
7.0))
-c b a g b a g b
+\relative { c'' b a g b a g b }
@end lilypond
@noindent
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
@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
-