]> git.donarmstrong.com Git - lilypond.git/blob - Documentation/user/programming-interface.itely
2004-11-10 Andreas Scherer <andreas_mutopia@freenet.de>
[lilypond.git] / Documentation / user / programming-interface.itely
1 @c -*- coding: latin-1; mode: texinfo; -*-
2 @node Interfaces for programmers
3 @chapter Interfaces for programmers
4
5
6
7 @menu
8 * Programmer interfaces for input ::  
9 * Markup programmer interface::  
10 * Contexts for programmers::    
11 @end menu
12
13 @node Programmer interfaces for input 
14 @section Programmer interfaces for input 
15
16 @menu
17 * Input variables and Scheme::  
18 * Internal music representation::  
19 * Extending music syntax::      
20 * Manipulating music expressions::  
21 * Using LilyPond syntax inside Scheme::  
22 @end menu
23
24 @node Input variables and Scheme
25 @subsection Input variables and Scheme
26
27
28 The input format supports the notion of variables: in the following
29 example, a music expression is assigned to a variable with the name
30 @code{traLaLa}.
31 @example
32 traLaLa = @{ c'4 d'4 @}
33 @end example
34
35 @noindent
36
37 There is also a form of scoping: in the following example, the
38 @code{\layout} block also contains a @code{traLaLa} variable, which is
39 independent of the outer @code{\traLaLa}.
40 @example
41 traLaLa = @{ c'4 d'4 @}
42 \layout @{ traLaLa = 1.0 @}
43 @end example
44 @c
45 In effect, each input file is a scope, and all @code{\header},
46 @code{\midi}, and @code{\layout} blocks are scopes nested inside that
47 toplevel scope.
48
49 Both variables and scoping are implemented in the GUILE module system.
50 An anonymous Scheme module is attached to each scope.  An assignment of
51 the form
52 @example
53 traLaLa = @{ c'4 d'4 @}
54 @end example
55
56 @noindent
57 is internally converted to a Scheme definition
58 @example
59 (define traLaLa @var{Scheme value of ``@code{... }''})
60 @end example
61
62 This means that input variables and Scheme variables may be freely
63 mixed.  In the following example, a music fragment is stored in the
64 variable @code{traLaLa}, and duplicated using Scheme.  The result is
65 imported in a @code{\score} block by means of a second variable
66 @code{twice}:
67 @example
68 traLaLa = @{ c'4 d'4 @}
69
70 #(define newLa (map ly:music-deep-copy
71   (list traLaLa traLaLa)))
72 #(define twice
73   (make-sequential-music newLa))
74
75 @{ \twice @}
76 @end example
77
78 In the above example, music expressions can be `exported' from the
79 input to the Scheme interpreter.  The opposite is also possible.  By
80 wrapping a Scheme value in the function @code{ly:export}, a Scheme
81 value is interpreted as if it were entered in LilyPond syntax.  Instead
82 of defining @code{\twice}, the example above could also have been
83 written as
84 @example
85 @dots{}
86 @{ #(ly:export (make-sequential-music newLa)) @}
87 @end example
88
89 @refbugs
90
91 Mixing Scheme and LilyPond identifiers is not possible with the
92 @code{--safe} option.
93
94 @node Internal music representation
95 @subsection Internal music representation
96
97 When a music expression is parsed, it is converted into a set of
98 Scheme music objects.  The defining property of a music object is that
99 it takes up time.  Time is a rational number that measures the length
100 of a piece of music, in whole notes.
101
102 A music object has three kinds of types:
103 @itemize @bullet
104 @item
105 music name: Each music expression has a name, for example, a note
106 leads to a @internalsref{NoteEvent}, and @code{\simultaneous} leads to
107 a @internalsref{SimultaneousMusic}.  A list of all expressions
108 available is in the internals manual, under
109 @internalsref{Music expressions}.
110
111 @item
112 `type' or interface: Each music name has several `types' or
113 interfaces, for example, a note is an @code{event}, but it is also a
114 @code{note-event}, a @code{rhythmic-event}, and a @code{melodic-event}.
115
116 All classes of music are listed in the internals manual, under
117 @internalsref{Music classes}.
118
119 @item
120 C++ object: Each music object is represented by a C++ object.  For
121 technical reasons, different music objects may be represented by
122 different C++ object types.  For example, a note is @code{Event}
123 object, while @code{\grace} creates a @code{Grace_music} object.
124
125 We expect that distinctions between different C++ types will disappear
126 in the future.
127 @end itemize
128
129 The actual information of a music expression is stored in properties.
130 For example, a @internalsref{NoteEvent} has @code{pitch} and
131 @code{duration} properties that store the pitch and duration of that
132 note.  A list of all properties available is in the internals manual,
133 under @internalsref{Music properties}.
134
135 A compound music expression is a music object that contains other
136 music objects in its properties.  A list of objects can be stored in
137 the @code{elements} property of a music object, or a single `child'
138 music object in the @code{element} object.  For example,
139 @internalsref{SequentialMusic} has its children in @code{elements},
140 and @internalsref{GraceMusic} has its single argument in
141 @code{element}.  The body of a repeat is stored in the @code{element}
142 property of @internalsref{RepeatedMusic}, and the alternatives in
143 @code{elements}.
144
145
146
147
148 @node Extending music syntax
149 @subsection Extending music syntax
150
151 The syntax of composite music expressions, like
152 @code{\repeat}, @code{\transpose}, and @code{\context}
153 follows the general form of
154
155 @example
156 \@code{keyword} @var{non-music-arguments} @var{music-arguments}
157 @end example
158
159 Such syntax can also be defined as user code.  To do this, it is
160 necessary to create a @emph{music function}.  This is a specially marked
161 Scheme function.  For example, the music function @code{\applymusic} applies
162 a user-defined function to a music expression.  Its syntax is
163
164 @example
165 \applymusic #@var{func} @var{music}
166 @end example
167
168 A music function is created with @code{ly:make-music-function},
169
170 @example
171 (ly:make-music-function
172 @end example
173
174 @code{\applymusic} takes a Scheme function and a Music expression as
175 arguments.  This is encoded in its parameter list,
176
177 @example
178 (list procedure? ly:music?)
179 @end example
180
181 The function itself takes another argument, an Input location
182 object.  That object is used to provide error messages with file names
183 and line numbers.  The definition is the second argument of
184 @code{ly:make-music-function}.  The body simply calls the function
185
186 @example
187 (lambda (where func music)
188  (func music))
189 @end example
190
191 The above Scheme code only defines the functionality.  The tag
192 @code{\applymusic} is selected by defining
193
194 @example
195 applymusic = #(ly:make-music-function
196                 (list procedure? ly:music?)
197                 (lambda (location func music)
198                   (func music)))
199 @end example
200
201 A @code{def-music-function} macro is introduced on top of
202 @code{ly:make-music-function} to ease the definition of music
203 functions:
204
205 @example
206 applymusic = #(def-music-function (location func music)
207                 (procedure? ly:music?)
208                 (func music))
209 @end example
210
211 Examples of the use of @code{\applymusic} are in the next section.
212
213 @seealso
214 @file{ly/@/music@/-functions@/-init@/.ly}.
215
216 @node Manipulating music expressions
217 @subsection Manipulating music expressions
218
219 Music objects and their properties can be accessed and manipulated
220 directly, through the @code{\applymusic} mechanism.
221 The syntax for @code{\applymusic} is
222 @example
223 \applymusic #@var{func} @var{music}
224 @end example
225
226 @noindent
227 This means that the Scheme function @var{func} is called with
228 @var{music} as its argument.  The return value of @var{func} is the
229 result of the entire expression.  @var{func} may read and write music
230 properties using the functions @code{ly:music-property} and
231 @code{ly:music-set-property!}.
232
233 An example is a function that reverses the order of elements in
234 its argument,
235 @lilypond[quote,verbatim,raggedright]
236 #(define (rev-music-1 m)
237   (ly:music-set-property! m 'elements 
238     (reverse (ly:music-property m 'elements)))
239   m)
240
241 \applymusic #rev-music-1 { c'4 d'4 } 
242 @end lilypond
243
244 The use of such a function is very limited.  The effect of this
245 function is void when applied to an argument that does not have
246 multiple children.  The following function application has no effect
247
248 @example
249 \applymusic #rev-music-1 \grace @{ c4 d4 @}
250 @end example
251
252 @noindent
253 In this case, @code{\grace} is stored as @internalsref{GraceMusic}, which
254 has no @code{elements}, only a single @code{element}.  Every generally
255 applicable function for @code{\applymusic} must -- like music expressions
256 themselves -- be recursive.
257
258 The following example is such a recursive function: It first extracts
259 the @code{elements} of an expression, reverses them and puts them
260 back.  Then it recurses, both on @code{elements} and @code{element}
261 children.
262 @example
263 #(define (reverse-music music)
264   (let* ((elements (ly:music-property music 'elements))
265          (child (ly:music-property music 'element))
266          (reversed (reverse elements)))
267
268     ; set children
269     (ly:music-set-property! music 'elements reversed)
270
271     ; recurse
272     (if (ly:music? child) (reverse-music child))
273     (map reverse-music reversed)
274
275     music))
276 @end example
277
278 A slightly more elaborate example is in
279 @inputfileref{input/@/test,reverse@/-music@/.ly}.
280
281 Some of the input syntax is also implemented as recursive music
282 functions.  For example, the syntax for polyphony
283 @example
284 <<a \\ b>>
285 @end example
286
287 @noindent
288 is actually implemented as a recursive function that replaces the
289 above by the internal equivalent of
290 @example
291 << \context Voice = "1" @{ \voiceOne a @}
292    \context Voice = "2" @{ \voiceTwo b @} >>
293 @end example
294
295 Other applications of @code{\applymusic} are writing out repeats
296 automatically (@inputfileref{input/@/test,unfold@/-all@/-repeats@/.ly}),
297 saving keystrokes (@inputfileref{input/@/test,music@/-box@/.ly}) and
298 exporting LilyPond input to other formats
299 (@inputfileref{input/@/test,to@/-xml@/.ly})
300
301 @cindex internal storage
302 @cindex @code{\displayMusic}
303 When writing a music function, it is often instructive to inspect how
304 a music expression is stored internally.  This can be done with the
305 music function @code{\displayMusic}.
306
307 @seealso
308
309 @file{scm/@/music@/-functions@/.scm}, @file{scm/@/music@/-types@/.scm},
310 @inputfileref{input/@/test,add@/-staccato@/.ly},
311 @inputfileref{input/@/test,unfold@/-all@/-repeats@/.ly}, and
312 @inputfileref{input/@/test,music@/-box@/.ly}.
313
314
315 @node Using LilyPond syntax inside Scheme
316 @subsection Using LilyPond syntax inside Scheme
317
318 Creating music expressions in Scheme can be tedious, as they are
319 heavily nested and the resulting Scheme code is large.  For some
320 simple tasks, this can be avoided, using common LilyPond syntax inside
321 Scheme, with the dedicated @code{#@{ ... #@}} syntax.
322
323 The following two expressions give equivalent music expressions:
324 @example
325 mynotes = @{ \override Stem #'thickness = #4
326             @{ c'8 d' @} @}
327   
328 #(define mynotes #@{ \override Stem #'thickness = #4
329                     @{ c'8 d' @} #@})
330 @end example
331
332 The content of @code{#@{ ... #@}} is enclosed in an implicit @code{@{
333 ... @}} block, which is parsed.  The resulting music expression, a
334 @code{SequentialMusic} music object, is then returned and usable in Scheme.
335
336 Arbitrary Scheme forms, including variables, can be used in @code{#@{ ... #@}}
337 expressions with the @code{$} character (@code{$$} can be used to
338 produce a single @code{$} character).  This makes the creation of simple
339 functions straightforward.  In the following example, a function
340 setting the TextScript's padding is defined:
341
342 @lilypond[quote,verbatim,raggedright]
343 #(use-modules (ice-9 optargs))
344 #(define* (textpad padding #:optional once?)
345   (ly:export   ; this is necessary for using the expression
346                ; directly inside a block
347     (if once?
348         #{ \once \override TextScript #'padding = #$padding #}
349         #{ \override TextScript #'padding = #$padding #})))
350
351  {
352    c'^"1"
353    #(textpad 3.0 #t) % only once
354    c'^"2"
355    c'^"3"
356    #(textpad 5.0)
357    c'^"4"
358    c'^"5"
359  }
360 @end lilypond
361
362 Here, the variable @code{padding} is a number; music expression
363 variables may also be used in a similar fashion, as in the following
364 example:
365
366 @lilypond[quote,verbatim,raggedright]
367 #(define (with-padding padding)
368   (lambda (music)
369    #{ \override TextScript #'padding = #$padding
370       $music
371       \revert TextScript #'padding #}))
372
373 {
374   c'^"1"
375   \applymusic #(with-padding 3) { c'^"2" c'^"3" }
376   c'^"4"
377 }
378 @end lilypond
379
380 The function created by @code{(with-padding 3)} adds @code{\override} and
381 @code{\revert} statements around the music given as an argument, and returns
382 this new expression.  Thus, this example is equivalent to:
383
384 @example
385 @{
386   c'^"1"
387   @{ \override TextScript #'padding = #3
388     @{ c'^"2" c'^"3"@}
389     \revert TextScript #'padding
390   @}
391   c'^"4"
392 @}
393 @end example
394
395 This function may also be defined as a music function:
396
397 @lilypond[quote,verbatim,raggedright]
398 withPadding =
399   #(def-music-function (location padding music) (number? ly:music?)
400     #{ \override TextScript #'padding = #$padding
401        $music 
402        \revert TextScript #'padding #})
403
404 {
405   c'^"1"
406   \withPadding #3 { c'^"2" c'^"3"}
407   c'^"4"
408 }
409 @end lilypond
410
411
412 @node Markup programmer interface
413 @section Markup programmer interface
414
415 @c Please rewrite the second sentence; I don't unÑ•erstand its meaning. AS
416 Markups are implemented as special Scheme functions.  When applied with as
417 arguments an output definition (@code{\layout} or @code{\paper}),
418 and a list of properties and other arguments, produce a Stencil
419 object.
420
421 @menu
422 * Markup construction in Scheme::  
423 * How markups work internally ::  
424 * Markup command definition::   
425 @end menu
426
427 @node Markup construction in Scheme
428 @subsection Markup construction in Scheme
429
430 @cindex defining markup commands 
431
432 The @code{markup} macro builds markup expressions in Scheme while
433 providing a LilyPond-like syntax.  For example,
434 @example
435 (markup #:column (#:line (#:bold #:italic "hello" #:raise 0.4 "world")
436                   #:bigger #:line ("foo" "bar" "baz")))
437 @end example
438
439 @noindent
440 is equivalent to:
441 @example
442 \markup \column < @{ \bold \italic "hello" \raise #0.4 "world" @}
443                   \bigger @{ foo bar baz @} >
444 @end example
445
446 @noindent
447 This example exposes the main translation rules between regular
448 LilyPond markup syntax and Scheme markup syntax, which are summed up
449 is this table:
450
451 @quotation
452 @multitable @columnfractions .3 .3
453 @item @b{LilyPond} @tab @b{Scheme}
454 @item @code{\command} @tab @code{#:command}
455 @item @code{\variable} @tab @code{variable}
456 @item @code{@{ ... @}} @tab @code{#:line ( ... )}
457 @item @code{\center-align < ... >} @tab @code{#:center ( ... )}
458 @item @code{string} @tab @code{"string"}
459 @item @code{#scheme-arg} @tab @code{scheme-arg}
460 @end multitable
461 @end quotation
462
463 Besides, the whole scheme language is accessible inside the
464 @code{markup} macro: thus, one may use function calls inside
465 @code{markup} in order to manipulate character strings for
466 instance.  This proves useful when defining new markup commands (see
467 @ref{Markup command definition}).
468
469 @refbugs
470
471 One can not feed the @code{#:line} (resp @code{#:center},
472 @code{#:column}) command with a variable or the result of a function
473 call.  Example:
474
475 @lisp
476 (markup #:line (fun-that-returns-markups))
477 @end lisp
478
479 @noindent
480 is invalid.  One should use the @code{make-line-markup} (resp.,
481 @code{make-center-markup} or @code{make-column-markup}) function
482 instead,
483 @lisp
484 (markup (make-line-markup (fun-that-returns-markups)))
485 @end lisp
486
487 @node How markups work internally 
488 @subsection How markups work internally 
489
490 In a markup like
491
492 @example
493 \raise #0.5 "foo"
494 @end example
495
496 @noindent
497 @code{\raise} is actually represented by the @code{raise-markup}
498 function.  The markup expression is stored as
499
500 @example
501 (list raise-markup 0.5 (list simple-markup 'latin1 "foo"))
502 @end example
503
504 @noindent
505 In this case, @code{latin1} is the input encoding, which is set with
506 the @code{\encoding} command.
507
508 When the markup is converted to printable objects (Stencils), the
509 raise markup is called as
510
511 @example
512 (apply raise-markup
513        @var{\layout object}
514        @var{list of property alists}
515        0.5
516        @var{the "foo" markup})
517 @end example
518
519 The @code{raise-markup} first creates the stencil for the @code{foo}
520 string, and then it raises that Stencil by 0.5 staff space.  This is a
521 rather simple example; more complex examples are in the rest of this
522 section, and in @file{scm/@/define@/-markup@/-commands@/.scm}.
523
524 @node Markup command definition
525 @subsection Markup command definition
526
527 New markup commands can be defined
528 with the @code{def-markup-command} scheme macro.
529 @lisp
530 (def-markup-command (@var{command-name} @var{layout} @var{props} @var{arg1} @var{arg2} ...)
531             (@var{arg1-type?} @var{arg2-type?} ...)
532   ..command body..)
533 @end lisp
534
535 The arguments signify
536
537 @table @var
538 @item argi
539 @var{i}th command argument
540 @item argi-type?
541 a type predicate for the i@var{th} argument
542 @item layout
543 the `layout' definition
544 @item props
545 a list of alists, containing all active properties. 
546 @end table
547
548 As a simple example, we show how to add a @code{\smallcaps} command,
549 which selects @TeX{}'s small caps font.  Normally, we could select the
550 small caps font as follows:
551
552 @example
553 \markup @{ \override #'(font-shape . caps) Text-in-caps @}
554 @end example
555
556 This selects the caps font by setting the @code{font-shape} property to
557 @code{#'caps} for interpreting @code{Text-in-caps}.
558
559 To make the above available as @code{\smallcaps} command, we have to
560 define a function using @code{def-markup-command}.  The command should
561 take a single argument, of type markup.  Therefore, the start of the
562 definition should read
563 @example
564 (def-markup-command (smallcaps layout props argument) (markup?)
565 @end example
566
567 @noindent
568
569 What follows is the content of the command: we should interpret
570 the @code{argument} as a markup, i.e.,
571
572 @example
573 (interpret-markup layout @dots{} argument)
574 @end example
575
576 @noindent
577 This interpretation should add @code{'(font-shape . caps)} to the active
578 properties, so we substitute the following for the @dots{} in the
579 above example:
580
581 @example
582 (cons (list '(font-shape . caps) ) props)
583 @end example
584
585 @noindent
586 The variable @code{props} is a list of alists, and we prepend to it by
587 cons'ing a list with the extra setting.
588
589
590 Suppose that we are typesetting a recitative in an opera, and
591 we would like to define a command that will show character names in a
592 custom manner.  Names should be printed with small caps and translated a
593 bit to the left and top.  We will define a @code{\character} command
594 that takes into account the necessary translation, and uses the newly
595 defined @code{\smallcaps} command:
596
597 @example
598 #(def-markup-command (character layout props name) (string?)
599   "Print the character name in small caps, translated to the left and
600   top.  Syntax: \\character #\"name\""
601   (interpret-markup layout props 
602    (markup "" #:translate (cons -3 1) #:smallcaps name)))
603 @end example
604
605 There is one complication that needs explanation: texts above and below
606 the staff are moved vertically to be at a certain distance (the
607 @code{padding} property) from the staff and the notes.  To make sure
608 that this mechanism does not annihilate the vertical effect of our
609 @code{#:translate}, we add an empty string (@code{""}) before the
610 translated text.  Now the @code{""} will be put above the notes, and the
611 @code{name} is moved in relation to that empty string.  The net effect is
612 that the text is moved to the upper left.
613
614 The final result is as follows:
615 @example
616 @{
617   c''^\markup \character #"Cleopatra"
618   e'^\markup \character #"Giulio Cesare"
619 @}
620 @end example
621
622 @lilypond[quote,raggedright]
623 #(def-markup-command (smallcaps layout props str) (string?)
624   "Print the string argument in small caps.  Syntax: \\smallcaps #\"string\""
625   (interpret-markup layout props
626    (make-line-markup
627     (map (lambda (s)
628           (if (= (string-length s) 0)
629               s
630               (markup #:large (string-upcase (substring s 0 1))
631                       #:translate (cons -0.6 0)
632                       #:tiny (string-upcase (substring s 1)))))
633          (string-split str #\Space)))))
634
635 #(def-markup-command (character layout props name) (string?)
636   "Print the character name in small caps, translated to the left and
637   top.  Syntax: \\character #\"name\""
638   (interpret-markup layout props 
639    (markup "" #:translate (cons -3 1) #:smallcaps name)))
640
641 {
642   c''^\markup \character #"Cleopatra" c'' c'' c''
643   e'^\markup \character #"Giulio Cesare" e' e' e'
644 }
645 @end lilypond
646
647 We have used the @code{caps} font shape, but suppose that our font
648 does not have a small-caps variant.  In that case we have to fake
649 the small caps font by setting a string in upcase with the first
650 letter a little larger:
651
652 @example
653 #(def-markup-command (smallcaps layout props str) (string?)
654   "Print the string argument in small caps."
655   (interpret-markup layout props
656    (make-line-markup
657     (map (lambda (s)
658           (if (= (string-length s) 0)
659               s
660               (markup #:large (string-upcase (substring s 0 1))
661                       #:translate (cons -0.6 0)
662                       #:tiny (string-upcase (substring s 1)))))
663          (string-split str #\Space)))))
664 @end example
665
666 The @code{smallcaps} command first splits its string argument into
667 tokens separated by spaces (@code{(string-split str #\Space)}); for
668 each token, a markup is built with the first letter made large and
669 upcased (@code{#:large (string-upcase (substring s 0 1))}), and a
670 second markup built with the following letters made tiny and upcased
671 (@code{#:tiny (string-upcase (substring s 1))}).  As LilyPond
672 introduces a space between markups on a line, the second markup is
673 translated to the left (@code{#:translate (cons -0.6 0) ...}).  Then,
674 the markups built for each token are put in a line by
675 @code{(make-line-markup ...)}.  Finally, the resulting markup is passed
676 to the @code{interpret-markup} function, with the @code{layout} and
677 @code{props} arguments.
678
679
680
681 @node Contexts for programmers
682 @section Contexts for programmers
683
684
685 @menu
686 * Context evaluation::          
687 * Running a function on all layout objects::  
688 @end menu
689
690 @node Context evaluation
691 @subsection Context evaluation
692
693 @cindex calling code during interpreting
694 @cindex @code{\applycontext}
695
696 Contexts can be modified during interpretation with Scheme code.  The
697 syntax for this is
698 @example
699 \applycontext @var{function}
700 @end example
701
702 @var{function} should be a Scheme function taking a single argument,
703 being the context to apply it to.  The following code will print the
704 current bar number on the standard output during the compile:
705
706 @example
707 \applycontext
708   #(lambda (x)
709     (format #t "\nWe were called in barnumber ~a.\n"
710      (ly:context-property x 'currentBarNumber)))
711 @end example
712
713
714
715 @node Running a function on all layout objects
716 @subsection Running a function on all layout objects
717
718
719 @cindex calling code on layout objects
720 @cindex @code{\applyoutput}
721
722
723 The most versatile way of tuning an object is @code{\applyoutput}.  Its
724 syntax is
725 @example
726 \applyoutput @var{proc}
727 @end example
728
729 @noindent
730 where @var{proc} is a Scheme function, taking three arguments.
731
732 When interpreted, the function @var{proc} is called for every layout
733 object found in the context, with the following arguments:
734 @itemize @bullet
735 @item the layout object itself,
736 @item the context where the layout object was created, and
737 @item the context where @code{\applyoutput} is processed.
738 @end itemize
739
740
741 In addition, the cause of the layout object, i.e., the music
742 expression or object that was responsible for creating it, is in the
743 object property @code{cause}.  For example, for a note head, this is a
744 @internalsref{NoteHead} event, and for a @internalsref{Stem} object,
745 this is a @internalsref{NoteHead} object.
746
747 Here is a function to use for @code{\applyoutput}; it blanks
748 note-heads on the center-line:
749
750 @example
751 (define (blanker grob grob-origin context)
752  (if (and (memq (ly:grob-property grob 'interfaces)
753                 note-head-interface)
754           (eq? (ly:grob-property grob 'staff-position) 0))
755      (set! (ly:grob-property grob 'transparent) #t)))
756 @end example
757