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"
@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).
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
@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 command-name
+the markup command name
+@item layout
+the @q{layout} definition.
+@item props
+a list of associative lists, containing all active properties.
@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,
+If the command uses properties from the @var{props} arguments, the
+@code{#:properties} keyword can be used, to specify which properties are
+used, and 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
+@var{layout} and @var{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
(eq? (ly:grob-property grob 'staff-position) 0))
(set! (ly:grob-property grob 'transparent) #t)))
-\relative {
+\relative c' {
e4 g8 \applyOutput #'Voice #blanker b d2
}
@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