@ref{Scheme tutorial}.
@menu
-* Programmer interfaces for input::
+* Music functions::
+* Programmer interfaces::
+* Building complicated functions::
* Markup programmer interface::
* Contexts for programmers::
@end menu
-@node Programmer interfaces for input
-@section Programmer interfaces for input
+@node Music functions
+@section Music functions
-This section discusses how to create functions within LilyPond.
+This section discusses how to create music functions within LilyPond.
+
+@menu
+* Overview of music functions::
+* Simple substitution functions::
+* Paired substition functions::
+* Mathematics in functions::
+* Void functions::
+@end menu
+
+@node Overview of music functions
+@subsection Overview of music functions
+
+Making a funcion which substitutes a variable into LilyPond
+code is easy. The general form of these functions is
+
+@example
+function =
+#(define-music-function (parser location @var{var1} @var{var2}... )
+ (@var{var1-type?} @var{var2-type?}...)
+ #@{
+ @emph{...music...}
+ #@})
+@end example
+
+@noindent
+where
+
+@multitable @columnfractions .33 .66
+@item @var{argi} @tab @var{i}th variable
+@item @var{argi-type?} @tab type of variable
+@item @var{...music...} @tab normal LilyPond input, using
+ variables as @code{#$var1}.
+@end multitable
+
+There 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.
+
+@multitable @columnfractions .33 .66
+@headitem Input type @tab @var{argi-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
+
+The @code{parser} and @code{location} argument are mandatory,
+and are used in some advanced situations. The @code{parser}
+argument is used to access to the value of another LilyPond
+variable. The @code{location} argument
+is used to set the ``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.
+
+
+@node Simple substitution functions
+@subsection Simple substitution functions
+
+Here is a simple example,
+
+@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
+
+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
+
+Multiple variables may be used,
+
+@lilypond[quote,verbatim,ragged-right]
+tempoMark = #(define-music-function (parser location padding marktext)
+ (number? string?)
+#{
+ \once \override Score . RehearsalMark #'padding = $padding
+ \once \override Score . RehearsalMark #'no-spacing-rods = ##t
+ \mark \markup { \bold $marktext }
+#})
+
+\relative c'' {
+c2 e
+\tempoMark #3.0 #"Allegro"
+g c
+}
+@end lilypond
+
+
+@node Paired substition functions
+@subsection Paired substition 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.
+
+@quotation
+@example
+manualBeam =
+#(define-music-function (parser location beg-end)
+ (pair?)
+#@{
+ \once \override Beam #'positions = #$beg-end
+#@})
+
+\relative @{
+ \manualBeam #'(3 . 6) c8 d e f
+@}
+@end example
+@end quotation
+
+@noindent
+or
+
+@lilypond[quote,verbatim,ragged-right]
+manualBeam =
+#(define-music-function (parser location beg end)
+ (number? number?)
+#{
+ \once \override Beam #'positions = #(cons $beg $end)
+#})
+
+\relative {
+ \manualBeam #3 #6 c8 d e f
+}
+@end lilypond
+
+
+@node Mathematics in functions
+@subsection Mathematics in functions
+
+Music functions can involve Scheme programming in
+addition to simple substitution,
+
+@lilypond[quote,verbatim,ragged-right]
+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))) #})
+
+AltOff = {
+ \revert Stem #'length
+ \revert NoteHead #'font-size
+}
+
+{ c'2 \AltOn #0.5 c'4 c'
+ \AltOn #1.5 c' c' \AltOff c'2 }
+@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)
+ \override NoteHead #'font-size =
+ #$(inexact->exact (* (/ 6.0 (log 2.0)) (log mag)))
+ $music
+ \revert Stem #'length
+ \revert NoteHead #'font-size #})
+
+{ c'2 \withAlt #0.5 {c'4 c'}
+ \withAlt #1.5 {c' c'} c'2 }
+@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 which 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 Programmer interfaces
+@section Programmer interfaces
+
+This section contains information about mixing LilyPond
+and Scheme.
@menu
* Input variables and Scheme::
* Internal music representation::
-* Extending music syntax::
-* Manipulating music expressions::
-* Displaying music expressions::
-* Using LilyPond syntax inside Scheme::
@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
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
@example
#(define (nopc)
@internalsref{Music classes}.
@item
-C++ object: Each music object is represented by a C++ object. For
-technical reasons, different music objects may be represented by
-different C++ object types. For example, a note is @code{Event}
-object, while @code{\grace} creates a @code{Grace_music} object. We
-expect that distinctions between different C++ types will disappear
-in the future.
+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.
+@node Building complicated functions
+@section Building complicated functions
-@node Extending music syntax
-@subsection Extending music syntax
-
-@c TODO: rewrite example.
-@c The use of FUNC as example argument is rather confusing.
+This section explains how to gather the information necessary
+to create complicated music functions.
-The syntax of composite music expressions, like @code{\repeat},
-@code{\transpose}, and @code{\context} follows the general form of
-
-@example
-\@code{keyword} @var{non-music-arguments} @var{music-arguments}
-@end example
-
-Such syntax can also be defined as user code. To do this it is
-necessary to create a @emph{music function}. This is a specially marked
-Scheme function. For example, the music function @code{\applyMusic} applies
-a user-defined function to a music expression. Its syntax is
+@menu
+* Displaying music expressions::
+* Music properties::
+* Doubling a note with slurs (example)::
+* Adding articulation to notes (example)::
+@end menu
-@example
-\applyMusic #@var{func} @var{music}
-@end example
-A music function is created with @code{ly:make-music-function},
+@node Displaying music expressions
+@subsection Displaying music expressions
-@example
-(ly:make-music-function
-@end example
+@cindex internal storage
+@findex \displayMusic
+@findex \displayLilyMusic
-@code{\applyMusic} takes a Scheme function and a Music expression as
-arguments. This is encoded in its parameter list,
+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
-(list procedure? ly:music?)
+@{
+ \displayMusic @{ c'4\f @}
+@}
@end example
-The function itself takes another argument: an Input location
-object. That object is used to provide error messages with file names
-and line numbers. The definition is the second argument of
-@code{ly:make-music-function}. The body simply calls the function
+@noindent
+will display
@example
-(lambda (where func music)
- (func music))
+(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
-The above Scheme code only defines the functionality. The tag
-@code{\applyMusic} is selected by defining
+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
-applyMusic = #(ly:make-music-function
- (list procedure? ly:music?)
- (lambda (parser location func music)
- (func music)))
+lilypond file.ly >display.txt
@end example
-A @code{define-music-function} macro is introduced on top of
-@code{ly:make-music-function} to ease the definition of music
-functions:
+With a bit of reformatting, the above information is
+easier to read,
@example
-applyMusic = #(define-music-function (parser location func music)
- (procedure? ly:music?)
- (func music))
+(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
-Examples of the use of @code{\applyMusic} are in the next section.
+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.
-@seealso
-@file{ly/@/music@/-functions@/-init@/.ly}.
+@node Music properties
+@subsection Music properties
-@node Manipulating music expressions
-@subsection Manipulating music expressions
-
-Music objects and their properties can be accessed and manipulated
-directly through the @code{\applyMusic} mechanism.
-The syntax for @code{\applyMusic} is
+The @code{NoteEvent} object is the first object of the
+@code{'elements} property of @code{someNote}.
@example
-\applyMusic #@var{func} @var{music}
+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
-@noindent
-This means that the Scheme function @var{func} is called with
-@var{music} as its argument. The return value of @var{func} is the
-result of the entire expression. @var{func} may read and write music
-properties using the functions @code{ly:music-property} and
-@code{ly:music-set-property!}.
-
-An example is a function that reverses the order of elements in
-its argument,
-@lilypond[quote,verbatim,ragged-right]
-#(define (rev-music-1 m)
- (ly:music-set-property! m 'elements
- (reverse (ly:music-property m 'elements)))
- m)
-
-\applyMusic #rev-music-1 { c'4 d'4 }
-@end lilypond
-
-The use of such a function is very limited. The effect of this
-function is void when applied to an argument that does not have
-multiple children. The following function application has no effect
+The @code{display-scheme-music} function is the function used by
+@code{\displayMusic} to display the scheme representation of a music
+expression.
@example
-\applyMusic #rev-music-1 \grace @{ c4 d4 @}
+#(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
-@noindent
-In this case, @code{\grace} is stored as @internalsref{GraceMusic}, which
-has no @code{elements}, only a single @code{element}. Every generally
-applicable function for @code{\applyMusic} must -- like music expressions
-themselves -- be recursive.
-
-The following example is such a recursive function: It first extracts
-the @code{elements} of an expression, reverses them and puts them
-back. Then it recurses, both on @code{elements} and @code{element}
-children.
+Then the note pitch is accessed thourgh the @code{'pitch} property
+of the @code{NoteEvent} object,
@example
-#(define (reverse-music music)
- (let* ((elements (ly:music-property music 'elements))
- (child (ly:music-property music 'element))
- (reversed (reverse elements)))
-
- ; set children
- (ly:music-set-property! music 'elements reversed)
-
- ; recurse
- (if (ly:music? child) (reverse-music child))
- (map reverse-music reversed)
-
- music))
+#(display-scheme-music
+ (ly:music-property (first (ly:music-property someNote 'elements))
+ 'pitch))
+===>
+(ly:make-pitch 0 0 0)
@end example
-A slightly more elaborate example is in
-@inputfileref{input/@/test,reverse@/-music@/.ly}.
-
-Some of the input syntax is also implemented as recursive music
-functions. For example, the syntax for polyphony
-@example
-<<a \\ b>>
-@end example
+The note pitch can be changed by setting this 'pitch property,
-@noindent
-is actually implemented as a recursive function that replaces the
-above by the internal equivalent of
@example
-<< \context Voice = "1" @{ \voiceOne a @}
- \context Voice = "2" @{ \voiceTwo b @} >>
+#(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
-Other applications of @code{\applyMusic} are writing out repeats
-automatically (@inputfileref{input/@/test,unfold@/-all@/-repeats@/.ly}),
-saving keystrokes (@inputfileref{input/@/test,music@/-box@/.ly}) and
-exporting LilyPond input to other formats
-@c no @inputfileref{} here
-(eg. @file{input/@/no@/-notation/@/to@/-xml@/.ly}).
-
-@seealso
-@file{scm/@/music@/-functions@/.scm}, @file{scm/@/music@/-types@/.scm},
-@inputfileref{input/@/test,add@/-staccato@/.ly},
-@inputfileref{input/@/test,unfold@/-all@/-repeats@/.ly}, and
-@inputfileref{input/@/test,music@/-box@/.ly}.
+@node Doubling a note with slurs (example)
+@subsection Doubling a note with slurs (example)
-
-@node Displaying music expressions
-@subsection Displaying music expressions
-
-@cindex internal storage
-@cindex @code{\displayMusic}
-@cindex @code{\displayLilyMusic}
-
-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}
+Suppose we want to create a function which translates
+input like ``@code{a}'' into ``@code{a( a)}''. We begin
+by examining the internal representation of the music
+we want to end up with.
@example
-@{
- \displayMusic @{ c'4\f @}
-@}
+\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
-@noindent
-will display
+The bad news is that the @code{SlurEvent} expressions
+must be added ``inside'' the note (or more precisely,
+inside the @code{EventChord} expression).
+
+Now we examine the input,
@example
(make-music
'duration
(ly:make-duration 2 0 1 1)
'pitch
- (ly:make-pitch 0 0 0))
- (make-music
- 'AbsoluteDynamicEvent
- 'text
- "f")))))
+ (ly:make-pitch 0 5 0))))))
@end example
-Displaying a music expression in LilyPond notation can be
-done using the music function @code{\displayLilyMusic}. For 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
-@{
- \displayLilyMusic \transpose c a, @{ c e g a bes @}
-@}
+doubleSlur = #(def-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
-will display
-@example
-@{ a, cis e fis g @}
-@end example
+@node Adding articulation to notes (example)
+@subsection Adding articulation to notes (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.
+The easy way to add articulation to notes is to merge two music
+expressions into one context, as explained in
+@ref{Creating contexts}. However, suppose that we want to write
+a music function which does this.
+
+A @code{$variable} inside the @code{#@{...#@}} notation is like
+using a regular @code{\variable} in classical LilyPond
+notation. We know that
@example
-lilypond file.ly >display.txt
+@{ \music -. -> @}
@end example
+@noindent
+will not work in LilyPond. We could avoid this problem by attaching
+the articulation to a fake note,
-@node Using LilyPond syntax inside Scheme
-@subsection Using LilyPond syntax inside Scheme
+@example
+@{ << \music s1*0-.-> @}
+@end example
-Creating music expressions in Scheme can be tedious, as they are
-heavily nested and the resulting Scheme code is large. For some
-simple tasks this can be avoided by using common LilyPond syntax inside
-Scheme, with the dedicated @code{#@{ ... #@}} syntax.
+@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,
-The following two expressions give equivalent music expressions:
@example
-mynotes = @{ \override Stem #'thickness = #4
- @{ c'8 d' @} @}
-
-#(define mynotes #@{ \override Stem #'thickness = #4
- @{ c'8 d' @} #@})
+% 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
-The content of @code{#@{ ... #@}} is enclosed in an implicit @code{@{
-... @}} block, which is parsed. The resulting music expression, a
-@code{SequentialMusic} music object, is then returned and usable in Scheme.
+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.
-Arbitrary Scheme forms, including variables, can be used in @code{#@{ ... #@}}
-expressions with the @code{$} character (@code{$$} can be used to
-produce a single @code{$} character). This makes the creation of simple
-functions straightforward. In the following example, a function
-setting the TextScript's padding is defined:
+To build this function, we begin with
-@lilypond[quote,verbatim,ragged-right]
-#(use-modules (ice-9 optargs))
-#(define* (textpad padding #:optional once?)
- (ly:export ; this is necessary for using the expression
- ; directly inside a block
- (if once?
- #{ \once \override TextScript #'padding = #$padding #}
- #{ \override TextScript #'padding = #$padding #})))
-
- {
- c'^"1"
- #(textpad 3.0 #t) % only once
- c'^"2"
- c'^"3"
- #(textpad 5.0)
- c'^"4"
- c'^"5"
- }
-@end lilypond
+@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
-Here, the variable @code{padding} is a number; music expression
-variables may also be used in a similar fashion, as in the following
-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!)
-@lilypond[quote,verbatim,ragged-right]
-#(define (with-padding padding)
- (lambda (music)
- #{ \override TextScript #'padding = #$padding
- $music
- \revert TextScript #'padding #}))
+@example
+"Add a marcato..."
+@end example
-{
- c'^"1"
- \applyMusic #(with-padding 3) { c'^"2" c'^"3" }
- c'^"4"
-}
-@end lilypond
+@noindent
+is a description of what the function does. This is not strictly
+necessary, but just like clear variable names, it is good practice.
-The function created by @code{(with-padding 3)} adds @code{\override} and
-@code{\revert} statements around the music given as an argument, and returns
-this new expression. Thus, this example is equivalent to:
+@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{oteEventChord} expression and is a copy of @code{event-chord}. We
+add the marcato to its elements list property.
@example
-@{
- c'^"1"
- @{ \override TextScript #'padding = #3
- @{ c'^"2" c'^"3"@}
- \revert TextScript #'padding
- @}
- c'^"4"
-@}
+(set! place new-value)
@end example
-This function may also be defined as a music function:
+Here, what we want to set (the "place") is the "elements" property of
+@code{result-event-chord} expression
-@lilypond[quote,verbatim,ragged-right]
-withPadding =
- #(define-music-function (parser location padding music) (number? ly:music?)
- #{ \override TextScript #'padding = #$padding
- $music
- \revert TextScript #'padding #})
+@example
+(ly:music-property result-event-chord 'elements)
+@end example
-{
- c'^"1"
- \withPadding #3 { c'^"2" c'^"3"}
- c'^"4"
-}
-@end lilypond
+@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 elements property, with an extra item: the
+@code{MarcatoEvent} expression, which we copy from the
+@code{\displayMusic} output,
-Music functions can involve Scheme programming, in
-addition to simple substitution,
+@example
+(cons (make-music 'ArticulationEvent
+ 'articulation-type "marcato")
+ (ly:music-property result-event-chord 'elements))
+@end example
-@lilypond[quote,verbatim,ragged-right]
-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))) #})
+`@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 elements property is not important here.
-AltOff = {
- \revert Stem #'length
- \revert NoteHead #'font-size
-}
+Finally, once we have added the @code{MarcatoEvent} to its elements
+property, we can return @code{result-event-chord}, hence the last line of
+the function.
-{ c'2 \AltOn #0.5 c'4 c'
- \AltOn #1.5 c' c' \AltOff c'2 }
-@end lilypond
+Now we transform the @code{add-marcato} function into a music
+function,
-@noindent
-This example may be rewritten
+@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
-@lilypond[quote,verbatim,ragged-right]
-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)))
- $music
- \revert Stem #'length
- \revert NoteHead #'font-size #})
+We may verify that this music function works correctly,
-{ c'2 \withAlt #0.5 {c'4 c'}
- \withAlt #1.5 {c' c'} c'2 }
-@end lilypond
+@example
+\displayMusic \addMarcato c4
+@end example
@node Markup programmer interface
@section Markup programmer interface
-Markups are implemented as special Scheme functions. Markups are
-implemented as special Scheme functions which produce a
+Markups are implemented as special Scheme functions which produce a
Stencil object given a number of arguments.
@menu
* Markup construction in Scheme::
-* How markups work internally ::
+* How markups work internally::
* New markup command definition::
@end menu
@node Markup construction in Scheme
@subsection Markup construction in Scheme
-@cindex defining markup commands
+@cindex defining markup commands
The @code{markup} macro builds markup expressions in Scheme while
providing a LilyPond-like syntax. For example,
@multitable @columnfractions .3 .3
@item @b{LilyPond} @tab @b{Scheme}
@item @code{\markup markup1} @tab @code{(markup markup1)}
-@item @code{\markup @{ markup1 markup2 ... @}} @tab
+@item @code{\markup @{ markup1 markup2 ... @}} @tab
@code{(markup markup1 markup2 ... )}
@item @code{\command} @tab @code{#:command}
@item @code{\variable} @tab @code{variable}
useful when defining new markup commands (see
@ref{New markup command definition}).
+
@refbugs
-One can not feed the @code{#:line}, @code{#:center}, or
-@code{#:column}) commands with a variable or the result of a function
-call. Example:
+The markup-list argument of commands such as @code{#:line},
+@code{#:center}, and @code{#:column} cannot be a variable or
+the result of a function call.
@lisp
(markup #:line (function-that-returns-markups))
@end lisp
-@node How markups work internally
-@subsection How markups work internally
+@node How markups work internally
+@subsection How markups work internally
In a markup like
@item layout
the `layout' definition
@item props
-a list of alists, containing all active properties.
+a list of alists, containing all active properties.
@end table
As a simple example, we show how to add a @code{\smallcaps} command,
#(define-markup-command (character layout props name) (string?)
"Print the character name in small caps, translated to the left and
top. Syntax: \\character #\"name\""
- (interpret-markup layout props
+ (interpret-markup layout props
(markup #:hspace 0 #:translate (cons -3 1) #:smallcaps name)))
@end 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\""
- (interpret-markup layout props
+ (interpret-markup layout props
(markup #:hspace 0 #:translate (cons -3 1) #:smallcaps name)))
{
@node Contexts for programmers
@section Contexts for programmers
-
@menu
* Context evaluation::
* Running a function on all layout objects::
@subsection Context evaluation
@cindex calling code during interpreting
-@cindex @code{\applyContext}
+@findex \applyContext
Contexts can be modified during interpretation with Scheme code. The
syntax for this is
@cindex calling code on layout objects
-@cindex @code{\applyOutput}
+@findex \applyOutput
The most versatile way of tuning an object is @code{\applyOutput}. Its
syntax is
@example
-\applyOutput @var{proc}
+\applyOutput @var{context} @var{proc}
@end example
@noindent
where @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, with the following arguments:
+object found in the context @var{context}, with the following
+arguments:
@itemize @bullet
@item the layout object itself,
@item the context where the layout object was created, and