]> git.donarmstrong.com Git - lilypond.git/blobdiff - Documentation/extending/programming-interface.itely
Imported Upstream version 2.19.45
[lilypond.git] / Documentation / extending / programming-interface.itely
index e580f29b63878b555603d9ac128a1540a8c1189f..5e63eabcd4f96598e64c742beca832dadfedf3ca 100644 (file)
@@ -8,7 +8,7 @@
     Guide, node Updating translation committishes..
 @end ignore
 
-@c \version "2.17.6"
+@c \version "2.19.24"
 
 @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
 
@@ -52,7 +51,7 @@ LilyPond code blocks look like
 Here is a trivial example:
 
 @lilypond[verbatim,quote]
-ritpp = #(define-event-function (parser location) ()
+ritpp = #(define-event-function () ()
   #{ ^"rit." \pp #}
 )
 
@@ -64,11 +63,8 @@ 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.
+call to the LilyPond 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
@@ -78,10 +74,8 @@ 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}.
+All music generated inside the code block has its
+@samp{origin} set to the current input 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
@@ -115,7 +109,7 @@ The general form for defining scheme functions is:
 @example
 function =
 #(define-scheme-function
-     (parser location @var{arg1} @var{arg2} @dots{})
+     (@var{arg1} @var{arg2} @dots{})
      (@var{type1?} @var{type2?} @dots{})
    @var{body})
 @end example
@@ -124,20 +118,11 @@ function =
 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
+@tab @var{n}th argument.
 
 @item @code{@var{typeN?}}
-@tab a Scheme @emph{type predicate} for which @code{@var{argN}}
+@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
@@ -149,7 +134,7 @@ 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.
+are copied while setting @code{origin} to the current input location.
 
 @item @code{@var{body}}
 @tab A sequence of Scheme forms evaluated in order, the last one being
