Translation of GIT committish: FILL-IN-HEAD-COMMITTISH
When revising a translation, copy the HEAD committish of the
- version that you are working on. See TRANSLATION for details.
+ version that you are working on. For details, see the Contributors'
+ Guide, node Updating translation committishes..
@end ignore
-@c \version "2.12.0"
+@c \version "2.14.0"
@node Interfaces for programmers
@chapter Interfaces for programmers
Advanced tweaks may be performed by using Scheme. If you are
not familiar with Scheme, you may wish to read our
-@rlearning{Scheme tutorial}.
+@ref{Scheme tutorial}.
@menu
* Music functions::
-* Programmer interfaces::
-* Building complicated functions::
-* Markup programmer interface::
+* Markup functions::
* Contexts for programmers::
-* Scheme procedures as properties::
-* Using Scheme code instead of \tweak::
+* Callback functions::
+* Inline Scheme code::
* Difficult tweaks::
@end menu
@node Music functions
@section Music functions
-This section discusses how to create music functions within LilyPond.
+@emph{Music functions} are scheme procedures that can create music
+expressions automatically, and can be used to greatly simplify the
+input file.
@menu
-* Overview of music functions::
+* Music function definitions::
+* Music function usage::
* Simple substitution functions::
-* Paired substitution functions::
+* Intermediate substitution functions::
* Mathematics in functions::
-* Void functions::
* Functions without arguments::
+* Void functions::
@end menu
-@node Overview of music functions
-@subsection Overview of music functions
-Making a function that substitutes a variable into LilyPond
-code is easy. The general form of these functions is
+@node Music function definitions
+@subsection Music function definitions
+
+The general form for defining music functions is:
@example
function =
-#(define-music-function (parser location @var{var1} @var{var2}...@var{vari}... )
- (@var{var1-type?} @var{var2-type?}...@var{vari-type?}...)
- #@{
- @emph{...music...}
- #@})
+#(define-music-function
+ (parser location @var{arg1} @var{arg2} @dots{})
+ (@var{type1?} @var{type2?} @dots{})
+ @var{music})
@end example
@noindent
where
@multitable @columnfractions .33 .66
-@item @var{vari} @tab @var{i}th variable
-@item @var{vari-type?} @tab type of @var{i}th variable
-@item @var{...music...} @tab normal LilyPond input, using
- variables as @code{#$var1}, etc.
+@item @code{@var{argN}}
+@tab @var{n}th argument
+
+@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.
+
+@item @code{@var{music}}
+@tab A music expression, optionally written in scheme, with any
+LilyPond code enclosed in hashed braces
+(@tie{}@w{@code{#@{@dots{}#@}}}@tie{}). Within LilyPond code
+blocks, use @code{$} to reference function arguments (eg.,
+@samp{$arg1}) or to start an inline scheme expression containing
+function arguments (eg., @w{@samp{$(cons arg1 arg2)}}).
+
@end multitable
-The following input types may be used as variables in a music
-function. This list is not exhaustive; see other documentation
-specifically about Scheme for more variable types.
+@noindent
+Some type predicates are specially recognized by the parser and will
+make the parser look for the respective arguments in Lilypond syntax
+rather than in Scheme syntax. Currently these are @code{ly:music?},
+@code{markup?}, @code{ly:pitch?}, and @code{ly:duration?}.
-@multitable @columnfractions .33 .66
-@headitem Input type @tab @var{vari-type?} notation
-@item Integer @tab @code{integer?}
-@item Float (decimal number) @tab @code{number?}
-@item Text string @tab @code{string?}
-@item Markup @tab @code{markup?}
-@item Music expression @tab @code{ly:music?}
-@item A pair of variables @tab @code{pair?}
-@end multitable
+If you really want to input one of those items as a Scheme rather than a
+Lilypond expression, you may write them as a Scheme expression that
+calls @code{ly:export} at its outermost level.
-The @code{parser} and @code{location} arguments are mandatory,
-and are used in some advanced situations. The @code{parser}
-argument is used to gain access to the value of another LilyPond
-variable. The @code{location} argument
-is used to set the @q{origin} of the music expression that is built
-by the music function, so that in case of a syntax error LilyPond
-can tell the user an appropriate place to look in the input file.
+Other type predicates, including user-defined ones, will make the
+respective argument only be accepted as a Scheme expression.
+For a list of available type predicates, see
+@ruser{Predefined type predicates}.
-@node Simple substitution functions
-@subsection Simple substitution functions
+@seealso
-Here is a simple example,
+Notation Reference:
+@ruser{Predefined type predicates}.
-@lilypond[quote,verbatim,ragged-right]
-padText = #(define-music-function (parser location padding) (number?)
- #{
- \once \override TextScript #'padding = #$padding
- #})
-
-\relative c''' {
- c4^"piu mosso" b a b
- \padText #1.8
- c4^"piu mosso" d e f
- \padText #2.6
- c4^"piu mosso" fis a g
-}
-@end lilypond
+Installed Files:
+@file{lily/music-scheme.cc},
+@file{scm/c++.scm},
+@file{scm/lily.scm}.
-Music expressions may be substituted as well,
-@lilypond[quote,verbatim,ragged-right]
-custosNote = #(define-music-function (parser location note)
- (ly:music?)
- #{
- \once \override Voice.NoteHead #'stencil =
- #ly:text-interface::print
- \once \override Voice.NoteHead #'text =
- \markup \musicglyph #"custodes.mensural.u0"
- \once \override Voice.Stem #'stencil = ##f
- $note
- #})
-
-{ c' d' e' f' \custosNote g' }
-@end lilypond
+@node Music function usage
+@subsection Music function usage
+Music functions may currently be used in three 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.
-Multiple variables may be used,
+@itemize
+@item
+At top level in a music expression. There are no special restrictions
+on the argument list. Using the @code{#@{}@dots{}@code{#@}} construct
+produces a sequential music expression and consequently can only applied
+in this context.
-@lilypond[quote,verbatim,ragged-right]
-tempoPadded = #(define-music-function (parser location padding tempotext)
- (number? string?)
-#{
- \once \override Score.MetronomeMark #'padding = $padding
- \tempo \markup { \bold $tempotext }
-#})
+@item
+As a post-event. All trailing arguments of the music function with the
+predicate @code{ly:music?} will get parsed also as post-events. Note
+that returning post-events will also be acceptable for music functions
+called at top level, leading to a result roughly equivalent to
+@example
+s 1*0-\fun
+@end example
-\relative c'' {
- \tempo \markup { "Low tempo" }
- c4 d e f g1
- \tempoPadded #4.0 #"High tempo"
- g4 f e d c1
-}
-@end lilypond
+@item
+As a chord constituent. All trailing arguments of the music function
+with the predicate @code{ly:music?} will get parsed also as chord
+constituents.
+@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.
+
+There is another somewhat special rule: if you have a predicate
+@code{ly:music?} directly before a @code{ly:duration?} predicate, then
+the corresponding music expression must be either a music identifier, or
+literal sequential or parallel music enclosed in
+@code{@{}@dots{}@code{@}} or @code{<<}@dots{}@code{>>} explicitly.
+Otherwise, Lilypond could get confused about where the music ends and
+the duration starts.
-@node Paired substitution functions
-@subsection Paired substitution functions
+@node Simple substitution functions
+@subsection Simple substitution functions
-Some @code{\override} commands require a pair of numbers
-(called a @code{cons cell} in Scheme). To pass these numbers
-into a function, either use a @code{pair?} variable, or
-insert the @code{cons} into the music function.
+Simple substitution functions are music functions whose output
+music expression is written in LilyPond format and contains
+function arguments in the output expression. They are described
+in @ruser{Substitution function examples}.
+
+
+@node Intermediate substitution functions
+@subsection Intermediate substitution functions
+
+Intermediate substitution functions involve a mix of Scheme code
+and LilyPond code in the music expression to be returned.
+
+Some @code{\override} commands require an argument consisting of
+a pair of numbers (called a @emph{cons cell} in Scheme).
+
+The pair can be directly passed into the music function,
+using a @code{pair?} variable:
-@quotation
@example
manualBeam =
-#(define-music-function (parser location beg-end)
- (pair?)
-#@{
- \once \override Beam #'positions = #$beg-end
-#@})
-
-\relative @{
+#(define-music-function
+ (parser location beg-end)
+ (pair?)
+ #@{
+ \once \override Beam #'positions = $beg-end
+ #@})
+
+\relative c' @{
\manualBeam #'(3 . 6) c8 d e f
@}
@end example
-@end quotation
-@noindent
-or
+Alternatively, the numbers making up the pair can be
+passed as separate arguments, and the Scheme code
+used to create the pair can be included in the
+music expression:
@lilypond[quote,verbatim,ragged-right]
manualBeam =
-#(define-music-function (parser location beg end)
- (number? number?)
-#{
- \once \override Beam #'positions = #(cons $beg $end)
-#})
-
-\relative {
+#(define-music-function
+ (parser location beg end)
+ (number? number?)
+ #{
+ \once \override Beam #'positions = $(cons beg end)
+ #})
+
+\relative c' {
\manualBeam #3 #6 c8 d e f
}
@end lilypond
addition to simple substitution,
@lilypond[quote,verbatim,ragged-right]
-AltOn = #(define-music-function (parser location mag) (number?)
- #{ \override Stem #'length = #$(* 7.0 mag)
+AltOn =
+#(define-music-function
+ (parser location mag)
+ (number?)
+ #{
+ \override Stem #'length = $(* 7.0 mag)
\override NoteHead #'font-size =
- #$(inexact->exact (* (/ 6.0 (log 2.0)) (log mag))) #})
+ $(inexact->exact (* (/ 6.0 (log 2.0)) (log mag)))
+ #})
AltOff = {
\revert Stem #'length
\revert NoteHead #'font-size
}
-{ c'2 \AltOn #0.5 c'4 c'
- \AltOn #1.5 c' c' \AltOff c'2 }
+\relative c' {
+ c2 \AltOn #0.5 c4 c
+ \AltOn #1.5 c c \AltOff c2
+}
@end lilypond
@noindent
This example may be rewritten to pass in music expressions,
@lilypond[quote,verbatim,ragged-right]
-withAlt = #(define-music-function (parser location mag music) (number? ly:music?)
- #{ \override Stem #'length = #$(* 7.0 mag)
+withAlt =
+#(define-music-function
+ (parser location mag music)
+ (number? ly:music?)
+ #{
+ \override Stem #'length = $(* 7.0 mag)
\override NoteHead #'font-size =
- #$(inexact->exact (* (/ 6.0 (log 2.0)) (log mag)))
+ $(inexact->exact (* (/ 6.0 (log 2.0)) (log mag)))
$music
\revert Stem #'length
- \revert NoteHead #'font-size #})
+ \revert NoteHead #'font-size
+ #})
-{ c'2 \withAlt #0.5 {c'4 c'}
- \withAlt #1.5 {c' c'} c'2 }
+\relative c' {
+ c2 \withAlt #0.5 { c4 c }
+ \withAlt #1.5 { c c } c2
+}
@end lilypond
-@node Void functions
-@subsection Void functions
-
-A music function must return a music expression, but sometimes we
-may want to have a function that does not involve music (such as
-turning off Point and Click). To do this, we return a @code{void}
-music expression.
-
-That is why the form
-that is returned is the @code{(make-music ...)}. With the
-@code{'void} property set to @code{#t}, the parser is told to
-actually disregard this returned music
-expression. Thus the important part of the void music function is the
-processing done by the function, not the music expression that is
-returned.
-
-@example
-noPointAndClick =
-#(define-music-function (parser location) ()
- (ly:set-option 'point-and-click #f)
- (make-music 'SequentialMusic 'void #t))
-...
-\noPointAndClick % disable point and click
-@end example
-
@node Functions without arguments
@subsection Functions without arguments
@example
displayBarNum =
-#(define-music-function (parser location) ()
+#(define-music-function
+ (parser location)
+ ()
(if (eq? #t (ly:get-option 'display-bar-numbers))
#@{ \once \override Score.BarNumber #'break-visibility = ##f #@}
#@{#@}))
@end example
-@node Programmer interfaces
-@section Programmer interfaces
-
-This section contains information about mixing LilyPond
-and Scheme.
-
-@menu
-* Input variables and Scheme::
-* Internal music representation::
-@end menu
-
-
-@node Input variables and Scheme
-@subsection Input variables and Scheme
-
-The input format supports the notion of variables: in the following
-example, a music expression is assigned to a variable with the name
-@code{traLaLa}.
-
-@example
-traLaLa = @{ c'4 d'4 @}
-@end example
-
-@noindent
-
-There is also a form of scoping: in the following example, the
-@code{\layout} block also contains a @code{traLaLa} variable, which is
-independent of the outer @code{\traLaLa}.
-@example
-traLaLa = @{ c'4 d'4 @}
-\layout @{ traLaLa = 1.0 @}
-@end example
-@c
-In effect, each input file is a scope, and all @code{\header},
-@code{\midi}, and @code{\layout} blocks are scopes nested inside that
-toplevel scope.
-
-Both variables and scoping are implemented in the GUILE module system.
-An anonymous Scheme module is attached to each scope. An assignment of
-the form
-@example
-traLaLa = @{ c'4 d'4 @}
-@end example
-
-@noindent
-is internally converted to a Scheme definition
-@example
-(define traLaLa @var{Scheme value of `@code{... }'})
-@end example
-
-This means that input variables and Scheme variables may be freely
-mixed. In the following example, a music fragment is stored in the
-variable @code{traLaLa}, and duplicated using Scheme. The result is
-imported in a @code{\score} block by means of a second variable
-@code{twice}:
-
-@lilypond[verbatim]
-traLaLa = { c'4 d'4 }
-
-%% dummy action to deal with parser lookahead
-#(display "this needs to be here, sorry!")
-
-#(define newLa (map ly:music-deep-copy
- (list traLaLa traLaLa)))
-#(define twice
- (make-sequential-music newLa))
-
-{ \twice }
-@end lilypond
-
-@c Due to parser lookahead
-
-In this example, the assignment happens after the parser has
-verified that nothing interesting happens after
-@code{traLaLa = @{ ... @}}. Without the dummy statement in the
-above example, the @code{newLa} definition is executed before
-@code{traLaLa} is defined, leading to a syntax error.
-
-The above example shows how to @q{export} music expressions from the
-input to the Scheme interpreter. The opposite is also possible. By
-wrapping a Scheme value in the function @code{ly:export}, a Scheme
-value is interpreted as if it were entered in LilyPond syntax.
-Instead of defining @code{\twice}, the example above could also have
-been written as
+@node Void functions
+@subsection Void functions
-@example
-...
-@{ #(ly:export (make-sequential-music (list newLa))) @}
-@end example
+A music function must return a music expression, but sometimes we
+may want to have a function that does not involve music (such as
+turning off Point and Click). To do this, we return a @code{void}
+music expression.
-Scheme code is evaluated as soon as the parser encounters it. To
-define some Scheme code in a macro (to be called later), use
-@ref{Void functions}, or
+That is why the form that is returned is the
+@w{@code{(make-music @dots{})}}. With the @code{'void} property
+set to @code{#t}, the parser is told to actually disregard this
+returned music expression. Thus the important part of the void
+music function is the processing done by the function, not the
+music expression that is returned.
@example
-#(define (nopc)
- (ly:set-option 'point-and-click #f))
-
+noPointAndClick =
+#(define-music-function
+ (parser location)
+ ()
+ (ly:set-option 'point-and-click #f)
+ (make-music 'SequentialMusic 'void #t))
...
-#(nopc)
-@{ c'4 @}
-@end example
-
-
-@knownissues
-
-Mixing Scheme and LilyPond variables is not possible with the
-@code{--safe} option.
-
-
-@node Internal music representation
-@subsection Internal music representation
-
-When a music expression is parsed, it is converted into a set of
-Scheme music objects. The defining property of a music object is that
-it takes up time. Time is a rational number that measures the length
-of a piece of music in whole notes.
-
-A music object has three kinds of types:
-@itemize
-@item
-music name: Each music expression has a name. For example, a note
-leads to a @rinternals{NoteEvent}, and @code{\simultaneous} leads to
-a @rinternals{SimultaneousMusic}. A list of all expressions
-available is in the Internals Reference manual, under
-@rinternals{Music expressions}.
-
-@item
-@q{type} or interface: Each music name has several @q{types} or
-interfaces, for example, a note is an @code{event}, but it is also a
-@code{note-event}, a @code{rhythmic-event}, and a
-@code{melodic-event}. All classes of music are listed in the
-Internals Reference, under
-@rinternals{Music classes}.
-
-@item
-C++ object: Each music object is represented by an object of the C++
-class @code{Music}.
-@end itemize
-
-The actual information of a music expression is stored in properties.
-For example, a @rinternals{NoteEvent} has @code{pitch} and
-@code{duration} properties that store the pitch and duration of that
-note. A list of all properties available can be found in the
-Internals Reference, under @rinternals{Music properties}.
-
-A compound music expression is a music object that contains other
-music objects in its properties. A list of objects can be stored in
-the @code{elements} property of a music object, or a single @q{child}
-music object in the @code{element} property. For example,
-@rinternals{SequentialMusic} has its children in @code{elements},
-and @rinternals{GraceMusic} has its single argument in
-@code{element}. The body of a repeat is stored in the @code{element}
-property of @rinternals{RepeatedMusic}, and the alternatives in
-@code{elements}.
-
-
-
-@node Building complicated functions
-@section Building complicated functions
-
-This section explains how to gather the information necessary
-to create complicated music functions.
-
-@menu
-* Displaying music expressions::
-* Music properties::
-* Doubling a note with slurs (example)::
-* Adding articulation to notes (example)::
-@end menu
-
-
-@node Displaying music expressions
-@subsection Displaying music expressions
-
-@cindex internal storage
-@cindex displaying music expressions
-@cindex internal representation, displaying
-@cindex displayMusic
-@funindex \displayMusic
-
-When writing a music function it is often instructive to inspect how
-a music expression is stored internally. This can be done with the
-music function @code{\displayMusic}
-
-@example
-@{
- \displayMusic @{ c'4\f @}
-@}
-@end example
-
-@noindent
-will display
-
-@example
-(make-music
- 'SequentialMusic
- 'elements
- (list (make-music
- 'EventChord
- 'elements
- (list (make-music
- 'NoteEvent
- 'duration
- (ly:make-duration 2 0 1 1)
- 'pitch
- (ly:make-pitch 0 0 0))
- (make-music
- 'AbsoluteDynamicEvent
- 'text
- "f")))))
-@end example
-
-By default, LilyPond will print these messages to the console along
-with all the other messages. To split up these messages and save
-the results of @code{\display@{STUFF@}}, redirect the output to
-a file.
-
-@example
-lilypond file.ly >display.txt
-@end example
-
-With a bit of reformatting, the above information is
-easier to read,
-
-@example
-(make-music 'SequentialMusic
- 'elements (list (make-music 'EventChord
- 'elements (list (make-music 'NoteEvent
- 'duration (ly:make-duration 2 0 1 1)
- 'pitch (ly:make-pitch 0 0 0))
- (make-music 'AbsoluteDynamicEvent
- 'text "f")))))
-@end example
-
-A @code{@{ ... @}} music sequence has the name @code{SequentialMusic},
-and its inner expressions are stored as a list in its @code{'elements}
-property. A note is represented as an @code{EventChord} expression,
-containing a @code{NoteEvent} object (storing the duration and
-pitch properties) and any extra information (in this case, an
-@code{AbsoluteDynamicEvent} with a @code{"f"} text property.
-
-
-@node Music properties
-@subsection Music properties
-
-The @code{NoteEvent} object is the first object of the
-@code{'elements} property of @code{someNote}.
-
-@example
-someNote = c'
-\displayMusic \someNote
-===>
-(make-music
- 'EventChord
- 'elements
- (list (make-music
- 'NoteEvent
- 'duration
- (ly:make-duration 2 0 1 1)
- 'pitch
- (ly:make-pitch 0 0 0))))
-@end example
-
-The @code{display-scheme-music} function is the function used by
-@code{\displayMusic} to display the Scheme representation of a music
-expression.
-
-@example
-#(display-scheme-music (first (ly:music-property someNote 'elements)))
-===>
-(make-music
- 'NoteEvent
- 'duration
- (ly:make-duration 2 0 1 1)
- 'pitch
- (ly:make-pitch 0 0 0))
-@end example
-
-Then the note pitch is accessed through the @code{'pitch} property
-of the @code{NoteEvent} object,
-
-@example
-#(display-scheme-music
- (ly:music-property (first (ly:music-property someNote 'elements))
- 'pitch))
-===>
-(ly:make-pitch 0 0 0)
-@end example
-
-The note pitch can be changed by setting this @code{'pitch} property,
-
-@funindex \displayLilyMusic
-
-@example
-#(set! (ly:music-property (first (ly:music-property someNote 'elements))
- 'pitch)
- (ly:make-pitch 0 1 0)) ;; set the pitch to d'.
-\displayLilyMusic \someNote
-===>
-d'
-@end example
-
-
-@node Doubling a note with slurs (example)
-@subsection Doubling a note with slurs (example)
-
-Suppose we want to create a function that translates input like
-@code{a} into @code{a( a)}. We begin by examining the internal
-representation of the desired result.
-
-@example
-\displayMusic@{ a'( a') @}
-===>
-(make-music
- 'SequentialMusic
- 'elements
- (list (make-music
- 'EventChord
- 'elements
- (list (make-music
- 'NoteEvent
- 'duration
- (ly:make-duration 2 0 1 1)
- 'pitch
- (ly:make-pitch 0 5 0))
- (make-music
- 'SlurEvent
- 'span-direction
- -1)))
- (make-music
- 'EventChord
- 'elements
- (list (make-music
- 'NoteEvent
- 'duration
- (ly:make-duration 2 0 1 1)
- 'pitch
- (ly:make-pitch 0 5 0))
- (make-music
- 'SlurEvent
- 'span-direction
- 1)))))
-@end example
-
-The bad news is that the @code{SlurEvent} expressions
-must be added @q{inside} the note (or more precisely,
-inside the @code{EventChord} expression).
-
-Now we examine the input,
-
-@example
-(make-music
- 'SequentialMusic
- 'elements
- (list (make-music
- 'EventChord
- 'elements
- (list (make-music
- 'NoteEvent
- 'duration
- (ly:make-duration 2 0 1 1)
- 'pitch
- (ly:make-pitch 0 5 0))))))
-@end example
-
-So in our function, we need to clone this expression (so that we
-have two notes to build the sequence), add @code{SlurEvents} to the
-@code{'elements} property of each one, and finally make a
-@code{SequentialMusic} with the two @code{EventChords}.
-
-@example
-doubleSlur = #(define-music-function (parser location note) (ly:music?)
- "Return: @{ note ( note ) @}.
- `note' is supposed to be an EventChord."
- (let ((note2 (ly:music-deep-copy note)))
- (set! (ly:music-property note 'elements)
- (cons (make-music 'SlurEvent 'span-direction -1)
- (ly:music-property note 'elements)))
- (set! (ly:music-property note2 'elements)
- (cons (make-music 'SlurEvent 'span-direction 1)
- (ly:music-property note2 'elements)))
- (make-music 'SequentialMusic 'elements (list note note2))))
-@end example
-
-
-@node Adding articulation to notes (example)
-@subsection Adding articulation to notes (example)
-
-The easy way to add articulation to notes is to merge two music
-expressions into one context, as explained in
-@ruser{Creating contexts}. However, suppose that we want to write
-a music function that does this.
-
-A @code{$variable} inside the @code{#@{...#@}} notation is like
-a regular @code{\variable} in classical LilyPond notation. We
-know that
-
-@example
-@{ \music -. -> @}
-@end example
-
-@noindent
-will not work in LilyPond. We could avoid this problem by attaching
-the articulation to a fake note,
-
-@example
-@{ << \music s1*0-.-> @}
-@end example
-
-@noindent
-but for the sake of this example, we will learn how to do this in
-Scheme. We begin by examining our input and desired output,
-
-@example
-% input
-\displayMusic c4
-===>
-(make-music
- 'EventChord
- 'elements
- (list (make-music
- 'NoteEvent
- 'duration
- (ly:make-duration 2 0 1 1)
- 'pitch
- (ly:make-pitch -1 0 0))))
-=====
-% desired output
-\displayMusic c4->
-===>
-(make-music
- 'EventChord
- 'elements
- (list (make-music
- 'NoteEvent
- 'duration
- (ly:make-duration 2 0 1 1)
- 'pitch
- (ly:make-pitch -1 0 0))
- (make-music
- 'ArticulationEvent
- 'articulation-type
- "marcato")))
-@end example
-
-We see that a note (@code{c4}) is represented as an @code{EventChord}
-expression, with a @code{NoteEvent} expression in its elements list. To
-add a marcato articulation, an @code{ArticulationEvent} expression must
-be added to the elements property of the @code{EventChord}
-expression.
-
-To build this function, we begin with
-
-@example
-(define (add-marcato event-chord)
- "Add a marcato ArticulationEvent to the elements of `event-chord',
- which is supposed to be an EventChord expression."
- (let ((result-event-chord (ly:music-deep-copy event-chord)))
- (set! (ly:music-property result-event-chord 'elements)
- (cons (make-music 'ArticulationEvent
- 'articulation-type "marcato")
- (ly:music-property result-event-chord 'elements)))
- result-event-chord))
-@end example
-
-The first line is the way to define a function in Scheme: the function
-name is @code{add-marcato}, and has one variable called
-@code{event-chord}. In Scheme, the type of variable is often clear
-from its name. (this is good practice in other programming languages,
-too!)
-
-@example
-"Add a marcato..."
-@end example
-
-@noindent
-is a description of what the function does. This is not strictly
-necessary, but just like clear variable names, it is good practice.
-
-@example
-(let ((result-event-chord (ly:music-deep-copy event-chord)))
-@end example
-
-@code{let} is used to declare local variables. Here we use one local
-variable, named @code{result-event-chord}, to which we give the value
-@code{(ly:music-deep-copy event-chord)}. @code{ly:music-deep-copy} is
-a function specific to LilyPond, like all functions prefixed by
-@code{ly:}. It is use to make a copy of a music
-expression. Here we copy @code{event-chord} (the parameter of the
-function). Recall that our purpose is to add a marcato to an
-@code{EventChord} expression. It is better to not modify the
-@code{EventChord} which was given as an argument, because it may be
-used elsewhere.
-
-Now we have a @code{result-event-chord}, which is a
-@code{NoteEventChord} expression and is a copy of
-@code{event-chord}. We add the marcato to its @code{'elements}
-list property.
-
-@example
-(set! place new-value)
-@end example
-
-Here, what we want to set (the @q{place}) is the @code{'elements}
-property of @code{result-event-chord} expression.
-
-@example
-(ly:music-property result-event-chord 'elements)
-@end example
-
-@code{ly:music-property} is the function used to access music properties
-(the @code{'elements}, @code{'duration}, @code{'pitch}, etc, that we
-see in the @code{\displayMusic} output above). The new value is the
-former @code{'elements} property, with an extra item: the
-@code{ArticulationEvent} expression, which we copy from the
-@code{\displayMusic} output,
-
-@example
-(cons (make-music 'ArticulationEvent
- 'articulation-type "marcato")
- (ly:music-property result-event-chord 'elements))
-@end example
-
-@code{cons} is used to add an element to a list without modifying
-the original list. This is what we want: the same list as before,
-plus the new @code{ArticulationEvent} expression. The order
-inside the @code{'elements} property is not important here.
-
-Finally, once we have added the marcato articulation to its @code{elements}
-property, we can return @code{result-event-chord}, hence the last line of
-the function.
-
-Now we transform the @code{add-marcato} function into a music
-function,
-
-@example
-addMarcato = #(define-music-function (parser location event-chord)
- (ly:music?)
- "Add a marcato ArticulationEvent to the elements of `event-chord',
- which is supposed to be an EventChord expression."
- (let ((result-event-chord (ly:music-deep-copy event-chord)))
- (set! (ly:music-property result-event-chord 'elements)
- (cons (make-music 'ArticulationEvent
- 'articulation-type "marcato")
- (ly:music-property result-event-chord 'elements)))
- result-event-chord))
-@end example
-
-We may verify that this music function works correctly,
-
-@example
-\displayMusic \addMarcato c4
+\noPointAndClick % disable point and click
@end example
-@node Markup programmer interface
-@section Markup programmer interface
+@node Markup functions
+@section Markup functions
Markups are implemented as special Scheme functions which produce a
@code{Stencil} object given a number of arguments.
@code{text example} string, and then it raises that Stencil by 0.5
staff space. This is a rather simple example; more complex examples
are in the rest
-of this section, and in @file{scm/@/define@/-markup@/-commands@/.scm}.
+of this section, and in @file{scm/define-markup-commands.scm}.
@node New markup command definition
@subsection New markup command definition
-New markup commands can be defined
-with the @code{define-markup-command} Scheme macro.
+This section discusses the definition of new markup commands.
+
+@menu
+* Markup command definition syntax::
+* On properties::
+* A complete example::
+* Adapting builtin commands::
+@end menu
+
+@node Markup command definition syntax
+@unnumberedsubsubsec Markup command definition syntax
+
+New markup commands can be defined using the
+@code{define-markup-command} Scheme macro, at top-level.
@lisp
(define-markup-command (@var{command-name} @var{layout} @var{props} @var{arg1} @var{arg2} ...)
- (@var{arg1-type?} @var{arg2-type?} ...)
+ (@var{arg1-type?} @var{arg2-type?} ...)
+ [ #:properties ((@var{property1} @var{default-value1})
+ ...) ]
..command body..)
@end lisp
The arguments are
-@table @var
-@item argi
-@var{i}th command argument
-@item argi-type?
-a type predicate for the i@var{th} argument
+@table @code
+@item @var{command-name}
+the markup command name
@item layout
-the @q{layout} definition
+the @q{layout} definition.
@item props
-a list of alists, containing all active properties.
+a list of associative lists, containing all active properties.
+@item @var{argi}
+@var{i}th command argument
+@item @var{argi-type?}
+a type predicate for the i@var{th} argument
@end table
-As a simple example, we show how to add a @code{\smallcaps} command,
-which selects a small caps font. Normally we could select the
-small caps font,
+If the command uses properties from the @code{props} arguments,
+the @code{#:properties} keyword can be used to specify which
+properties are used along with their default values.
-@example
-\markup @{ \override #'(font-shape . caps) Text-in-caps @}
-@end example
+Arguments are distinguished according to their type:
+@itemize
+@item a markup, corresponding to type predicate @code{markup?};
+@item a list of markups, corresponding to type predicate
+@code{markup-list?};
+@item any other scheme object, corresponding to type predicates such as
+@code{list?}, @code{number?}, @code{boolean?}, etc.
+@end itemize
-@noindent
-This selects the caps font by setting the @code{font-shape} property to
-@code{#'caps} for interpreting @code{Text-in-caps}.
+There is no limitation on the order of arguments (after the
+standard @code{layout} and @code{props} arguments). However,
+markup functions taking a markup as their last argument are
+somewhat special as you can apply them to a markup list, and the
+result is a markup list where the markup function (with the
+specified leading arguments) has been applied to every element of
+the original markup list.
-To make the above available as @code{\smallcaps} command, we must
-define a function using @code{define-markup-command}. The command should
-take a single argument of type @code{markup}. Therefore the start of the
-definition should read
+Since replicating the leading arguments for applying a markup
+function to a markup list is cheap mostly for Scheme arguments,
+you avoid performance pitfalls by just using Scheme arguments for
+the leading arguments of markup functions that take a markup as
+their last argument.
-@example
-(define-markup-command (smallcaps layout props argument) (markup?)
-@end example
+@node On properties
+@unnumberedsubsubsec On properties
-@noindent
+The @code{layout} and @code{props} arguments of markup commands bring a
+context for the markup interpretation: font size, line width, etc.
-What follows is the content of the command: we should interpret
-the @code{argument} as a markup, i.e.,
+The @code{layout} argument allows access to properties defined in
+@code{paper} blocks, using the @code{ly:output-def-lookup} function.
+For instance, the line width (the same as the one used in scores) is
+read using:
@example
-(interpret-markup layout @dots{} argument)
+(ly:output-def-lookup layout 'line-width)
@end example
-@noindent
-This interpretation should add @code{'(font-shape . caps)} to the active
-properties, so we substitute the following for the @dots{} in the
-above example:
+The @code{props} argument makes some properties accessible to markup
+commands. For instance, when a book title markup is interpreted, all
+the variables defined in the @code{\header} block are automatically
+added to @code{props}, so that the book title markup can access the book
+title, composer, etc. It is also a way to configure the behaviour of a
+markup command: for example, when a command uses font size during
+processing, the font size is read from @code{props} rather than having a
+@code{font-size} argument. The caller of a markup command may change
+the value of the font size property in order to change the behaviour.
+Use the @code{#:properties} keyword of @code{define-markup-command} to
+specify which properties shall be read from the @code{props} arguments.
-@example
-(cons (list '(font-shape . caps) ) props)
-@end example
+The example in next section illustrates how to access and override
+properties in a markup command.
-@noindent
-The variable @code{props} is a list of alists, and we prepend to it by
-cons'ing a list with the extra setting.
+@node A complete example
+@unnumberedsubsubsec A complete example
+The following example defines a markup command to draw a double box
+around a piece of text.
-Suppose that we are typesetting a recitative in an opera and
-we would like to define a command that will show character names in a
-custom manner. Names should be printed with small caps and moved a
-bit up and to the left. We will define a @code{\character} command
-which takes into account the necessary translation and uses the newly
-defined @code{\smallcaps} command:
+Firstly, we need to build an approximative result using markups.
+Consulting the @ruser{Text markup commands} shows us the @code{\box}
+command is useful:
-@example
-#(define-markup-command (character layout props name) (string?)
- "Print the character name in small caps, translated to the left and
- top. Syntax: \\character #\"name\""
+@lilypond[quote,verbatim,ragged-right]
+\markup \box \box HELLO
+@end lilypond
+
+Now, we consider that more padding between the text and the boxes is
+preferable. According to the @code{\box} documentation, this command
+uses a @code{box-padding} property, which defaults to 0.2. The
+documentation also mentions how to override it:
+
+@lilypond[quote,verbatim,ragged-right]
+\markup \box \override #'(box-padding . 0.6) \box A
+@end lilypond
+
+Then, the padding between the two boxes is considered too small, so we
+override it too:
+
+@lilypond[quote,verbatim,ragged-right]
+\markup \override #'(box-padding . 0.4) \box \override #'(box-padding . 0.6) \box A
+@end lilypond
+
+Repeating this lengthy markup would be painful. This is where a markup
+command is needed. Thus, we write a @code{double-box} markup command,
+taking one argument (the text). This draws the two boxes, with some
+padding.
+
+@lisp
+#(define-markup-command (double-box layout props text) (markup?)
+ "Draw a double box around text."
(interpret-markup layout props
- (markup #:hspace 0 #:translate (cons -3 1) #:smallcaps name)))
-@end example
+ (markup #:override '(box-padding . 0.4) #:box
+ #:override '(box-padding . 0.6) #:box text)))
+@end lisp
-There is one complication that needs explanation: texts above and below
-the staff are moved vertically to be at a certain distance (the
-@code{padding} property) from the staff and the notes. To make sure
-that this mechanism does not annihilate the vertical effect of our
-@code{#:translate}, we add an empty string (@code{#:hspace 0}) before the
-translated text. Now the @code{#:hspace 0} will be put above the notes,
-and the
-@code{name} is moved in relation to that empty string. The net effect is
-that the text is moved to the upper left.
+@code{text} is the name of the command argument, and @code{markup?} its
+type: it identifies it as a markup. The @code{interpret-markup}
+function is used in most of markup commands: it builds a stencil, using
+@code{layout}, @code{props}, and a markup. Here, this markup is built
+using the @code{markup} scheme macro, see @ref{Markup construction in Scheme}.
+The transformation from @code{\markup} expression to scheme
+markup expression is straight-forward.
-The final result is as follows:
+The new command can be used as follow:
@example
-@{
- c''^\markup \character #"Cleopatra"
- e'^\markup \character #"Giulio Cesare"
-@}
+\markup \double-box A
@end example
-@lilypond[quote,ragged-right]
-#(define-markup-command (smallcaps layout props str) (string?)
- "Print the string argument in small caps. Syntax: \\smallcaps #\"string\""
- (interpret-markup layout props
- (make-line-markup
- (map (lambda (s)
- (if (= (string-length s) 0)
- s
- (markup #:large (string-upcase (substring s 0 1))
- #:translate (cons -0.6 0)
- #:tiny (string-upcase (substring s 1)))))
- (string-split str #\Space)))))
-
-#(define-markup-command (character layout props name) (string?)
- "Print the character name in small caps, translated to the left and
- top. Syntax: \\character #\"name\""
+It would be nice to make the @code{double-box} command customizable:
+here, the @code{box-padding} values are hard coded, and cannot be
+changed by the user. Also, it would be better to distinguish the
+padding between the two boxes, from the padding between the inner box
+and the text. So we will introduce a new property,
+@code{inter-box-padding}, for the padding between the two boxes. The
+@code{box-padding} will be used for the inner padding. The new code is
+now as follows:
+
+@lisp
+#(define-markup-command (double-box layout props text) (markup?)
+ #:properties ((inter-box-padding 0.4)
+ (box-padding 0.6))
+ "Draw a double box around text."
(interpret-markup layout props
- (markup #:hspace 0 #:translate (cons -3 1) #:smallcaps name)))
+ (markup #:override `(box-padding . ,inter-box-padding) #:box
+ #:override `(box-padding . ,box-padding) #:box text)))
+@end lisp
-{
- c''^\markup \character #"Cleopatra" c'' c'' c''
- e'^\markup \character #"Giulio Cesare" e' e' e'
-}
-@end lilypond
+Here, the @code{#:properties} keyword is used so that the
+@code{inter-box-padding} and @code{box-padding} properties are read from
+the @code{props} argument, and default values are given to them if the
+properties are not defined.
-We have used the @code{caps} font shape, but suppose that our font
-does not have a small-caps variant. In that case we have to fake
-the small caps font by setting a string in uppercase with the
-first letter a little larger:
+Then, these values are used to override the @code{box-padding}
+properties used by the two @code{\box} commands. Note the backquote and
+the comma in the @code{\override} argument: they allow you to introduce
+a variable value into a literal expression.
-@example
-#(define-markup-command (smallcaps layout props str) (string?)
- "Print the string argument in small caps."
+Now, the command can be used in a markup, and the boxes padding be
+customized:
+
+@lilypond[quote,verbatim,ragged-right]
+#(define-markup-command (double-box layout props text) (markup?)
+ #:properties ((inter-box-padding 0.4)
+ (box-padding 0.6))
+ "Draw a double box around text."
(interpret-markup layout props
- (make-line-markup
- (map (lambda (s)
- (if (= (string-length s) 0)
- s
- (markup #:large (string-upcase (substring s 0 1))
- #:translate (cons -0.6 0)
- #:tiny (string-upcase (substring s 1)))))
- (string-split str #\Space)))))
-@end example
+ (markup #:override `(box-padding . ,inter-box-padding) #:box
+ #:override `(box-padding . ,box-padding) #:box text)))
-The @code{smallcaps} command first splits its string argument into
-tokens separated by spaces (@code{(string-split str #\Space)}); for
-each token, a markup is built with the first letter made large and
-upcased (@code{#:large (string-upcase (substring s 0 1))}), and a
-second markup built with the following letters made tiny and upcased
-(@code{#:tiny (string-upcase (substring s 1))}). As LilyPond
-introduces a space between markups on a line, the second markup is
-translated to the left (@code{#:translate (cons -0.6 0) ...}). Then,
-the markups built for each token are put in a line by
-@code{(make-line-markup ...)}. Finally, the resulting markup is passed
-to the @code{interpret-markup} function, with the @code{layout} and
-@code{props} arguments.
-
-Note: there is now an internal command @code{\smallCaps} which can
-be used to set text in small caps. See
-@ruser{Text markup commands}, for details.
+\markup \double-box A
+\markup \override #'(inter-box-padding . 0.8) \double-box A
+\markup \override #'(box-padding . 1.0) \double-box A
+@end lilypond
-@knownissues
+@node Adapting builtin commands
+@unnumberedsubsubsec Adapting builtin commands
-Currently, the available combinations of arguments (after the standard
-@var{layout} and @var{props} arguments) to a markup command defined with
-@code{define-markup-command} are limited as follows.
-
-@table @asis
-@item (no argument)
-@itemx @var{list}
-@itemx @var{markup}
-@itemx @var{markup markup}
-@itemx @var{scm}
-@itemx @var{scm markup}
-@itemx @var{scm scm}
-@itemx @var{scm scm markup}
-@itemx @var{scm scm markup markup}
-@itemx @var{scm markup markup}
-@itemx @var{scm scm scm}
-@end table
+A good way to start writing a new markup command, is to take example on
+a builtin one. Most of the markup commands provided with LilyPond can be
+found in file @file{scm/define-markup-commands.scm}.
-@noindent
-In the above table, @var{scm} represents native Scheme data types like
-@q{number} or @q{string}.
+For instance, we would like to adapt the @code{\draw-line} command, to
+draw a double line instead. The @code{\draw-line} command is defined as
+follow (documentation stripped):
+
+@lisp
+(define-markup-command (draw-line layout props dest)
+ (number-pair?)
+ #:category graphic
+ #:properties ((thickness 1))
+ "..documentation.."
+ (let ((th (* (ly:output-def-lookup layout 'line-thickness)
+ thickness))
+ (x (car dest))
+ (y (cdr dest)))
+ (make-line-stencil th 0 0 x y)))
+@end lisp
-As an example, it is not possible to use a markup command @code{foo} with
-four arguments defined as
+To define a new command based on an existing one, copy the definition,
+and change the command name. The @code{#:category} keyword can be
+safely removed, as it is only used for generating LilyPond
+documentation, and is of no use for user-defined markup commands.
-@example
-#(define-markup-command (foo layout props
- num1 str1 num2 str2)
- (number? string? number? string?)
- ...)
-@end example
+@lisp
+(define-markup-command (draw-double-line layout props dest)
+ (number-pair?)
+ #:properties ((thickness 1))
+ "..documentation.."
+ (let ((th (* (ly:output-def-lookup layout 'line-thickness)
+ thickness))
+ (x (car dest))
+ (y (cdr dest)))
+ (make-line-stencil th 0 0 x y)))
+@end lisp
-@noindent
-If you apply it as, say,
+Then, a property for setting the gap between two lines is added, called
+@code{line-gap}, defaulting e.g. to 0.6:
-@example
-\markup \foo #1 #"bar" #2 #"baz"
-@end example
+@lisp
+(define-markup-command (draw-double-line layout props dest)
+ (number-pair?)
+ #:properties ((thickness 1)
+ (line-gap 0.6))
+ "..documentation.."
+ ...
+@end lisp
-@cindex Scheme signature
-@cindex signature, Scheme
-@noindent
-@command{lilypond} complains that it cannot parse @code{foo} due to its
-unknown Scheme signature.
+Finally, the code for drawing two lines is added. Two calls to
+@code{make-line-stencil} are used to draw the lines, and the resulting
+stencils are combined using @code{ly:stencil-add}:
+
+@lilypond[quote,verbatim,ragged-right]
+#(define-markup-command (my-draw-line layout props dest)
+ (number-pair?)
+ #:properties ((thickness 1)
+ (line-gap 0.6))
+ "..documentation.."
+ (let* ((th (* (ly:output-def-lookup layout 'line-thickness)
+ thickness))
+ (dx (car dest))
+ (dy (cdr dest))
+ (w (/ line-gap 2.0))
+ (x (cond ((= dx 0) w)
+ ((= dy 0) 0)
+ (else (/ w (sqrt (+ 1 (* (/ dx dy) (/ dx dy))))))))
+ (y (* (if (< (* dx dy) 0) 1 -1)
+ (cond ((= dy 0) w)
+ ((= dx 0) 0)
+ (else (/ w (sqrt (+ 1 (* (/ dy dx) (/ dy dx))))))))))
+ (ly:stencil-add (make-line-stencil th x y (+ dx x) (+ dy y))
+ (make-line-stencil th (- x) (- y) (- dx x) (- dy y)))))
+
+\markup \my-draw-line #'(4 . 3)
+\markup \override #'(line-gap . 1.2) \my-draw-line #'(4 . 3)
+@end lilypond
@node New markup list command definition
indented. The indent width is taken from the @code{props} argument.
@example
#(define-markup-list-command (paragraph layout props args) (markup-list?)
- (let ((indent (chain-assoc-get 'par-indent props 2)))
- (interpret-markup-list layout props
- (make-justified-lines-markup-list (cons (make-hspace-markup indent)
- args)))))
+ #:properties ((par-indent 2))
+ (interpret-markup-list layout props
+ (make-justified-lines-markup-list (cons (make-hspace-markup par-indent)
+ args))))
@end example
Besides the usual @code{layout} and @code{props} arguments, the
First, the function gets the indent width, a property here named
@code{par-indent}, from the property list @code{props}. If the
property is not found, the default value is @code{2}. Then, a
-list of justified lines is made using the
+list of justified lines is made using the
@code{make-justified-lines-markup-list} function, which is related
to the @code{\justified-lines} built-in markup list command. A
horizontal space is added at the beginning using the
\applyContext @var{function}
@end example
-@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:
+@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:
@example
\applyContext
@funindex \applyOutput
-The most versatile way of tuning an object is @code{\applyOutput}. Its
-syntax is
+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
@example
\applyOutput @var{context} @var{proc}
@end example
@noindent
-where @var{proc} is a Scheme function, taking three arguments.
+where @code{@var{proc}} is a Scheme function, taking three arguments.
-When interpreted, the function @var{proc} is called for every layout
-object found in the context @var{context}, with the following
-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:
@itemize
@item the layout object itself,
@item the context where the layout object was created, and
In addition, the cause of the layout object, i.e., the music
expression or object that was responsible for creating it, is in the
object property @code{cause}. For example, for a note head, this is a
-@rinternals{NoteHead} event, and for a @rinternals{Stem} object,
-this is a @rinternals{NoteHead} object.
+@rinternals{NoteHead} event, and for a stem object,
+this is a @rinternals{Stem} object.
Here is a function to use for @code{\applyOutput}; it blanks
-note-heads on the center-line:
+note-heads on the center-line and next to it:
@lilypond[quote,verbatim,ragged-right]
#(define (blanker grob grob-origin context)
(if (and (memq 'note-head-interface (ly:grob-interfaces grob))
- (eq? (ly:grob-property grob 'staff-position) 0))
+ (< (abs (ly:grob-property grob 'staff-position)) 2))
(set! (ly:grob-property grob 'transparent) #t)))
-\relative {
- e4 g8 \applyOutput #'Voice #blanker b d2
+\relative c' {
+ a'4 e8 <<\applyOutput #'Voice #blanker a c d>> b2
}
@end lilypond
-@node Scheme procedures as properties
-@section Scheme procedures as properties
+@node Callback functions
+@section Callback functions
Properties (like @code{thickness}, @code{direction}, etc.) can be
set at fixed values with @code{\override}, e.g.
@code{AccidentalSuggestion},
@example
-(X-offset .
+`(X-offset .
,(ly:make-simple-closure
`(,+
,(ly:make-simple-closure
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:
-@node Using Scheme code instead of \tweak
-@section Using Scheme code instead of @code{\tweak}
+@example
+my-callback = #(lambda (grob)
+ (grob-interpret-markup grob (markup "foo")))
+@end example
+
+@node Inline Scheme code
+@section Inline Scheme code
The main disadvantage of @code{\tweak} is its syntactical
inflexibility. For example, the following produces a syntax error.
spanner object is created at a time, and it can be adjusted with
the normal mechanism. However, occasionally a spanner crosses a
line break. When this happens, the object is cloned. A separate
-object is created for every system in which the spanner appears.
+object is created for every system in which the spanner appears.
The new objects are clones of the original object and inherit all
properties, including @code{\override}s.
@lilypond[quote,verbatim,ragged-right]
#(define (my-callback grob)
- (let* (
- ; have we been split?
- (orig (ly:grob-original grob))
+ (let* (
+ ;; have we been split?
+ (orig (ly:grob-original grob))
- ; if yes, get the split pieces (our siblings)
- (siblings (if (ly:grob? orig)
- (ly:spanner-broken-into orig) '() )))
+ ;; if yes, get the split pieces (our siblings)
+ (siblings (if (ly:grob? orig)
+ (ly:spanner-broken-into orig)
+ '())))
- (if (and (>= (length siblings) 2)
- (eq? (car (last-pair siblings)) grob))
- (ly:grob-set-property! grob 'extra-offset '(-2 . 5)))))
+ (if (and (>= (length siblings) 2)
+ (eq? (car (last-pair siblings)) grob))
+ (ly:grob-set-property! grob 'extra-offset '(-2 . 5)))))
\relative c'' {
\override Tie #'after-line-breaking =
#my-callback
- c1 ~ \break c2 ~ c
+ c1 ~ \break
+ c2 ~ c
}
@end lilypond
@noindent
When applying this trick, the new @code{after-line-breaking} callback
-should also call the old one @code{after-line-breaking}, if there is
-one. For example, if using this with @code{Hairpin},
-@code{ly:hairpin::after-line-breaking} should also be called.
+should also call the old one, if such a default exists. For example,
+if using this with @code{Hairpin}, @code{ly:spanner::kill-zero-spanned-time}
+should also be called.
-@item Some objects cannot be changed with @code{\override} for
+@item
+Some objects cannot be changed with @code{\override} for
technical reasons. Examples of those are @code{NonMusicalPaperColumn}
and @code{PaperColumn}. They can be changed with the
@code{\overrideProperty} function, which works similar to @code{\once
@end itemize
+@node LilyPond Scheme interfaces
+@chapter LilyPond Scheme interfaces
+This chapter covers the various tools provided by LilyPond to help
+Scheme programmers get information into and out of the music streams.
-
+TODO -- figure out what goes in here and how to organize it