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.15.17"
@node Interfaces for programmers
@chapter Interfaces for programmers
@ref{Scheme tutorial}.
@menu
+* Lilypond code blocks::
+* Scheme functions::
* Music functions::
+* Event functions::
* Markup functions::
* Contexts for programmers::
* Callback functions::
* Difficult tweaks::
@end menu
+@node Lilypond code blocks
+@section Lilypond code blocks
+
+Lilypond code blocks look like
+@example
+ #@{ @var{Lilypond code} #@}
+@end example
+They can be used anywhere where you can write Scheme code: the Scheme
+reader actually is changed for accommodating LilyPond code blocks. When
+the LilyPond code block is being read, it is parsed superficially and
+replaced by a call to the LilyPond @code{parser} which is executed at
+runtime to interpret the LilyPond code block.
+
+The point of the superficial parsing is the interpretation of @code{$}
+signs which can be used for splicing in expressions from the surrounding
+lexical Scheme context (like @code{let} variables and function
+parameters). @code{$} can be used in the following ways:
+
+@table @code
+@item $$
+just passes a single @code{$} to the LilyPond parser.
+@item $@var{form}
+will evaluate the Scheme form at runtime and splice its value as an
+identifier @code{\form} into the LilyPond parser. Depending on the
+value type, it may be interpreted as several different syntactic
+entities.
+@item #$@var{form}
+will evaluate the Scheme form at runtime and splice its value as a
+Scheme expression into the LilyPond parser.
+@item #@var{form}
+Forms in Scheme expressions started with @code{#} are read and parsed
+recursively for @code{$} signs. Those are treated as follows:
+@item #@dots{}$@var{variable}
+splices the value of the variable into the surrounding expression.
+@item #@dots{}($ @var{form} @dots{})
+splices the value of the form into the surrounding expression. As
+opposed to a LilyPond level @code{$@var{form}}, you need to separate the
+form with a blank, making @code{$} be recognizable as a separate Scheme
+symbol.
+@end table
+
+A LilyPond code block may contain anything that you can use on the right
+side of an assignment. In addition, an empty LilyPond block corresponds
+to a void music expression, and a LilyPond block containing multiple
+music events gets turned into a sequential music expression.
+
+@node Scheme functions
+@section Scheme functions
+@cindex Scheme functions (LilyPond syntax)
+
+@emph{Scheme functions} are Scheme procedures that can create Scheme
+expressions from input written in LilyPond syntax. They can be called
+in pretty much all places where using @code{#} for specifying a value in
+Scheme syntax is allowed. While Scheme has functions of its own, this
+chapter is concerned with @emph{syntactic} functions, functions that
+receive arguments specified in LilyPond syntax.
+
+@menu
+* Scheme function definitions::
+* Scheme function usage::
+* Void scheme functions::
+@end menu
+
+@node Scheme function definitions
+@subsection Scheme function definitions
+@funindex define-scheme-function
+
+The general form for defining scheme functions is:
+
+@example
+function =
+#(define-scheme-function
+ (parser location @var{arg1} @var{arg2} @dots{})
+ (@var{type1?} @var{type2?} @dots{})
+ @var{body})
+@end example
+
+@noindent
+where
+
+@multitable @columnfractions .33 .66
+@item @code{parser}
+@tab needs to be literally @code{parser} in order to give LilyPond code
+blocks (@code{#@{}@dots{}@code{#@}}) access to the parser.
+
+@item @code{@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. There is also a special form
+@code{(@emph{predicate?} @emph{default})} for specifying optional
+arguments. If the actual argument is missing when the function is being
+called, the default value is substituted instead. Default values are
+evaluated at definition time (including LilyPond code blocks!), so if
+you need a default calculated at runtime, instead write a special value
+you can easily recognize. If you write the predicate in parentheses but
+don't follow it with a default value, @code{#f} is used as the default.
+Default values are not verified with @emph{predicate?} at either
+definition or run time: it is your responsibility to deal with the
+values you specify. Default values that happen to be music expressions
+are copied while setting @code{origin} to the @code{location} parameter.
+
+@item @code{@var{body}}
+@tab A sequence of Scheme forms evaluated in order, the last one being
+used as the return value of the scheme function. It may contain
+LilyPond code blocks enclosed in hashed braces
+(@tie{}@w{@code{#@{@dots{}#@}}}@tie{}), like described in @ref{Lilypond
+code blocks}. 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)}}). If your function returns a music expression, it is cloned and
+given the correct @code{origin}.
+@end multitable
+
+@noindent
+Some type predicates are specially handled by the parser since it
+can't recognize the arguments reliably otherwise. Currently these are
+@code{ly:pitch?} and @code{ly:duration?}.
+
+Suitability of arguments for all other predicates is determined by
+actually calling the predicate after Lilypond has already converted
+them into a Scheme expression. As a consequence, the argument can be
+specified in Scheme syntax if desired (introduced with @code{#} or as
+the result of calling a scheme function), but Lilypond will also
+convert a number of Lilypond constructs into Scheme before actually
+checking the predicate on them. Currently, those include music,
+simple strings (with or without quotes), full markups and markup
+lists, score, book, bookpart, context definition and output definition
+blocks.
+
+For some kinds of expression (like most music not enclosed in braces)
+Lilypond needs to look further than the expression itself in order to
+determine its end. When such an expression is considered for an
+optional argument by evaluating its predicate, Lilypond can't ``back
+up'' when it decides the expression does not fit the parameter, and
+complains. So in some contexts involving optional arguments, you may
+need extra braces to make them acceptable to Lilypond.
+
+This also applies for music arguments preceding @code{ly:duration?}
+arguments. It may also affect the last argument of a scheme function
+that is used as the last part of another expression, since otherwise
+Lilypond won't know whether following postevents or durations apply to
+the argument of the Scheme function, or to the containing music
+expression.
+
+For a list of available type predicates, see
+@ruser{Predefined type predicates}.
+
+@seealso
+
+Notation Reference:
+@ruser{Predefined type predicates}.
+
+Installed Files:
+@file{lily/music-scheme.cc},
+@file{scm/c++.scm},
+@file{scm/lily.scm}.
+
+@node Scheme function usage
+@subsection Scheme function usage
+
+Scheme functions can be called pretty much anywhere where a Scheme
+expression starting with @code{#} can be written. You call a scheme
+function by writing its name preceded by @code{\}, followed by its
+arguments. The last argument can't be an optional argument. If there
+are several optional arguments in a row, they are filled with values
+left to right. Once an optional argument can't match input, it and all
+immediately following optional arguments are replaced with their default
+values, and the matching continues with the next non-optional argument.
+
+Apart from places where a Scheme value is required, there are a few
+places where @code{#} expressions are currently accepted and evaluated
+for their side effects but otherwise ignored. Mostly those are the
+places where an assignment would be acceptable as well.
+
+Since it is a bad idea to return values that can be misinterpreted in
+some context, you should use normal scheme functions only for those
+cases where you always return a useful value, and use void scheme
+functions (@pxref{Void scheme functions}) otherwise.
+
+@node Void scheme functions
+@subsection Void scheme functions
+@funindex define-void-function
+@funindex \void
+
+Sometimes a procedure is executed in order to perform an action rather
+than return a value. Some programming languages (like C and Scheme)
+use functions for either concept and just discard the returned value
+(usually by allowing any expression to act as statement, ignoring the
+result). This is clever but error-prone: most C compilers nowadays
+offer warnings for various non-``void'' expressions being discarded.
+For many functions executing an action, the Scheme standards declare
+the return value to be unspecified. Lilypond's Scheme interpreter
+Guile has a unique ``unspecified'' value that it usually (such when
+using @code{set!} directly on a variable) but unfortunately not
+consistently returns in such cases.
+
+Defining a Lilypond function with @code{define-void-function} makes
+sure that this special value (the only value satisfying the predicate
+@code{void?}) will be returned.
+
+@example
+noPointAndClick =
+#(define-void-function
+ (parser location)
+ ()
+ (ly:set-option 'point-and-click #f))
+...
+\noPointAndClick % disable point and click
+@end example
+
+If you want to evaluate an expression only for its side-effect and
+don't want any value it may return interpreted, you can do so by
+prefixing it with @code{\void}:
+
+@example
+\void #(hashq-set! some-table some-key some-value)
+@end example
+
+That way, you can be sure that Lilypond will not assign meaning to the
+returned value regardless of where it encounters it. This will also
+work for music functions such as @code{\displayMusic}.
@node Music functions
@section Music functions
-Music functions are scheme functions that are used to
-automatically create music expressions. They can be used to
-greatly simplify the input file.
+@cindex music functions
+
+@emph{Music functions} are Scheme procedures that can create music
+expressions automatically, and can be used to greatly simplify the
+input file.
@menu
-* Music function syntax::
+* Music function definitions::
+* Music function usage::
* Simple substitution functions::
* Intermediate substitution functions::
* Mathematics in functions::
-* Void functions::
* Functions without arguments::
+* Void music functions::
@end menu
-@node Music function syntax
-@subsection Music function syntax
-The general syntax of a music function is:
+@node Music function definitions
+@subsection Music function definitions
+@cindex defining music functions
+@funindex define-music-function
+
+The general form for defining music functions is:
@example
-myFunction =
-#(define-music-function (parser location @var{var_1} @var{var_2}...@var{var_n})
- (@var{var_1-type?} @var{var_2-type?}...@var{var_n-type?})
- @var{...valid music expression...})
+function =
+#(define-music-function
+ (parser location @var{arg1} @var{arg2} @dots{})
+ (@var{type1?} @var{type2?} @dots{})
+ @var{body})
@end example
@noindent
-where
+quite in analogy to @ref{Scheme function definitions}. More often than
+not, @var{body} will be a @ref{Lilypond code blocks, Lilypond code block}.
-@multitable @columnfractions .33 .66
-@item @var{var_i} @tab @var{i}th variable
-@item @var{var_i-type?} @tab type of @var{i}th variable
-@item @var{...valid music expression...} @tab expression that returns
-valid music, generally in the form of a Scheme expression. There is
-also special syntax that allows LilyPond input code in this music
-expression.
-@end multitable
+For a list of available type predicates, see
+@ruser{Predefined type predicates}.
-The variable type checkers are scheme procedures that will return
-@code{#t} if a variable is of a given type. Some common types
-are shown in the table below. Other types can be found in the files
-@file{lily/music-scheme.cc} and @file{scm/c++.scm}.
+@seealso
-@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
+Notation Reference:
+@ruser{Predefined type predicates}.
-The @code{parser} and @code{location} arguments are mandatory.
-The @code{parser} argument is used in the body of the function
-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.
+Installed Files:
+@file{lily/music-scheme.cc},
+@file{scm/c++.scm},
+@file{scm/lily.scm}.
-@node Simple substitution functions
-@subsection Simple substitution functions
-A simple substitution function is a music function whose output music
-expression is written in LilyPond code, but with an input variable
-substituted into the LilyPond code. The general form of these functions is
+@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.
+@itemize
+@item
+At top level in a music expression. There are no special restrictions
+on the argument list.
+
+@item
+As a post-event, explicitly started with a direction indicator (one of
+@code{-}, @code{^}, @w{and @code{_}}). All trailing arguments of the
+music function with the predicate @code{ly:music?} will get parsed also
+as post-events (if the last argument is a scheme function, this will
+hold for trailing @code{ly:music?} arguments of the scheme function
+instead). Note that returning a post-event will be acceptable for music
+functions called as normal music, leading to a result roughly equivalent
+to
@example
-myFunction =
-#(define-music-function (parser location @var{var1})
- (@var{var1-type?})
- #@{
- @emph{... LilyPond input code with} @code{#$var1} @emph{for substition ...}
- #@})
+s 1*0-\fun
@end example
-Note that the special characters @code{#@{} and @code{#@}} surround the
-LilyPond music.
-
-@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
+@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
-For example, a function can be defined that simplifies
-setting the padding of a TextScript:
+@noindent
+The special rules for trailing arguments make it possible to write
+polymorphic functions like @code{\tweak} that can be applied to
+different constructs.
-@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
+@node Simple substitution functions
+@subsection Simple substitution functions
-In addition to numbers, we can use music expressions such
-as notes for arguments to music functions:
+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}.
-@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
- #})
-@end lilypond
@node Intermediate substitution functions
@subsection Intermediate substitution functions
-Slightly more complicated than simple substitution function,
-intermediate substitution functions involve a mix of Scheme code and
-LilyPond code in the music expression to be
-returned.
+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 @code{cons cell} in Scheme).
+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
Alternatively, the numbers making up the pair can be
passed as separate arguments, and the Scheme code
@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 Void music functions
+@subsection Void music functions
+
+A music function must return a music expression. If you want to
+execute a function only for its side effect, you should use
+@code{define-void-function}. But there may be cases where you
+sometimes want to produce a music expression, and sometimes not (like
+in the previous example). Returning a @code{void} music expression
+via @code{#@{ #@}} will achieve that.
+
+@node Event functions
+@section Event functions
+@funindex define-event-function
+@cindex event functions
+
+To use a music function in the place of an event, you need to write a
+direction indicator before it. But sometimes, this does not quite match
+the syntax of constructs you want to replace. For example, if you want
+to write dynamics commands, those are usually attached without direction
+indicator, like @code{c'\pp}. Here is a way to write arbitrary
+dynamics:
+@lilypond[quote,verbatim,raggedright]
+dyn=#(define-event-function (parser location arg) (markup?)
+ (make-dynamic-script arg))
+\relative c' { c\dyn pfsss }
+@end lilypond
+You could do the same using a music function, but then you always would
+have to write a direction indicator before calling it, like
+@code{@w{c-\dyn pfsss}}.
+
@node Markup functions
@section Markup functions
@noindent
is equivalent to:
@example
-\markup \column @{ \line @{ \bold \italic "hello" \raise #0.4 "world" @}
- \larger \line @{ foo bar baz @} @}
+#@{ \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.
+LilyPond markup syntax and Scheme markup syntax. Using @code{#@{
+@dots{} #@}} for entering in LilyPond syntax will often be most
+convenient, but we explain how to use the @code{markup} macro to get a
+Scheme-only solution.
@quotation
@multitable @columnfractions .3 .3
@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
+
+or, equivalently
+
+@lisp
+#(define-markup-command (double-box layout props text) (markup?)
+ "Draw a double box around text."
+ (interpret-markup layout props
+ (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. In the second case, 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\""
+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
- (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\""
+ #@{\markup \override #`(box-padding . ,$inter-box-padding) \box
+ \override #`(box-padding . ,$box-padding) \box
+ @{ $text @} #@}))
+@end lisp
+
+Again, the equivalent version using the markup macro would be:
+
+@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):
-As an example, it is not possible to use a markup command @code{foo} with
-four arguments defined as
+@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
-@example
-#(define-markup-command (foo layout props
- num1 str1 num2 str2)
- (number? string? number? string?)
- ...)
-@end example
+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.
-@noindent
-If you apply it as, say,
+@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
-@example
-\markup \foo #1 #"bar" #2 #"baz"
-@end example
+Then, a property for setting the gap between two lines is added, called
+@code{line-gap}, defaulting e.g. to 0.6:
-@cindex Scheme signature
-@cindex signature, Scheme
-@noindent
-@command{lilypond} complains that it cannot parse @code{foo} due to its
-unknown Scheme signature.
+@lisp
+(define-markup-command (draw-double-line layout props dest)
+ (number-pair?)
+ #:properties ((thickness 1)
+ (line-gap 0.6))
+ "..documentation.."
+ ...
+@end lisp
+
+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
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?)
+ #:properties ((par-indent 2))
+ (interpret-markup-list layout props
+ #@{\markuplist \justified-lines @{ \hspace #$par-indent $args @} #@}))
+@end example
+
+
+The version using just Scheme is more complex:
@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
-@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
-@code{make-hspace-markup} function. Finally, the markup list is
+list of justified lines is made using the built-in markup list command
+@code{\justified-lines}, which is related to the
+@code{make-justified-lines-markup-list} function. A
+horizontal space is added at the beginning using @code{\hspace} (or 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 @{
+\markuplist @{
\paragraph @{
The art of music typography is called \italic @{(plate) engraving.@}
The term derives from the traditional process of music printing.
\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
@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:
+
+@example
+my-callback = #(lambda (grob)
+ (grob-interpret-markup grob (markup "foo")))
+@end example
@node Inline Scheme code
@section Inline Scheme code
@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