X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=Documentation%2Fextending%2Fprogramming-interface.itely;h=87c6505c0f2124838571f47fc9cf938449e8d07e;hb=e4c6153f484d9687e5a7fcb2039a1ef3a9351582;hp=32c33634a1a48935b00690224a52829129531a9b;hpb=60fc32ec59fd97456218332612b87b821968da84;p=lilypond.git diff --git a/Documentation/extending/programming-interface.itely b/Documentation/extending/programming-interface.itely index 32c33634a1..87c6505c0f 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.13.36" +@c \version "2.15.17" @node Interfaces for programmers @chapter Interfaces for programmers @@ -18,7 +18,10 @@ not familiar with Scheme, you may wish to read our @ref{Scheme tutorial}. @menu +* Lilypond code blocks:: +* Scheme functions:: * Music functions:: +* Event functions:: * Markup functions:: * Contexts for programmers:: * Callback functions:: @@ -26,63 +29,277 @@ not familiar with Scheme, you may wish to read our * Difficult tweaks:: @end menu +@node Lilypond code blocks +@section Lilypond code blocks -@node Music functions -@section Music functions +Lilypond code blocks look like +@example + #@{ @var{Lilypond code} #@} +@end example +They can be used anywhere where you can write Scheme code: the Scheme +reader actually is changed for accommodating LilyPond code blocks. When +the LilyPond code block is being read, it is parsed superficially and +replaced by a call to the LilyPond @code{parser} which is executed at +runtime to interpret the LilyPond code block. -@emph{Music functions} are scheme procedures that can create music -expressions automatically, and can be used to greatly simplify the -input file. +The point of the superficial parsing is the interpretation of @code{$} +signs which can be used for splicing in expressions from the surrounding +lexical Scheme context (like @code{let} variables and function +parameters). @code{$} can be used in the following ways: + +@table @code +@item $$ +just passes a single @code{$} to the LilyPond parser. +@item $@var{form} +will evaluate the Scheme form at runtime and splice its value as an +identifier @code{\form} into the LilyPond parser. Depending on the +value type, it may be interpreted as several different syntactic +entities. +@item #$@var{form} +will evaluate the Scheme form at runtime and splice its value as a +Scheme expression into the LilyPond parser. +@item #@var{form} +Forms in Scheme expressions started with @code{#} are read and parsed +recursively for @code{$} signs. Those are treated as follows: +@item #@dots{}$@var{variable} +splices the value of the variable into the surrounding expression. +@item #@dots{}($ @var{form} @dots{}) +splices the value of the form into the surrounding expression. As +opposed to a LilyPond level @code{$@var{form}}, you need to separate the +form with a blank, making @code{$} be recognizable as a separate Scheme +symbol. +@end table + +A LilyPond code block may contain anything that you can use on the right +side of an assignment. In addition, an empty LilyPond block corresponds +to a void music expression, and a LilyPond block containing multiple +music events gets turned into a sequential music expression. + +@node Scheme functions +@section Scheme functions +@cindex Scheme functions (LilyPond syntax) + +@emph{Scheme functions} are Scheme procedures that can create Scheme +expressions from input written in LilyPond syntax. They can be called +in pretty much all places where using @code{#} for specifying a value in +Scheme syntax is allowed. While Scheme has functions of its own, this +chapter is concerned with @emph{syntactic} functions, functions that +receive arguments specified in LilyPond syntax. @menu -* Music function syntax:: -* Simple substitution functions:: -* Intermediate substitution functions:: -* Mathematics in functions:: -* Functions without arguments:: -* Void functions:: +* Scheme function definitions:: +* Scheme function usage:: +* Void scheme functions:: @end menu +@node Scheme function definitions +@subsection Scheme function definitions +@funindex define-scheme-function -@node Music function syntax -@subsection Music function syntax - -The general form for music functions is: +The general form for defining scheme functions is: @example function = -#(define-music-function +#(define-scheme-function (parser location @var{arg1} @var{arg2} @dots{}) (@var{type1?} @var{type2?} @dots{}) - @var{music}) + @var{body}) @end example @noindent where @multitable @columnfractions .33 .66 +@item @code{parser} +@tab needs to be literally @code{parser} in order to give LilyPond code +blocks (@code{#@{}@dots{}@code{#@}}) access to the parser. + @item @code{@var{argN}} @tab @var{n}th argument @item @code{@var{typeN?}} -@tab a scheme @emph{type predicate} for which @code{@var{argN}} -must return @code{#t}. - -@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)}}). - +@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 +@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 +evaluated at definition time (including LilyPond code blocks!), so if +you need a default calculated at runtime, instead write a special value +you can easily recognize. If you write the predicate in parentheses but +don't follow it with a default value, @code{#f} is used as the default. +Default values are not verified with @emph{predicate?} at either +definition or run time: it is your responsibility to deal with the +values you specify. Default values that happen to be music expressions +are copied while setting @code{origin} to the @code{location} parameter. + +@item @code{@var{body}} +@tab A sequence of Scheme forms evaluated in order, the last one being +used as the return value of the scheme function. It may contain +LilyPond code blocks enclosed in hashed braces +(@tie{}@w{@code{#@{@dots{}#@}}}@tie{}), like described in @ref{Lilypond +code blocks}. 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)}}). If your function returns a music expression, it is cloned and +given the correct @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 +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 +the result of calling a scheme function), but Lilypond will also +convert a number of Lilypond constructs into Scheme before actually +checking the predicate on them. Currently, those include music, +simple 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 +complications that may cause a predicate function to be called several +times on successive versions of an argument (like @code{3} and +@code{3\cm}) or several interpretations (like @code{"a" 4} in lyric +mode, which can either be a string followed by a number, or a lyric +event of duration @code{4}). + +Music arguments preceding @code{ly:duration?} arguments must also be +lookahead-free. This may also hold for the last argument of a scheme +function that is used as the last part of another expression, since +otherwise Lilypond won't know whether following postevents or +durations apply to the argument of the Scheme function, or to the +containing music expression. + For a list of available type predicates, see -@ruser{Predefined type predicates}. User-defined type predicates -are also allowed. +@ruser{Predefined type predicates}. + +@seealso + +Notation Reference: +@ruser{Predefined type predicates}. + +Installed Files: +@file{lily/music-scheme.cc}, +@file{scm/c++.scm}, +@file{scm/lily.scm}. + +@node Scheme function usage +@subsection Scheme function usage + +Scheme functions can be called pretty much anywhere where a Scheme +expression starting with @code{#} can be written. You call a scheme +function by writing its name preceded by @code{\}, followed by its +arguments. The last argument can't be an optional argument. If there +are several optional arguments in a row, they are filled with values +left to right. Once an optional argument can't match input, it and all +immediately following optional arguments are replaced with their default +values, and the matching continues with the next non-optional argument. + +Apart from places where a Scheme value is required, there are a few +places where @code{#} expressions are currently accepted and evaluated +for their side effects but otherwise ignored. Mostly those are the +places where an assignment would be acceptable as well. + +Since it is a bad idea to return values that can be misinterpreted in +some context, you should use normal scheme functions only for those +cases where you always return a useful value, and use void scheme +functions (@pxref{Void scheme functions}) otherwise. + +@node Void scheme functions +@subsection Void scheme functions +@funindex define-void-function +@funindex \void + +Sometimes a procedure is executed in order to perform an action rather +than return a value. Some programming languages (like C and Scheme) +use functions for either concept and just discard the returned value +(usually by allowing any expression to act as statement, ignoring the +result). This is clever but error-prone: most C compilers nowadays +offer warnings for various non-``void'' expressions being discarded. +For many functions executing an action, the Scheme standards declare +the return value to be unspecified. Lilypond's Scheme interpreter +Guile has a unique ``unspecified'' value that it usually (such when +using @code{set!} directly on a variable) but unfortunately not +consistently returns in such cases. + +Defining a Lilypond function with @code{define-void-function} makes +sure that this special value (the only value satisfying the predicate +@code{void?}) will be returned. + +@example +noPointAndClick = +#(define-void-function + (parser location) + () + (ly:set-option 'point-and-click #f)) +... +\noPointAndClick % disable point and click +@end example + +If you want to evaluate an expression only for its side-effect and +don't want any value it may return interpreted, you can do so by +prefixing it with @code{\void}: + +@example +\void #(hashq-set! some-table some-key some-value) +@end example + +That way, you can be sure that Lilypond will not assign meaning to the +returned value regardless of where it encounters it. This will also +work for music functions such as @code{\displayMusic}. + +@node Music functions +@section Music functions + +@cindex music functions + +@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 definitions:: +* Music function usage:: +* Simple substitution functions:: +* Intermediate substitution functions:: +* Mathematics in functions:: +* Functions without arguments:: +* Void music functions:: +@end menu + + +@node Music function definitions +@subsection Music function definitions +@cindex defining music functions +@funindex define-music-function +The general form for defining music functions is: + +@example +function = +#(define-music-function + (parser location @var{arg1} @var{arg2} @dots{}) + (@var{type1?} @var{type2?} @dots{}) + @var{body}) +@end example + +@noindent +quite in analogy to @ref{Scheme function definitions}. More often than +not, @var{body} will be a @ref{Lilypond code blocks, Lilypond code block}. + +For a list of available type predicates, see +@ruser{Predefined type predicates}. @seealso @@ -95,6 +312,42 @@ Installed Files: @file{scm/lily.scm}. +@node Music function usage +@subsection Music function usage +Music functions may currently be used in three 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. + +@itemize +@item +At top level in a music expression. There are no special restrictions +on the argument list. + +@item +As a post-event, explicitly started with a direction indicator (one of +@code{-}, @code{^}, @w{and @code{_}}). All trailing arguments of the +music function with the predicate @code{ly:music?} will get parsed also +as post-events (if the last argument is a scheme function, this will +hold for trailing @code{ly:music?} arguments of the scheme function +instead). 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 + +@item +As a chord constituent. All trailing arguments of the music function +with the predicate @code{ly:music?} will get parsed also as chord +constituents. +@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. + @node Simple substitution functions @subsection Simple substitution functions @@ -233,31 +486,35 @@ lilypond -d display-bar-numbers FILENAME.ly @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 Void music functions +@subsection Void music functions + +A music function must return a music expression. If you want to +execute a function only for its side effect, you should use +@code{define-void-function}. But there may be cases where you +sometimes want to produce a music expression, and sometimes not (like +in the previous example). Returning a @code{void} music expression +via @code{#@{ #@}} will achieve that. + +@node Event functions +@section Event functions +@funindex define-event-function +@cindex event functions + +To use a music function in the place of an event, you need to write a +direction indicator before it. But sometimes, this does not quite match +the syntax of constructs you want to replace. For example, if you want +to write dynamics commands, those are usually attached without direction +indicator, like @code{c'\pp}. Here is a way to write arbitrary +dynamics: +@lilypond[quote,verbatim,raggedright] +dyn=#(define-event-function (parser location arg) (markup?) + (make-dynamic-script arg)) +\relative c' { c\dyn pfsss } +@end lilypond +You could do the same using a music function, but then you always would +have to write a direction indicator before calling it, like +@code{@w{c-\dyn pfsss}}. @node Markup functions @@ -289,13 +546,16 @@ providing a LilyPond-like syntax. For example, @noindent is equivalent to: @example -\markup \column @{ \line @{ \bold \italic "hello" \raise #0.4 "world" @} - \larger \line @{ foo bar baz @} @} +#@{ \markup \column @{ \line @{ \bold \italic "hello" \raise #0.4 "world" @} + \larger \line @{ foo bar baz @} @} #@} @end example @noindent This example demonstrates the main translation rules between regular -LilyPond markup syntax and Scheme markup syntax. +LilyPond markup syntax and Scheme markup syntax. Using @code{#@{ +@dots{} #@}} for entering in LilyPond syntax will often be most +convenient, but we explain how to use the @code{markup} macro to get a +Scheme-only solution. @quotation @multitable @columnfractions .3 .3 @@ -370,7 +630,7 @@ The @code{raise-markup} function first creates the stencil for the @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 @@ -498,7 +758,8 @@ 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 +\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 @@ -506,6 +767,16 @@ 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 \override #'(box-padding . 0.4) \box + \override #'(box-padding . 0.6) \box @{ $text @}#@})) +@end lisp + +or, equivalently + @lisp #(define-markup-command (double-box layout props text) (markup?) "Draw a double box around text." @@ -517,10 +788,10 @@ padding. @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. +@code{layout}, @code{props}, and a markup. In the second case, 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 new command can be used as follow: @@ -537,6 +808,19 @@ and the text. So we will introduce a new property, @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 \override #`(box-padding . ,$inter-box-padding) \box + \override #`(box-padding . ,$box-padding) \box + @{ $text @} #@})) +@end lisp + +Again, the equivalent version using the markup macro would be: + @lisp #(define-markup-command (double-box layout props text) (markup?) #:properties ((inter-box-padding 0.4) @@ -566,8 +850,9 @@ customized: (box-padding 0.6)) "Draw a double box around text." (interpret-markup layout props - (markup #:override `(box-padding . ,inter-box-padding) #:box - #:override `(box-padding . ,box-padding) #:box text))) + #{\markup \override #`(box-padding . ,$inter-box-padding) \box + \override #`(box-padding . ,$box-padding) \box + { $text } #})) \markup \double-box A \markup \override #'(inter-box-padding . 0.8) \double-box A @@ -579,7 +864,7 @@ customized: 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}. +found in file @file{scm/define-markup-commands.scm}. 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 @@ -668,6 +953,16 @@ a single stencil, the former returns a list of stencils. In the following example, a @code{\paragraph} markup list command is defined, which returns a list of justified lines, the first one being indented. The indent width is taken from the @code{props} argument. + +@example +#(define-markup-list-command (paragraph layout props args) (markup-list?) + #:properties ((par-indent 2)) + (interpret-markup-list layout props + #@{\markuplist \justified-lines @{ \hspace #$par-indent $args @} #@})) +@end example + + +The version using just Scheme is more complex: @example #(define-markup-list-command (paragraph layout props args) (markup-list?) #:properties ((par-indent 2)) @@ -683,16 +978,16 @@ Besides the usual @code{layout} and @code{props} arguments, the First, the function gets the indent width, a property here named @code{par-indent}, from the property list @code{props}. If the property is not found, the default value is @code{2}. Then, a -list of justified lines is made using the -@code{make-justified-lines-markup-list} function, which is related -to the @code{\justified-lines} built-in markup list command. A -horizontal space is added at the beginning using the -@code{make-hspace-markup} function. Finally, the markup list is +list of justified lines is made using the built-in markup list command +@code{\justified-lines}, which is related to the +@code{make-justified-lines-markup-list} function. A +horizontal space is added at the beginning using @code{\hspace} (or the +@code{make-hspace-markup} function). Finally, the markup list is interpreted using the @code{interpret-markup-list} function. This new markup list command can be used as follows: @example -\markuplines @{ +\markuplist @{ \paragraph @{ The art of music typography is called \italic @{(plate) engraving.@} The term derives from the traditional process of music printing.