@c -*- coding: utf-8; mode: texinfo; -*- @c This file is part of lilypond.tely @ignore 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. @end ignore @c \version "2.12.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}. @menu * Music functions:: * Programmer interfaces:: * Building complicated functions:: * Markup programmer interface:: * Contexts for programmers:: * Scheme procedures as properties:: * Using Scheme code instead of \tweak:: * Difficult tweaks:: @end menu @node Music functions @section Music functions This section discusses how to create music functions within LilyPond. @menu * Overview of music functions:: * Simple substitution functions:: * Paired substitution functions:: * Mathematics in functions:: * Void functions:: * Functions without arguments:: * Overview of available music functions:: @end menu @node Overview of music functions @subsection Overview of music functions Making a function 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{vari}... ) (@var{var1-type?} @var{var2-type?}...@var{vari-type?}...) #@{ @emph{...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. @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{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 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. @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] tempoPadded = #(define-music-function (parser location padding tempotext) (number? string?) #{ \once \override Score.MetronomeMark #'padding = $padding \tempo \markup { \bold $tempotext } #}) \relative c'' { \tempo \markup { "Low tempo" } c4 d e f g1 \tempoPadded #4.0 #"High tempo" g4 f e d c1 } @end lilypond @node Paired substitution functions @subsection Paired 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. @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 Functions without arguments @subsection Functions without arguments In most cases a function without arguments should be written with an variable, @example dolce = \markup@{ \italic \bold dolce @} @end example However, in rare cases it may be useful to create a music function without arguments, @example displayBarNum = #(define-music-function (parser location) () (if (eq? #t (ly:get-option 'display-bar-numbers)) #@{ \once \override Score.BarNumber #'break-visibility = ##f #@} #@{#@})) @end example To actually display bar numbers where this function is called, invoke @command{lilypond} with @example lilypond -d display-bar-numbers FILENAME.ly @end example @node Overview of available music functions @subsection Overview of available music functions @c fixme ; this should be move somewhere else? The following commands are music functions @include identifiers.tely @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 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 @example ... @{ #(ly:export (make-sequential-music (list newLa))) @} @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) (ly:set-option 'point-and-click #f)) ... #(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 is in the internals manual, 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 '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 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@{ 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 @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 @{ \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 elements list property. @example (set! place new-value) @end example Here, what we want to set (the @q{place}) is the @q{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 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 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 @end example @node Markup programmer interface @section Markup programmer interface 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:: * New markup command definition:: * New markup list command definition:: @end menu @node Markup construction in Scheme @subsection Markup construction in Scheme @cindex defining markup commands The @code{markup} macro builds markup expressions in Scheme while providing a LilyPond-like syntax. For example, @example (markup #:column (#:line (#:bold #:italic "hello" #:raise 0.4 "world") #:larger #:line ("foo" "bar" "baz"))) @end example @noindent is equivalent to: @example \markup \column @{ \line @{ \bold \italic "hello" \raise #0.4 "world" @} \larger \line @{ foo bar baz @} @} @end example @noindent This example demonstrates the main translation rules between regular LilyPond markup syntax and Scheme markup syntax. @quotation @multitable @columnfractions .3 .3 @item @b{LilyPond} @tab @b{Scheme} @item @code{\markup markup1} @tab @code{(markup markup1)} @item @code{\markup @{ markup1 markup2 ... @}} @tab @code{(markup markup1 markup2 ... )} @item @code{\command} @tab @code{#:command} @item @code{\variable} @tab @code{variable} @item @code{\center-column @{ ... @}} @tab @code{#:center-column ( ... )} @item @code{string} @tab @code{"string"} @item @code{#scheme-arg} @tab @code{scheme-arg} @end multitable @end quotation The whole Scheme language is accessible inside the @code{markup} macro. For example, You may use function calls inside @code{markup} in order to manipulate character strings. This is useful when defining new markup commands (see @ref{New markup command definition}). @knownissues 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 @noindent is invalid. One should use the @code{make-line-markup}, @code{make-center-markup}, or @code{make-column-markup} functions instead, @lisp (markup (make-line-markup (function-that-returns-markups))) @end lisp @node How markups work internally @subsection How markups work internally In a markup like @example \raise #0.5 "text example" @end example @noindent @code{\raise} is actually represented by the @code{raise-markup} function. The markup expression is stored as @example (list raise-markup 0.5 (list simple-markup "text example")) @end example When the markup is converted to printable objects (Stencils), the @code{raise-markup} function is called as @example (apply raise-markup @var{\layout object} @var{list of property alists} 0.5 @var{the "text example" markup}) @end example The @code{raise-markup} function first creates the stencil for the @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}. @node New markup command definition @subsection New markup command definition New markup commands can be defined with the @code{define-markup-command} Scheme macro. @lisp (define-markup-command (@var{command-name} @var{layout} @var{props} @var{arg1} @var{arg2} ...) (@var{arg1-type?} @var{arg2-type?} ...) ..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 @item layout the @q{layout} definition @item props a list of alists, containing all active properties. @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, @example \markup @{ \override #'(font-shape . caps) Text-in-caps @} @end example @noindent This selects the caps font by setting the @code{font-shape} property to @code{#'caps} for interpreting @code{Text-in-caps}. 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 @example (define-markup-command (smallcaps layout props argument) (markup?) @end example @noindent What follows is the content of the command: we should interpret the @code{argument} as a markup, i.e., @example (interpret-markup layout @dots{} argument) @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: @example (cons (list '(font-shape . caps) ) props) @end example @noindent The variable @code{props} is a list of alists, and we prepend to it by cons'ing a list with the extra setting. 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 to the left and top. We will define a @code{\character} command which takes into account the necessary translation and uses the newly defined @code{\smallcaps} command: @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 (markup #:hspace 0 #:translate (cons -3 1) #:smallcaps name))) @end example 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. The final result is as follows: @example @{ c''^\markup \character #"Cleopatra" e'^\markup \character #"Giulio Cesare" @} @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\"" (interpret-markup layout props (markup #:hspace 0 #:translate (cons -3 1) #:smallcaps name))) { c''^\markup \character #"Cleopatra" c'' c'' c'' e'^\markup \character #"Giulio Cesare" e' e' e' } @end lilypond 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 upcase with the first letter a little larger: @example #(define-markup-command (smallcaps layout props str) (string?) "Print the string argument in small caps." (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 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 @ref{Text markup commands}, for details. @knownissues 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 @noindent In the above table, @var{scm} represents native Scheme data types like @q{number} or @q{string}. As an example, it is not possible to use a markup command @code{foo} with four arguments defined as @example #(define-markup-command (foo layout props num1 str1 num2 str2) (number? string? number? string?) ...) @end example @noindent If you apply it as, say, @example \markup \foo #1 #"bar" #2 #"baz" @end example @cindex Scheme signature @cindex signature, Scheme @noindent @command{lilypond} complains that it cannot parse @code{foo} due to its unknown Scheme signature. @node New markup list command definition @subsection New markup list command definition Markup list commands are defined with the @code{define-markup-list-command} Scheme macro, which is similar to the @code{define-markup-command} macro described in @ref{New markup command definition}, except that where the latter returns a single stencil, the former returns a list stencils. In the following example, a @code{\paragraph} markup list command is defined, which returns a list of justified lines, the first one being 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))))) @end example Besides the usual @code{layout} and @code{props} arguments, the @code{paragraph} markup list command takes a markup list argument, named @code{args}. The predicate for markup lists is @code{markup-list?}. 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 @code{make-justified-lines-markup-list} function, which is related to the @code{\justified-lines} built-in markup list command. An horizontal space is added at the beginning using the @code{make-hspace-markup} function. Finally, the markup list is interpreted using the @code{interpret-markup-list} function. This new markup list command can be used as follows: @example \markuplines @{ \paragraph @{ The art of music typography is called \italic @{(plate) engraving.@} The term derives from the traditional process of music printing. Just a few decades ago, sheet music was made by cutting and stamping the music into a zinc or pewter plate in mirror image. @} \override-lines #'(par-indent . 4) \paragraph @{ The plate would be inked, the depressions caused by the cutting and stamping would hold ink. An image was formed by pressing paper to the plate. The stamping and cutting was completely done by hand. @} @} @end example @node Contexts for programmers @section Contexts for programmers @menu * Context evaluation:: * Running a function on all layout objects:: @end menu @node Context evaluation @subsection Context evaluation @cindex calling code during interpreting @funindex \applyContext Contexts can be modified during interpretation with Scheme code. The syntax for this is @example \applyContext @var{function} @end example @var{function} should be a Scheme function taking a single argument, being the context to apply it to. The following code will print the current bar number on the standard output during the compile: @example \applyContext #(lambda (x) (format #t "\nWe were called in barnumber ~a.\n" (ly:context-property x 'currentBarNumber))) @end example @node Running a function on all layout objects @subsection Running a function on all layout objects @cindex calling code on layout objects @funindex \applyOutput The most versatile way of tuning an object is @code{\applyOutput}. Its syntax is @example \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 @var{context}, with the following arguments: @itemize @item the layout object itself, @item the context where the layout object was created, and @item the context where @code{\applyOutput} is processed. @end itemize 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. Here is a function to use for @code{\applyOutput}; it blanks note-heads on the center-line: @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)) (set! (ly:grob-property grob 'transparent) #t))) \relative { e4 g8 \applyOutput #'Voice #blanker b d2 } @end lilypond @node Scheme procedures as properties @section Scheme procedures as properties Properties (like thickness, direction, etc.) can be set at fixed values with \override, e.g. @example \override Stem #'thickness = #2.0 @end example Properties can also be set to a Scheme procedure, @lilypond[fragment,verbatim,quote,relative=2] \override Stem #'thickness = #(lambda (grob) (if (= UP (ly:grob-property grob 'direction)) 2.0 7.0)) c b a g b a g b @end lilypond @noindent In this case, the procedure is executed as soon as the value of the property is requested during the formatting process. Most of the typesetting engine is driven by such callbacks. Properties that typically use callbacks include @table @code @item stencil The printing routine, that constructs a drawing for the symbol @item X-offset The routine that sets the horizontal position @item X-extent The routine that computes the width of an object @end table The procedure always takes a single argument, being the grob. If routines with multiple arguments must be called, the current grob can be inserted with a grob closure. Here is a setting from @code{AccidentalSuggestion}, @example (X-offset . ,(ly:make-simple-closure `(,+ ,(ly:make-simple-closure (list ly:self-alignment-interface::centered-on-x-parent)) ,(ly:make-simple-closure (list ly:self-alignment-interface::x-aligned-on-self))))) @end example @noindent In this example, both @code{ly:self-alignment-interface::x-aligned-on-self} and @code{ly:self-alignment-interface::centered-on-x-parent} are called with the grob as argument. The results are added with the @code{+} function. To ensure that this addition is properly executed, the whole thing is enclosed in @code{ly:make-simple-closure}. In fact, using a single procedure as property value is equivalent to @example (ly:make-simple-closure (ly:make-simple-closure (list @var{proc}))) @end example @noindent The inner @code{ly:make-simple-closure} supplies the grob as argument to @var{proc}, the outer ensures that result of the function is returned, rather than the @code{simple-closure} object. @node Using Scheme code instead of \tweak @section Using Scheme code instead of @code{\tweak} The main disadvantage of @code{\tweak} is its syntactical inflexibility. For example, the following produces a syntax error. @example F = \tweak #'font-size #-3 -\flageolet \relative c'' @{ c4^\F c4_\F @} @end example @noindent With other words, @code{\tweak} doesn't behave like an articulation regarding the syntax; in particular, it can't be attached with @code{^} and @code{_}. Using Scheme, this problem can be circumvented. The route to the result is given in @ref{Adding articulation to notes (example)}, especially how to use @code{\displayMusic} as a helping guide. @example F = #(let ((m (make-music 'ArticulationEvent 'articulation-type "flageolet"))) (set! (ly:music-property m 'tweaks) (acons 'font-size -3 (ly:music-property m 'tweaks))) m) \relative c'' @{ c4^\F c4_\F @} @end example @noindent Here, the @code{tweaks} properties of the flageolet object @code{m} (created with @code{make-music}) are extracted with @code{ly:music-property}, a new key-value pair to change the font size is prepended to the property list with the @code{acons} Scheme function, and the result is finally written back with @code{set!}. The last element of the @code{let} block is the return value, @code{m} itself. @node Difficult tweaks @section Difficult tweaks There are a few classes of difficult adjustments. @itemize @item One type of difficult adjustment is the appearance of spanner objects, such as slur and tie. Initially, only one of these objects is created, and they can be adjusted with the normal mechanism. However, in some cases the spanners cross line breaks. If this happens, these objects are cloned. A separate object is created for every system that it is in. These are clones of the original object and inherit all properties, including @code{\override}s. In other words, an @code{\override} always affects all pieces of a broken spanner. To change only one part of a spanner at a line break, it is necessary to hook into the formatting process. The @code{after-line-breaking} callback contains the Scheme procedure that is called after the line breaks have been determined, and layout objects have been split over different systems. In the following example, we define a procedure @code{my-callback}. This procedure @itemize @item determines if we have been split across line breaks @item if yes, retrieves all the split objects @item checks if we are the last of the split objects @item if yes, it sets @code{extra-offset}. @end itemize This procedure is installed into @rinternals{Tie}, so the last part of the broken tie is translated up. @lilypond[quote,verbatim,ragged-right] #(define (my-callback 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 (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 } @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. @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 \override}, but uses a different syntax. @example \overrideProperty #"Score.NonMusicalPaperColumn" % Grob name #'line-break-system-details % Property name #'((next-padding . 20)) % Value @end example Note, however, that @code{\override}, applied to @code{NonMusicalPaperColumn} and @code{PaperColumn}, still works as expected within @code{\context} blocks. @end itemize