2.7 Callback functions

Properties (like thickness, direction, etc.) can be set at fixed values with \override, e.g.

\override Stem.thickness = #2.0

Properties can also be set to a Scheme procedure,

\override Stem.thickness = #(lambda (grob)
(if (= UP (ly:grob-property grob 'direction))
2.0
7.0))
c b a g b a g b

In this case, the procedure is executed as soon as the value of the property is requested during the formatting process.

Most of the typesetting engine is driven by such callbacks. Properties that typically use callbacks include

stencil

The printing routine, that constructs a drawing for the symbol

X-offset

The routine that sets the horizontal position

X-extent

The routine that computes the width of an object

The procedure always takes a single argument, being the grob.

That procedure may access the usual value of the property, by first calling the function that is the usual callback for that property, which can by found in the Internals Reference or the file ’define-grobs.scm’:

\relative c'' {
\override Flag #'X-offset = #(lambda (flag)
(let ((default (ly:flag::calc-x-offset flag)))
(* default 4.0)))
c4. d8 a4. g8
}

If routines with multiple arguments must be called, the current grob can be inserted with a grob closure. Here is a setting from AccidentalSuggestion,

`(X-offset .
,(ly:make-simple-closure
`(,+
,(ly:make-simple-closure
(list ly:self-alignment-interface::centered-on-x-parent))
,(ly:make-simple-closure
(list ly:self-alignment-interface::x-aligned-on-self)))))

In this example, both ly:self-alignment-interface::x-aligned-on-self and ly:self-alignment-interface::centered-on-x-parent are called with the grob as argument. The results are added with the + function. To ensure that this addition is properly executed, the whole thing is enclosed in ly:make-simple-closure.

In fact, using a single procedure as property value is equivalent to

(ly:make-simple-closure (ly:make-simple-closure (list proc)))

The inner ly:make-simple-closure supplies the grob as argument to proc, the outer ensures that result of the function is returned, rather than the simple-closure object.

From within a callback, the easiest method for evaluating a markup is to use grob-interpret-markup. For example:

my-callback = #(lambda (grob)
(grob-interpret-markup grob (markup "foo")))

Other languages: deutsch, español, français.