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.13.36"
@node Interfaces for programmers
@chapter Interfaces for programmers
@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.
+@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::
* Simple substitution functions::
* Intermediate substitution functions::
* Mathematics in functions::
-* Void functions::
* Functions without arguments::
+* Void functions::
@end menu
+
@node Music function syntax
@subsection Music function syntax
-The general syntax of a music function is:
+The general form for 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{music})
@end example
@noindent
where
@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
+@item @code{@var{argN}}
+@tab @var{n}th argument
-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}.
+@item @code{@var{typeN?}}
+@tab a scheme @emph{type predicate} for which @code{@var{argN}}
+must return @code{#t}.
-@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
+@item @code{@var{music}}
+@tab A music expression, optionally written in scheme, with any
+LilyPond code enclosed in hashed braces
+(@tie{}@w{@code{#@{@dots{}#@}}}@tie{}). Within LilyPond code
+blocks, use @code{$} to reference function arguments (eg.,
+@samp{$arg1}) or to start an inline scheme expression containing
+function arguments (eg., @w{@samp{$(cons arg1 arg2)}}).
-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.
+@end multitable
-@node Simple substitution functions
-@subsection Simple substitution functions
+@noindent
+For a list of available type predicates, see
+@ruser{Predefined type predicates}. User-defined type predicates
+are also allowed.
-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
-@example
-myFunction =
-#(define-music-function (parser location @var{var1})
- (@var{var1-type?})
- #@{
- @emph{... LilyPond input code with} @code{#$var1} @emph{for substition ...}
- #@})
-@end example
+@seealso
-Note that the special characters @code{#@{} and @code{#@}} surround the
-LilyPond music.
+Notation Reference:
+@ruser{Predefined type predicates}.
-@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
+Installed Files:
+@file{lily/music-scheme.cc},
+@file{scm/c++.scm},
+@file{scm/lily.scm}.
-For example, a function can be defined that simplifies
-setting the padding of a TextScript:
-@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 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
+@w{@code{(make-music @dots{})}}. With the @code{'void} property
+set to @code{#t}, the parser is told to actually disregard this
+returned music expression. Thus the important part of the void
+music function is the processing done by the function, not the
+music expression that is returned.
+
+@example
+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 Markup functions
@section Markup functions
@code{text example} string, and then it raises that Stencil by 0.5
staff space. This is a rather simple example; more complex examples
are in the rest
-of this section, and in @file{scm/@/define@/-markup@/-commands@/.scm}.
+of this section, and in @file{scm/define-markup-commands.scm}.
@node New markup command definition
@subsection New markup command definition
-New markup commands can be defined
-with the @code{define-markup-command} Scheme macro.
+This section discusses the definition of new markup commands.
+
+@menu
+* Markup command definition syntax::
+* On properties::
+* A complete example::
+* Adapting builtin commands::
+@end menu
+
+@node Markup command definition syntax
+@unnumberedsubsubsec Markup command definition syntax
+
+New markup commands can be defined using the
+@code{define-markup-command} Scheme macro, at top-level.
@lisp
(define-markup-command (@var{command-name} @var{layout} @var{props} @var{arg1} @var{arg2} ...)
- (@var{arg1-type?} @var{arg2-type?} ...)
+ (@var{arg1-type?} @var{arg2-type?} ...)
+ [ #:properties ((@var{property1} @var{default-value1})
+ ...) ]
..command body..)
@end lisp
The arguments are
-@table @var
-@item argi
-@var{i}th command argument
-@item argi-type?
-a type predicate for the i@var{th} argument
+@table @code
+@item @var{command-name}
+the markup command name
@item layout
-the @q{layout} definition
+the @q{layout} definition.
@item props
-a list of alists, containing all active properties.
+a list of associative lists, containing all active properties.
+@item @var{argi}
+@var{i}th command argument
+@item @var{argi-type?}
+a type predicate for the i@var{th} argument
@end table
-As a simple example, we show how to add a @code{\smallcaps} command,
-which selects a small caps font. Normally we could select the
-small caps font,
+If the command uses properties from the @code{props} arguments,
+the @code{#:properties} keyword can be used to specify which
+properties are used along with their default values.
-@example
-\markup @{ \override #'(font-shape . caps) Text-in-caps @}
-@end example
+Arguments are distinguished according to their type:
+@itemize
+@item a markup, corresponding to type predicate @code{markup?};
+@item a list of markups, corresponding to type predicate
+@code{markup-list?};
+@item any other scheme object, corresponding to type predicates such as
+@code{list?}, @code{number?}, @code{boolean?}, etc.
+@end itemize
-@noindent
-This selects the caps font by setting the @code{font-shape} property to
-@code{#'caps} for interpreting @code{Text-in-caps}.
+There is no limitation on the order of arguments (after the
+standard @code{layout} and @code{props} arguments). However,
+markup functions taking a markup as their last argument are
+somewhat special as you can apply them to a markup list, and the
+result is a markup list where the markup function (with the
+specified leading arguments) has been applied to every element of
+the original markup list.
-To make the above available as @code{\smallcaps} command, we must
-define a function using @code{define-markup-command}. The command should
-take a single argument of type @code{markup}. Therefore the start of the
-definition should read
+Since replicating the leading arguments for applying a markup
+function to a markup list is cheap mostly for Scheme arguments,
+you avoid performance pitfalls by just using Scheme arguments for
+the leading arguments of markup functions that take a markup as
+their last argument.
-@example
-(define-markup-command (smallcaps layout props argument) (markup?)
-@end example
+@node On properties
+@unnumberedsubsubsec On properties
-@noindent
+The @code{layout} and @code{props} arguments of markup commands bring a
+context for the markup interpretation: font size, line width, etc.
-What follows is the content of the command: we should interpret
-the @code{argument} as a markup, i.e.,
+The @code{layout} argument allows access to properties defined in
+@code{paper} blocks, using the @code{ly:output-def-lookup} function.
+For instance, the line width (the same as the one used in scores) is
+read using:
@example
-(interpret-markup layout @dots{} argument)
+(ly:output-def-lookup layout 'line-width)
@end example
-@noindent
-This interpretation should add @code{'(font-shape . caps)} to the active
-properties, so we substitute the following for the @dots{} in the
-above example:
+The @code{props} argument makes some properties accessible to markup
+commands. For instance, when a book title markup is interpreted, all
+the variables defined in the @code{\header} block are automatically
+added to @code{props}, so that the book title markup can access the book
+title, composer, etc. It is also a way to configure the behaviour of a
+markup command: for example, when a command uses font size during
+processing, the font size is read from @code{props} rather than having a
+@code{font-size} argument. The caller of a markup command may change
+the value of the font size property in order to change the behaviour.
+Use the @code{#:properties} keyword of @code{define-markup-command} to
+specify which properties shall be read from the @code{props} arguments.
-@example
-(cons (list '(font-shape . caps) ) props)
-@end example
+The example in next section illustrates how to access and override
+properties in a markup command.
-@noindent
-The variable @code{props} is a list of alists, and we prepend to it by
-cons'ing a list with the extra setting.
+@node A complete example
+@unnumberedsubsubsec A complete example
+The following example defines a markup command to draw a double box
+around a piece of text.
-Suppose that we are typesetting a recitative in an opera and
-we would like to define a command that will show character names in a
-custom manner. Names should be printed with small caps and moved a
-bit up and to the left. We will define a @code{\character} command
-which takes into account the necessary translation and uses the newly
-defined @code{\smallcaps} command:
+Firstly, we need to build an approximative result using markups.
+Consulting the @ruser{Text markup commands} shows us the @code{\box}
+command is useful:
-@example
-#(define-markup-command (character layout props name) (string?)
- "Print the character name in small caps, translated to the left and
- top. Syntax: \\character #\"name\""
+@lilypond[quote,verbatim,ragged-right]
+\markup \box \box HELLO
+@end lilypond
+
+Now, we consider that more padding between the text and the boxes is
+preferable. According to the @code{\box} documentation, this command
+uses a @code{box-padding} property, which defaults to 0.2. The
+documentation also mentions how to override it:
+
+@lilypond[quote,verbatim,ragged-right]
+\markup \box \override #'(box-padding . 0.6) \box A
+@end lilypond
+
+Then, the padding between the two boxes is considered too small, so we
+override it too:
+
+@lilypond[quote,verbatim,ragged-right]
+\markup \override #'(box-padding . 0.4) \box \override #'(box-padding . 0.6) \box A
+@end lilypond
+
+Repeating this lengthy markup would be painful. This is where a markup
+command is needed. Thus, we write a @code{double-box} markup command,
+taking one argument (the text). This draws the two boxes, with some
+padding.
+
+@lisp
+#(define-markup-command (double-box layout props text) (markup?)
+ "Draw a double box around text."
(interpret-markup layout props
- (markup #:hspace 0 #:translate (cons -3 1) #:smallcaps name)))
-@end example
+ (markup #:override '(box-padding . 0.4) #:box
+ #:override '(box-padding . 0.6) #:box text)))
+@end lisp
-There is one complication that needs explanation: texts above and below
-the staff are moved vertically to be at a certain distance (the
-@code{padding} property) from the staff and the notes. To make sure
-that this mechanism does not annihilate the vertical effect of our
-@code{#:translate}, we add an empty string (@code{#:hspace 0}) before the
-translated text. Now the @code{#:hspace 0} will be put above the notes,
-and the
-@code{name} is moved in relation to that empty string. The net effect is
-that the text is moved to the upper left.
+@code{text} is the name of the command argument, and @code{markup?} its
+type: it identifies it as a markup. The @code{interpret-markup}
+function is used in most of markup commands: it builds a stencil, using
+@code{layout}, @code{props}, and a markup. Here, this markup is built
+using the @code{markup} scheme macro, see @ref{Markup construction in Scheme}.
+The transformation from @code{\markup} expression to scheme
+markup expression is straight-forward.
-The final result is as follows:
+The new command can be used as follow:
@example
-@{
- c''^\markup \character #"Cleopatra"
- e'^\markup \character #"Giulio Cesare"
-@}
+\markup \double-box A
@end example
-@lilypond[quote,ragged-right]
-#(define-markup-command (smallcaps layout props str) (string?)
- "Print the string argument in small caps. Syntax: \\smallcaps #\"string\""
- (interpret-markup layout props
- (make-line-markup
- (map (lambda (s)
- (if (= (string-length s) 0)
- s
- (markup #:large (string-upcase (substring s 0 1))
- #:translate (cons -0.6 0)
- #:tiny (string-upcase (substring s 1)))))
- (string-split str #\Space)))))
-
-#(define-markup-command (character layout props name) (string?)
- "Print the character name in small caps, translated to the left and
- top. Syntax: \\character #\"name\""
+It would be nice to make the @code{double-box} command customizable:
+here, the @code{box-padding} values are hard coded, and cannot be
+changed by the user. Also, it would be better to distinguish the
+padding between the two boxes, from the padding between the inner box
+and the text. So we will introduce a new property,
+@code{inter-box-padding}, for the padding between the two boxes. The
+@code{box-padding} will be used for the inner padding. The new code is
+now as follows:
+
+@lisp
+#(define-markup-command (double-box layout props text) (markup?)
+ #:properties ((inter-box-padding 0.4)
+ (box-padding 0.6))
+ "Draw a double box around text."
(interpret-markup layout props
- (markup #:hspace 0 #:translate (cons -3 1) #:smallcaps name)))
+ (markup #:override `(box-padding . ,inter-box-padding) #:box
+ #:override `(box-padding . ,box-padding) #:box text)))
+@end lisp
-{
- c''^\markup \character #"Cleopatra" c'' c'' c''
- e'^\markup \character #"Giulio Cesare" e' e' e'
-}
-@end lilypond
+Here, the @code{#:properties} keyword is used so that the
+@code{inter-box-padding} and @code{box-padding} properties are read from
+the @code{props} argument, and default values are given to them if the
+properties are not defined.
-We have used the @code{caps} font shape, but suppose that our font
-does not have a small-caps variant. In that case we have to fake
-the small caps font by setting a string in uppercase with the
-first letter a little larger:
+Then, these values are used to override the @code{box-padding}
+properties used by the two @code{\box} commands. Note the backquote and
+the comma in the @code{\override} argument: they allow you to introduce
+a variable value into a literal expression.
-@example
-#(define-markup-command (smallcaps layout props str) (string?)
- "Print the string argument in small caps."
+Now, the command can be used in a markup, and the boxes padding be
+customized:
+
+@lilypond[quote,verbatim,ragged-right]
+#(define-markup-command (double-box layout props text) (markup?)
+ #:properties ((inter-box-padding 0.4)
+ (box-padding 0.6))
+ "Draw a double box around text."
(interpret-markup layout props
- (make-line-markup
- (map (lambda (s)
- (if (= (string-length s) 0)
- s
- (markup #:large (string-upcase (substring s 0 1))
- #:translate (cons -0.6 0)
- #:tiny (string-upcase (substring s 1)))))
- (string-split str #\Space)))))
-@end example
+ (markup #:override `(box-padding . ,inter-box-padding) #:box
+ #:override `(box-padding . ,box-padding) #:box text)))
-The @code{smallcaps} command first splits its string argument into
-tokens separated by spaces (@code{(string-split str #\Space)}); for
-each token, a markup is built with the first letter made large and
-upcased (@code{#:large (string-upcase (substring s 0 1))}), and a
-second markup built with the following letters made tiny and upcased
-(@code{#:tiny (string-upcase (substring s 1))}). As LilyPond
-introduces a space between markups on a line, the second markup is
-translated to the left (@code{#:translate (cons -0.6 0) ...}). Then,
-the markups built for each token are put in a line by
-@code{(make-line-markup ...)}. Finally, the resulting markup is passed
-to the @code{interpret-markup} function, with the @code{layout} and
-@code{props} arguments.
-
-Note: there is now an internal command @code{\smallCaps} which can
-be used to set text in small caps. See
-@ruser{Text markup commands}, for details.
+\markup \double-box A
+\markup \override #'(inter-box-padding . 0.8) \double-box A
+\markup \override #'(box-padding . 1.0) \double-box A
+@end lilypond
-@knownissues
+@node Adapting builtin commands
+@unnumberedsubsubsec Adapting builtin commands
-Currently, the available combinations of arguments (after the standard
-@var{layout} and @var{props} arguments) to a markup command defined with
-@code{define-markup-command} are limited as follows.
-
-@table @asis
-@item (no argument)
-@itemx @var{list}
-@itemx @var{markup}
-@itemx @var{markup markup}
-@itemx @var{scm}
-@itemx @var{scm markup}
-@itemx @var{scm scm}
-@itemx @var{scm scm markup}
-@itemx @var{scm scm markup markup}
-@itemx @var{scm markup markup}
-@itemx @var{scm scm scm}
-@end table
+A good way to start writing a new markup command, is to take example on
+a builtin one. Most of the markup commands provided with LilyPond can be
+found in file @file{scm/define-markup-commands.scm}.
-@noindent
-In the above table, @var{scm} represents native Scheme data types like
-@q{number} or @q{string}.
+For instance, we would like to adapt the @code{\draw-line} command, to
+draw a double line instead. The @code{\draw-line} command is defined as
+follow (documentation stripped):
-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
indented. The indent width is taken from the @code{props} argument.
@example
#(define-markup-list-command (paragraph layout props args) (markup-list?)
- (let ((indent (chain-assoc-get 'par-indent props 2)))
- (interpret-markup-list layout props
- (make-justified-lines-markup-list (cons (make-hspace-markup indent)
- args)))))
+ #:properties ((par-indent 2))
+ (interpret-markup-list layout props
+ (make-justified-lines-markup-list (cons (make-hspace-markup par-indent)
+ args))))
@end example
Besides the usual @code{layout} and @code{props} arguments, the
\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