@@ -179,13 +164,7 @@ 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 @q{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 in some circumstances.  Some other
+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
@@ -196,8 +175,8 @@ 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 might
-not work with that interpretation.  So it's best to avoid overly
+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.
 
@@ -218,14 +197,15 @@ Installed Files:
 @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
+expression starting with @code{#} can be written.  You call a
+scheme function from LilyPond 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
@@ -245,6 +225,14 @@ 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.
 
+For convenience, scheme functions may also be called directly from
+Scheme bypassing the LilyPond parser.  Their name can be used like
+the name of an ordinary function.  Typechecking of the arguments
+and skipping optional arguments will happen in the same manner as
+when called from within LilyPond, with the Scheme value
+@code{*unspecified*} taking the role of the @code{\default}
+reserved word for explicitly skipping optional arguments.
+
 @node Void scheme functions
 @subsection Void scheme functions
 @funindex define-void-function
@@ -269,7 +257,7 @@ sure that this special value (the only value satisfying the predicate
 @example
 noPointAndClick =
 #(define-void-function
-     (parser location)
+     ()
      ()
    (ly:set-option 'point-and-click #f))
 @dots{}
@@ -318,7 +306,7 @@ The general form for defining music functions is:
 @example
 function =
 #(define-music-function
-     (parser location @var{arg1} @var{arg2} @dots{})
+     (@var{arg1} @var{arg2} @dots{})
      (@var{type1?} @var{type2?} @dots{})
    @var{body})
 @end example
@@ -343,32 +331,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{_}}).
-
-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
@@ -394,7 +382,7 @@ using a @code{pair?} variable:
 @example
 manualBeam =
 #(define-music-function
-     (parser location beg-end)
+     (beg-end)
      (pair?)
    #@{
      \once \override Beam.positions = #beg-end
@@ -413,7 +401,7 @@ music expression:
 @lilypond[quote,verbatim,ragged-right]
 manualBeam =
 #(define-music-function
-     (parser location beg end)
+     (beg end)
      (number? number?)
    #{
      \once \override Beam.positions = #(cons beg end)
@@ -462,7 +450,7 @@ set on exit.
 
 @example
 crossStaff =
-#(define-music-function (parser location notes) (ly:music?)
+#(define-music-function (notes) (ly:music?)
   (_i "Create cross-staff stems")
   #@{
   \temporary \override Stem.cross-staff = #cross-staff-connect
@@ -483,7 +471,7 @@ addition to simple substitution,
 @lilypond[quote,verbatim,ragged-right]
 AltOn =
 #(define-music-function
-     (parser location mag)
+     (mag)
      (number?)
    #{
      \override Stem.length = #(* 7.0 mag)
@@ -496,8 +484,8 @@ AltOff = {
   \revert NoteHead.font-size
 }
 
-\relative c' {
-  c2 \AltOn #0.5 c4 c
+\relative {
+  c'2 \AltOn #0.5 c4 c
   \AltOn #1.5 c c \AltOff c2
 }
 @end lilypond
@@ -508,7 +496,7 @@ This example may be rewritten to pass in music expressions,
 @lilypond[quote,verbatim,ragged-right]
 withAlt =
 #(define-music-function
-     (parser location mag music)
+     (mag music)
      (number? ly:music?)
    #{
      \override Stem.length = #(* 7.0 mag)
@@ -519,8 +507,8 @@ withAlt =
      \revert NoteHead.font-size
    #})
 
-\relative c' {
-  c2 \withAlt #0.5 { c4 c }
+\relative {
+  c'2 \withAlt #0.5 { c4 c }
   \withAlt #1.5 { c c } c2
 }
 @end lilypond
@@ -542,7 +530,7 @@ without arguments,
 @example
 displayBarNum =
 #(define-music-function
-     (parser location)
+     ()
      ()
    (if (eq? #t (ly:get-option 'display-bar-numbers))
        #@{ \once \override Score.BarNumber.break-visibility = ##f #@}
@@ -579,9 +567,9 @@ 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?)
+dyn=#(define-event-function (arg) (markup?)
          (make-dynamic-script arg))
-\relative c' { c\dyn pfsss }
+\relative { 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
@@ -1142,25 +1130,137 @@ 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 {
+  \time 3/4
+  g'8[ 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
+   (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 {
+  \override NoteHead.color = #darkblue
+  \override Stem.color = #darkblue
+  \override Beam.color = #darkblue
+  g'8 a b c
+  \desaturate { d c b a }
+  g b d b g2
+}
+@end lilypond
 
 
 @node Running a function on all layout objects
@@ -1172,17 +1272,22 @@ current bar number on the standard output during the compile:
 
 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
+(@rinternals{ApplyOutputEvent}).  Its syntax is either
 @example
 \applyOutput @var{Context} @var{proc}
 @end example
+or
+@example
+\applyOutput @var{Context}.@var{Grob} @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
-the current time step, with the following arguments:
+every layout object (with grob name @var{Grob} if specified) found
+in the context @code{@var{Context}} at the current time step, with
+the following arguments:
 @itemize
 @item the layout object itself,
 @item the context where the layout object was created, and
@@ -1201,12 +1306,11 @@ note-heads on the center-line and next to it:
 
 @lilypond[quote,verbatim,ragged-right]
 #(define (blanker grob grob-origin context)
-   (if (and (memq 'note-head-interface (ly:grob-interfaces grob))
-            (< (abs (ly:grob-property grob 'staff-position)) 2))
+   (if (< (abs (ly:grob-property grob 'staff-position)) 2)
        (set! (ly:grob-property grob 'transparent) #t)))
 
-\relative c' {
-  a'4 e8 <<\applyOutput #'Voice #blanker a c d>> b2
+\relative {
+  a'4 e8 <<\applyOutput Voice.NoteHead #blanker a c d>> b2
 }
 @end lilypond
 
@@ -1214,8 +1318,8 @@ 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}
+\applyOutput Score@dots{}
+\applyOutput Staff@dots{}
 @end example
 
 
@@ -1229,14 +1333,14 @@ set at fixed values with @code{\override}, e.g.
 \override Stem.thickness = #2.0
 @end example
 
-Properties can also be set to a Scheme procedure,
+Properties can also be set to a Scheme procedure:
 
-@lilypond[fragment,verbatim,quote,relative=2]
+@lilypond[fragment,verbatim,quote]
 \override Stem.thickness = #(lambda (grob)
     (if (= UP (ly:grob-property grob 'direction))
         2.0
         7.0))
-c b a g b a g b
+\relative { c'' b a g b a g b }
 @end lilypond
 
 @noindent
@@ -1262,46 +1366,14 @@ 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)
+\relative @{
+  \override Flag.X-offset = #(lambda (flag)
     (let ((default (ly:flag::calc-x-offset flag)))
       (* default 4.0)))
-  c4. d8 a4. g8
+  c''4. 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},
-
-@example
-`(X-offset .
-  ,(ly:make-simple-closure
-    `(,+
-        ,(ly:make-simple-closure
-           (list ly:self-alignment-interface::centered-on-x-parent))
-      ,(ly:make-simple-closure
-           (list ly:self-alignment-interface::x-aligned-on-self)))))
-@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
-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}.
-
-In fact, using a single procedure as property value is equivalent to
-
-@example
-(ly:make-simple-closure (ly:make-simple-closure (list @var{proc})))
-@end example
-
-@noindent
-The inner @code{ly:make-simple-closure} supplies the grob as argument
-to @var{proc}, the outer ensures that result of the function is
-returned, rather than the @code{simple-closure} object.
-
 From within a callback, the easiest method for evaluating a markup is
 to use grob-interpret-markup.  For example:
 
@@ -1310,8 +1382,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
@@ -1326,8 +1400,8 @@ inflexibility.  For example, the following produces a syntax error
 @example
 F = \tweak font-size #-3 -\flageolet
 
-\relative c'' @{
-  c4^\F c4_\F
+\relative @{
+  c''4^\F c4_\F
 @}
 @end example
 
@@ -1344,8 +1418,8 @@ F = #(let ((m (make-music 'ArticulationEvent
                     (ly:music-property m 'tweaks)))
        m)
 
-\relative c'' @{
-  c4^\F c4_\F
+\relative @{
+  c''4^\F c4_\F
 @}
 @end example
 
@@ -1358,6 +1432,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
@@ -1418,11 +1493,11 @@ of the broken tie is repositioned.
               (eq? (car (last-pair siblings)) grob))
          (ly:grob-set-property! grob 'extra-offset '(-2 . 5)))))
 
-\relative c'' {
+\relative {
   \override Tie.after-line-breaking =
   #my-callback
-  c1 ~ \break
-  c2 ~ c
+  c''1 ~ \break
+  c2 ~ 2
 }
 @end lilypond
 
@@ -1461,4 +1536,3 @@ This chapter covers the various tools provided by LilyPond to help
 Scheme programmers get information into and out of the music streams.
 
 TODO -- figure out what goes in here and how to organize it
-