X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=Documentation%2Fextending%2Fprogramming-interface.itely;h=9c4cbe7805fd2eace8878c056101853a9f15ffc7;hb=730d4eb3e0328e8ba0b376f8191a5bb6ae7f904c;hp=311a13807362de516cd5670a88a3c37d6f2d4faf;hpb=176f53b1cedfe82c1337d4351792628116a54dd2;p=lilypond.git diff --git a/Documentation/extending/programming-interface.itely b/Documentation/extending/programming-interface.itely index 311a138073..9c4cbe7805 100644 --- a/Documentation/extending/programming-interface.itely +++ b/Documentation/extending/programming-interface.itely @@ -8,7 +8,7 @@ Guide, node Updating translation committishes.. @end ignore -@c \version "2.17.6" +@c \version "2.19.2" @node Interfaces for programmers @chapter Interfaces for programmers @@ -25,7 +25,6 @@ not familiar with Scheme, you may wish to read our * Markup functions:: * Contexts for programmers:: * Callback functions:: -* Inline Scheme code:: * Difficult tweaks:: @end menu @@ -138,8 +137,7 @@ with file names and line numbers. @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 +must return @code{#t}. 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 @@ -169,11 +167,7 @@ of @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 +Suitability of arguments for the 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 @@ -184,20 +178,21 @@ strings (with or without quotes), numbers, 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. If such an expression were considered for an -optional argument by evaluating its predicate, LilyPond would not be -able to ``backup'' when it decides the expression does not fit the -parameter. So some forms of music might need to be enclosed in braces -to make them acceptable to LilyPond. There are also some other -ambiguities that LilyPond sorts out by checking with predicate +Some +ambiguities LilyPond sorts out by checking with predicate functions: is @samp{-3} a fingering postevent or a negative number? Is @code{"a" 4} in lyric mode a string followed by a number, or a lyric -event of duration @code{4}? LilyPond decides by asking the predicates. -That means that you should avoid permissive predicates like -@code{scheme?} if you have a particular use in mind instead of a general -purpose function. +event of duration @code{4}? LilyPond tries the argument +predicate on successive interpretations until success, with an +order designed to minimize inconsistent interpretations and +lookahead. + +For example, a predicate accepting both music expressions and +pitches will consider @code{c''} to be a pitch rather than a music +expression. Immediately following durations or postevents will +change that interpretation. It's best to avoid overly +permissive predicates like @code{scheme?} when the application +rather calls for more specific argument types. For a list of available predefined type predicates, see @ruser{Predefined type predicates}. @@ -341,37 +336,32 @@ Installed Files: @node Music function usage @subsection Music function usage -Music functions may currently be used in several 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. +A @q{music function} has to return an expression matching the predicate +@code{ly:music?}. This makes music function calls suitable as arguments +of type @code{ly:music?} for another music function call. + +When using a music function call in other contexts, the context may +cause further semantic restrictions. @itemize @item -At top level in a music expression. No restriction apply here. +At the top level in a music expression a post-event is not accepted. @item -As a post-event, explicitly started with a direction indicator (one of -@code{-}, @code{^}, @w{and @code{_}}). Note that returning a post-event -will be acceptable for music functions called as normal music, leading -to a result roughly equivalent to -@example -s 1*0-\fun -@end example - -In this case, you can't use an @emph{open} music expression as the last -argument, one that would end with a music expression able to accept -additional postevents. +When a music function (as opposed to an event function) returns an +expression of type post-event, LilyPond requires one of the named +direction indicators (@code{-}, @code{^}, @w{and @code{_}})) in order to +properly integrate the post-event produced by the music function call +into the surrounding expression. @item -As a chord constituent. The returned expression must be of +As a chord constituent. The returned expression must be of a @code{rhythmic-event} type, most likely a @code{NoteEvent}. @end itemize @noindent -The special rules for trailing arguments make it possible to write -polymorphic functions like @code{\tweak} that can be applied to -different constructs. +@q{Polymorphic} functions, like @code{\tweak}, can be applied to +post-events, chord constituent and top level music expressions. @node Simple substitution functions @subsection Simple substitution functions @@ -1145,26 +1135,138 @@ This new markup list command can be used as follows: @cindex calling code during interpreting @funindex \applyContext +@funindex make-apply-context +@funindex ly:context-property +@funindex ly:context-set-property! +@funindex ly:context-grob-definition +@funindex ly:assoc-get +@funindex ly:context-pushpop-property + +Contexts can be modified during interpretation with Scheme code. +In a LilyPond code block, the syntax for this is: -Contexts can be modified during interpretation with Scheme code. The -syntax for this is @example \applyContext @var{function} @end example +In Scheme code, the syntax is: + +@example +(make-apply-context @var{function}) +@end example + @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: +command is being called. The function can access as well as +override/set grob properties and context properties. Any actions +taken by the function that depend on the state of the context are +limited to the state of the context @emph{when the function is +called}. Also, changes effected by a call to @code{\applyContext} +remain in effect until they are directly modified again, or +reverted, even if the initial conditions that they depended on +have changed. + +The following scheme functions are useful when using +@code{\applyContext}: -@example +@table @code +@item ly:context-property +look up a context property value + +@item ly:context-set-property! +set a context property + +@item ly:context-grob-definition +@itemx ly:assoc-get +look up a grob property value + +@item ly:context-pushpop-property +do a @code{\temporary@tie{}\override} +or a @code{\revert} on a grob property +@end table + + +The following example looks up the current @code{fontSize} value, and +then doubles it: + +@lilypond[quote,verbatim] +doubleFontSize = \applyContext - #(lambda (x) - (format #t "\nWe were called in barnumber ~a.\n" - (ly:context-property x 'currentBarNumber))) -@end example + #(lambda (context) + (let ((fontSize (ly:context-property context 'fontSize))) + (ly:context-set-property! context 'fontSize (+ fontSize 6)))) + +{ + \set fontSize = -3 + b'4 + \doubleFontSize + b' +} +@end lilypond +The following example looks up the current colors of the +@code{NoteHead}, @code{Stem}, and @code{Beam} grobs, and then changes +each to a less saturated shade. + +@lilypond[quote,verbatim] +desaturate = +\applyContext + #(lambda (context) + (define (desaturate-grob grob) + (let* ((grob-def (ly:context-grob-definition context grob)) + (color (ly:assoc-get 'color grob-def black)) + (new-color (map (lambda (x) (min 1 (/ (1+ x) 2))) color))) + (ly:context-pushpop-property context grob 'color new-color))) + (for-each desaturate-grob '(NoteHead Stem Beam))) + +\relative g' { + \time 3/4 + g8[ g] \desaturate g[ g] \desaturate g[ g] + \override NoteHead.color = #darkred + \override Stem.color = #darkred + \override Beam.color = #darkred + g[ g] \desaturate g[ g] \desaturate g[ g] +} +@end lilypond + + +This also could be implemented as a music function, in order to +restrict the modifications to a single music block. Notice how +@code{ly:context-pushpop-property} is used both as a +@code{\temporary@tie{}\override} and as a @code{\revert}: + +@lilypond[quote,verbatim] +desaturate = +#(define-music-function + (parser location music) (ly:music?) + #{ + \applyContext + #(lambda (context) + (define (desaturate-grob grob) + (let* ((grob-def (ly:context-grob-definition context grob)) + (color (ly:assoc-get 'color grob-def black)) + (new-color (map (lambda (x) (min 1 (/ (1+ x) 2))) color))) + (ly:context-pushpop-property context grob 'color new-color))) + (for-each desaturate-grob '(NoteHead Stem Beam))) + #music + \applyContext + #(lambda (context) + (define (revert-color grob) + (ly:context-pushpop-property context grob 'color)) + (for-each revert-color '(NoteHead Stem Beam))) + #}) + +\relative g' { + \override NoteHead.color = #darkblue + \override Stem.color = #darkblue + \override Beam.color = #darkblue + g8 a b c + \desaturate { d c b a } + g b d b g2 +} +@end lilypond + @node Running a function on all layout objects @subsection Running a function on all layout objects @@ -1260,23 +1362,36 @@ Properties that typically use callbacks include 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': + +@example +\relative c'' @{ + \override Flag #'X-offset = #(lambda (flag) + (let ((default (ly:flag::calc-x-offset flag))) + (* default 4.0))) + c4. d8 a4. g8 +@} +@end example + If routines with multiple arguments must be called, the current grob can be inserted with a grob closure. Here is a setting from -@code{AccidentalSuggestion}, +@code{RehearsalMark}, @example `(X-offset . - ,(ly:make-simple-closure - `(,+ + ,(ly:make-simple-closure + `(,+ + ,(ly:make-simple-closure + (list ly:break-alignable-interface::self-align-callback)) ,(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))))) + (list ly:self-alignment-interface::x-aligned-on-self))))) @end example @noindent -In this example, both @code{ly:self-alignment-interface::x-aligned-on-self} and -@code{ly:self-alignment-interface::centered-on-x-parent} are called +In this example, both @code{ly:break-alignable-interface::self-align-callback} and +@code{ly:self-alignment-interface::x-aligned-on-self} are called with the grob as argument. The results are added with the @code{+} function. To ensure that this addition is properly executed, the whole thing is enclosed in @code{ly:make-simple-closure}. @@ -1300,8 +1415,10 @@ my-callback = #(lambda (grob) (grob-interpret-markup grob (markup "foo"))) @end example -@node Inline Scheme code -@section Inline Scheme code +@ignore + +@n ode Inline Scheme code +@s ection Inline Scheme code TODO: after this section had been written, LilyPond has improved to the point that finding a @emph{simple} example where one would @@ -1348,6 +1465,7 @@ font size is prepended to the property list with the written back with @code{set!}. The last element of the @code{let} block is the return value, @code{m} itself. +@end ignore @node Difficult tweaks @@ -1412,7 +1530,7 @@ of the broken tie is repositioned. \override Tie.after-line-breaking = #my-callback c1 ~ \break - c2 ~ c + c2 ~ 2 } @end lilypond