X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;ds=sidebyside;f=Documentation%2Fextending%2Fprogramming-interface.itely;h=6b16fdafbc64bb34bb4bfa580ebdfe5b98561f48;hb=8848da24e00c75d7de626b2ecc409fb45e87ce4a;hp=59364e6ff25ba48d8ccf73f48a77bf668031ff98;hpb=a8d54f44df1fe4f89823f6b78364870ce51174dc;p=lilypond.git diff --git a/Documentation/extending/programming-interface.itely b/Documentation/extending/programming-interface.itely index 59364e6ff2..6b16fdafbc 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.12.0" +@c \version "2.17.6" @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,300 @@ 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 +@cindex LilyPond code blocks +@cindex code blocks, LilyPond +@funindex #@{ @dots{} #@} +@funindex $ +@funindex # -@emph{Music functions} are scheme procedures that can create music -expressions automatically, and can be used to greatly simplify the -input file. +Creating music expressions in Scheme can be tedious, as they are +heavily nested and the resulting Scheme code is large. For some +simple tasks this can be avoided by using LilyPond code blocks, +which enable common LilyPond syntax to be used within Scheme. + +LilyPond code blocks look like + +@example + #@{ @var{LilyPond code} #@} +@end example + +Here is a trivial example: + +@lilypond[verbatim,quote] +ritpp = #(define-event-function (parser location) () + #{ ^"rit." \pp #} +) + +{ c'4 e'4\ritpp g'2 } +@end lilypond + +LilyPond code blocks can be used anywhere where you can write Scheme +code. The Scheme reader actually is changed for accommodating +LilyPond code blocks and can deal with embedded Scheme expressions +starting with @code{$} and@w{ }@code{#}. + +@cindex parser (function argument) +@cindex location + +The reader extracts the LilyPond code block and generates a runtime +call to the LilyPond @code{parser} to interpret the LilyPond code. +Scheme expressions embedded in the LilyPond code are evaluated in the +lexical environment of the LilyPond code block, so all local variables +and function parameters available at the point the LilyPond code block +is written may be accessed. Variables defined in other Scheme modules, +like the modules containing @code{\header} and @code{\layout} blocks, +are not accessible as Scheme variables, i.e. prefixed +with@tie{}@code{#}, but they are accessible as LilyPond variables, i.e. +prefixed with@tie{}@code{\}. + +If @code{location} (see @ref{Scheme functions}) refers to a valid +input location (which it usually does inside of music/@/Scheme +functions), all music generated inside the code block has its +@samp{origin} set to @code{location}. + +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{location} +@tab needs to be literally @code{location} in order to provide access +to the input location object, which is used to provide error messages +with file names and line numbers. + @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}. +@tab a Scheme @emph{type predicate} for which @code{@var{argN}} +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 +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)}}). Where normal Scheme expressions using +@code{#} don't do the trick, you might need to revert to immediate +Scheme expressions using @code{$}, for example as @samp{$music}. + +If your function returns a music expression, it is given a useful value +of @code{origin}. +@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)}}). +@noindent +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 +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, postevents, simple +strings (with or without quotes), numbers, full markups and markup +lists, score, book, bookpart, context definition and output definition +blocks. + +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 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}. -@end multitable +@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. Once an optional argument predicate does not match an +argument, LilyPond skips this and all following optional arguments, +replacing them with their specified default, and @q{backs up} the +argument that did not match to the place of the next mandatory argument. +Since the backed up argument needs to go somewhere, optional arguments +are not actually considered optional unless followed by a mandatory +argument. + +There is one exception: if you write @code{\default} in the place of an +optional argument, this and all following optional arguments are skipped +and replaced by their default. This works even when no mandatory +argument follows since @code{\default} does not need to get backed up. +The @code{mark} and @code{key} commands make use of that trick to +provide their default behavior when just followed by @code{\default}. + +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 value @code{*unspecified*} 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)) +@dots{} +\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 -For a list of available type predicates, see -@ruser{Predefined type predicates}. User-defined type predicates -are also allowed. +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 +335,35 @@ Installed Files: @file{scm/lily.scm}. +@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. + +@itemize +@item +At top level in a music expression. No restriction apply here. + +@item +As a post-event, explicitly started with a direction indicator (one of +@code{-}, @code{^}, @w{and @code{_}}). + +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. + +@item +As a chord constituent. The returned expression must be of +@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. + @node Simple substitution functions @subsection Simple substitution functions @@ -122,7 +391,7 @@ manualBeam = (parser location beg-end) (pair?) #@{ - \once \override Beam #'positions = $beg-end + \once \override Beam.positions = #beg-end #@}) \relative c' @{ @@ -141,7 +410,7 @@ manualBeam = (parser location beg end) (number? number?) #{ - \once \override Beam #'positions = $(cons beg end) + \once \override Beam.positions = #(cons beg end) #}) \relative c' { @@ -149,6 +418,55 @@ manualBeam = } @end lilypond +@funindex \temporary +@cindex temporary overrides +@cindex overrides, temporary +@cindex properties, popping previous value + +Properties are maintained conceptually using one stack per property +per grob per context. Music functions may need to override one or +several properties for the duration of the function, restoring them +to their previous value before exiting. However, normal overrides +pop and discard the top of the current property stack before +pushing to it, so the previous value of the property is lost when it +is overridden. When the previous value must be preserved, prefix the +@code{\override} command with @code{\temporary}, like this: + +@example +\temporary \override @dots{} +@end example + +The use of @code{\temporary} causes the (usually set) @code{pop-first} +property in the override to be cleared, so the previous value is not +popped off the property stack before pushing the new value onto it. +When a subsequent @code{\revert} pops off the temporarily overriden +value, the previous value will re-emerge. + +In other words, calling @code{\temporary \override} and @code{\revert} +in succession on the same property will have a net effect of zero. +Similarly, pairing @code{\temporary} and @code{\undo} on the same +music containing overrides will have a net effect of zero. + +Here is an example of a music function which makes use of this. +The use of @code{\temporary} ensures the values of the +@code{cross-staff} and @code{style} properties are restored on exit +to whatever values they had when the @code{crossStaff} function was +called. Without @code{\temporary} the default values would have been +set on exit. + +@example +crossStaff = +#(define-music-function (parser location notes) (ly:music?) + (_i "Create cross-staff stems") + #@{ + \temporary \override Stem.cross-staff = #cross-staff-connect + \temporary \override Flag.style = #'no-flag + #notes + \revert Stem.cross-staff + \revert Flag.style +#@}) +@end example + @node Mathematics in functions @subsection Mathematics in functions @@ -162,14 +480,14 @@ AltOn = (parser location mag) (number?) #{ - \override Stem #'length = $(* 7.0 mag) - \override NoteHead #'font-size = - $(inexact->exact (* (/ 6.0 (log 2.0)) (log mag))) + \override Stem.length = #(* 7.0 mag) + \override NoteHead.font-size = + #(inexact->exact (* (/ 6.0 (log 2.0)) (log mag))) #}) AltOff = { - \revert Stem #'length - \revert NoteHead #'font-size + \revert Stem.length + \revert NoteHead.font-size } \relative c' { @@ -187,12 +505,12 @@ withAlt = (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))) - $music - \revert Stem #'length - \revert NoteHead #'font-size + \override Stem.length = #(* 7.0 mag) + \override NoteHead.font-size = + #(inexact->exact (* (/ 6.0 (log 2.0)) (log mag))) + #music + \revert Stem.length + \revert NoteHead.font-size #}) \relative c' { @@ -221,7 +539,7 @@ displayBarNum = (parser location) () (if (eq? #t (ly:get-option 'display-bar-numbers)) - #@{ \once \override Score.BarNumber #'break-visibility = ##f #@} + #@{ \once \override Score.BarNumber.break-visibility = ##f #@} #@{#@})) @end example @@ -233,31 +551,35 @@ lilypond -d display-bar-numbers FILENAME.ly @end example -@node Void functions -@subsection Void functions +@node Void music functions +@subsection Void music 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. +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. -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. +@node Event functions +@section Event functions +@funindex define-event-function +@cindex event functions -@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 +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,ragged-right] +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 @@ -278,34 +600,66 @@ Markups are implemented as special Scheme functions which produce a @subsection Markup construction in Scheme @cindex defining markup commands +@funindex \displayScheme + +Markup expressions are internally represented in Scheme using the +@code{markup} macro: -The @code{markup} macro builds markup expressions in Scheme while -providing a LilyPond-like syntax. For example, @example -(markup #:column (#:line (#:bold #:italic "hello" #:raise 0.4 "world") - #:larger #:line ("foo" "bar" "baz"))) +(markup @var{expr}) +@end example + +To see a markup expression in its Scheme form, use the +@code{\displayScheme} command: + +@example +\displayScheme +\markup @{ + \column @{ + \line @{ \bold \italic "hello" \raise #0.4 "world" @} + \larger \line @{ foo bar baz @} + @} +@} @end example @noindent -is equivalent to: +Compiling the code above will send the following to the display +console: + @example -\markup \column @{ \line @{ \bold \italic "hello" \raise #0.4 "world" @} - \larger \line @{ foo bar baz @} @} +(markup + #:line + (#:column + (#:line + (#:bold (#:italic "hello") #:raise 0.4 "world") + #:larger + (#:line + (#:simple "foo" #:simple "bar" #:simple "baz"))))) @end example +To prevent the markup from printing on the page, use +@w{@samp{\void \displayScheme @var{markup}}}. Also, as with the +@code{\displayMusic} command, the output of @code{\displayScheme} +can be saved to an external file. See +@ref{Displaying music expressions}. + @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 @item @b{LilyPond} @tab @b{Scheme} @item @code{\markup markup1} @tab @code{(markup markup1)} -@item @code{\markup @{ markup1 markup2 ... @}} @tab - @code{(markup markup1 markup2 ... )} +@item @code{\markup @{ markup1 markup2 @dots{} @}} @tab + @code{(markup markup1 markup2 @dots{} )} @item @code{\markup-command} @tab @code{#:markup-command} @item @code{\variable} @tab @code{variable} -@item @code{\center-column @{ ... @}} @tab @code{#:center-column ( ... )} +@item @code{\center-column @{ @dots{} @}} @tab + @code{#:center-column ( @dots{} )} @item @code{string} @tab @code{"string"} @item @code{#scheme-arg} @tab @code{scheme-arg} @end multitable @@ -370,7 +724,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 @@ -392,11 +746,11 @@ 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?} ...) +(define-markup-command (@var{command-name} @var{layout} @var{props} @var{arg1} @var{arg2} @dots{}) + (@var{arg1-type?} @var{arg2-type?} @dots{}) [ #:properties ((@var{property1} @var{default-value1}) - ...) ] - ..command body..) + @dots{}) ] + @dots{}command body@dots{}) @end lisp The arguments are @@ -441,6 +795,26 @@ you avoid performance pitfalls by just using Scheme arguments for the leading arguments of markup functions that take a markup as their last argument. +@funindex \markup +@cindex markup macro +@funindex interpret-markup +Markup commands have a rather complex life cycle. The body of a +markup command definition is responsible for converting the +arguments of the markup command into a stencil expression which is +returned. Quite often this is accomplished by calling the +@code{interpret-markup} function on a markup expression, passing +the @var{layout} and @var{props} arguments on to it. Those +arguments are usually only known at a very late stage in +typesetting. Markup expressions have their components assembled +into markup expressions already when @code{\markup} in a LilyPond +expression or the @code{markup} macro in Scheme is expanded. The +evaluation and typechecking of markup command arguments happens at +the time @code{\markup}/@code{markup} are interpreted. + +But the actual conversion of markup expressions into stencil +expressions by executing the markup function bodies only happens +when @code{interpret-markup} is called on a markup expression. + @node On properties @unnumberedsubsubsec On properties @@ -498,7 +872,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 +881,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 +902,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 +922,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 +964,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 +978,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 @@ -590,7 +989,7 @@ follow (documentation stripped): (number-pair?) #:category graphic #:properties ((thickness 1)) - "..documentation.." + "@dots{}documentation@dots{}" (let ((th (* (ly:output-def-lookup layout 'line-thickness) thickness)) (x (car dest)) @@ -607,7 +1006,7 @@ documentation, and is of no use for user-defined markup commands. (define-markup-command (draw-double-line layout props dest) (number-pair?) #:properties ((thickness 1)) - "..documentation.." + "@dots{}documentation@dots{}" (let ((th (* (ly:output-def-lookup layout 'line-thickness) thickness)) (x (car dest)) @@ -623,8 +1022,8 @@ Then, a property for setting the gap between two lines is added, called (number-pair?) #:properties ((thickness 1) (line-gap 0.6)) - "..documentation.." - ... + "@dots{}documentation@dots{}" + @dots{} @end lisp Finally, the code for drawing two lines is added. Two calls to @@ -659,15 +1058,31 @@ stencils are combined using @code{ly:stencil-add}: @node New markup list command definition @subsection New markup list command definition +@funindex define-markup-list-command +@funindex interpret-markup-list Markup list commands are defined with the @code{define-markup-list-command} Scheme macro, which is similar to the @code{define-markup-command} macro described in @ref{New markup command definition}, except that where the latter returns a single stencil, the former returns a list of stencils. +In a similar vein, @code{interpret-markup-list} is used instead of +@code{interpret-markup} for converting a markup list into 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 +1098,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. @@ -749,19 +1164,18 @@ current bar number on the standard output during the compile: @cindex calling code on layout objects @funindex \applyOutput - The most versatile way of tuning an object is @code{\applyOutput} which works by inserting an event into the specified context (@rinternals{ApplyOutputEvent}). Its syntax is @example -\applyOutput @var{context} @var{proc} +\applyOutput @var{Context} @var{proc} @end example @noindent where @code{@var{proc}} is a Scheme function, taking three arguments. When interpreted, the function @code{@var{proc}} is called for -every layout object found in the context @code{@var{context}} at +every layout object found in the context @code{@var{Context}} at the current time step, with the following arguments: @itemize @item the layout object itself, @@ -790,6 +1204,14 @@ note-heads on the center-line and next to it: } @end lilypond +To have @var{function} interpreted at the @code{Score} or @code{Staff} +level use these forms + +@example +\applyOutput #'Score #@var{function} +\applyOutput #'Staff #@var{function} +@end example + @node Callback functions @section Callback functions @@ -798,13 +1220,13 @@ Properties (like @code{thickness}, @code{direction}, etc.) can be set at fixed values with @code{\override}, e.g. @example -\override Stem #'thickness = #2.0 +\override Stem.thickness = #2.0 @end example Properties can also be set to a Scheme procedure, @lilypond[fragment,verbatim,quote,relative=2] -\override Stem #'thickness = #(lambda (grob) +\override Stem.thickness = #(lambda (grob) (if (= UP (ly:grob-property grob 'direction)) 2.0 7.0)) @@ -872,11 +1294,18 @@ my-callback = #(lambda (grob) @node Inline Scheme code @section 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 +@emph{have} to revert to Scheme has become rather hard. + +Until this section gets a rewrite, let's pretend we don't know. + The main disadvantage of @code{\tweak} is its syntactical -inflexibility. For example, the following produces a syntax error. +inflexibility. For example, the following produces a syntax error +(or rather, it did so at some point in the past). @example -F = \tweak #'font-size #-3 -\flageolet +F = \tweak font-size #-3 -\flageolet \relative c'' @{ c4^\F c4_\F @@ -884,10 +1313,6 @@ F = \tweak #'font-size #-3 -\flageolet @end example @noindent -In other words, @code{\tweak} doesn't behave like an articulation -regarding the syntax; in particular, it can't be attached with -@code{^} and @code{_}. - Using Scheme, this problem can be avoided. The route to the result is given in @ref{Adding articulation to notes (example)}, especially how to use @code{\displayMusic} as a helping guide. @@ -975,7 +1400,7 @@ of the broken tie is repositioned. (ly:grob-set-property! grob 'extra-offset '(-2 . 5))))) \relative c'' { - \override Tie #'after-line-breaking = + \override Tie.after-line-breaking = #my-callback c1 ~ \break c2 ~ c @@ -998,9 +1423,10 @@ and @code{PaperColumn}. They can be changed with the @example \overrideProperty -#"Score.NonMusicalPaperColumn" % Grob name -#'line-break-system-details % Property name -#'((next-padding . 20)) % Value +Score.NonMusicalPaperColumn % Grob name + . line-break-system-details % Property name + . next-padding % Optional subproperty name + #20 % Value @end example Note, however, that @code{\override}, applied to