]> git.donarmstrong.com Git - lilypond.git/blobdiff - Documentation/extending/programming-interface.itely
issue 4804: table cells shoud be top-aligned in HTML manuals
[lilypond.git] / Documentation / extending / programming-interface.itely
index aaca71c9b30f522c055ad77a3452af0f319d78d4..5e63eabcd4f96598e64c742beca832dadfedf3ca 100644 (file)
@@ -8,7 +8,7 @@
     Guide, node Updating translation committishes..
 @end ignore
 
-@c \version "2.14.0"
+@c \version "2.19.24"
 
 @node Interfaces for programmers
 @chapter Interfaces for programmers
@@ -18,62 +18,70 @@ not familiar with Scheme, you may wish to read our
 @ref{Scheme tutorial}.
 
 @menu
-* Lilypond code blocks::
+* LilyPond code blocks::
 * Scheme functions::
 * Music functions::
 * Event functions::
 * Markup functions::
 * Contexts for programmers::
 * Callback functions::
-* Inline Scheme code::
 * Difficult tweaks::
 @end menu
 
-@node Lilypond code blocks
-@section Lilypond code blocks
+@node LilyPond code blocks
+@section LilyPond code blocks
+
+@cindex LilyPond code blocks
+@cindex code blocks, LilyPond
+@funindex #@{ @dots{} #@}
+@funindex $
+@funindex #
+
+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
 
-Lilypond code blocks look like
 @example
-  #@{ @var{Lilypond code} #@}
+  #@{ @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.
 
-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:
+Here is a trivial example:
 
-@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
+@lilypond[verbatim,quote]
+ritpp = #(define-event-function () ()
+  #{ ^"rit." \pp #}
+)
+
+{ c'4 e'4\ritpp g'2 }
+@end lilypond
 
-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.
+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{#}.
+
+The reader extracts the LilyPond code block and generates a runtime
+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
+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{\}.
+
+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
+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
@@ -101,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
@@ -110,17 +118,12 @@ 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{@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}}
-must return @code{#t}.  Some of these predicates are specially
-recognized by the parser, see below.  There is also a special form
+@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
@@ -131,37 +134,53 @@ 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
 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}.
+(@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
 
 @noindent
-Some type predicates are specially handled by the parser since it
-can't recognize the arguments reliably otherwise.  Currently these are
-@code{ly:music?}, @code{ly:pitch?}, and @code{ly:duration?}.
-
-All other predicates can be specified in Scheme syntax if desired
-(introduced with @code{#} or as the result of calling a scheme
-function), but Lilypond will also accept a number of Lilypond
-constructs it can recognize fully without lookahead.  Currently, those
-include simple strings (with or without quotes), context
-modifications, full markups and markup lists.
-
-If you really want to input one of the special items as a Scheme rather
-than a LilyPond expression, you may write them as a Scheme expression
-that calls @code{ly:export} at its outermost level.
-
-For a list of available type predicates, see
+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}.
 
 @seealso
@@ -178,62 +197,85 @@ 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.  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.
+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
+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 accepted and evaluated for their
-side effects but otherwise ignored.  Mostly those are the places where
-an assignment would be acceptable as well.
-
-There are a few special places where an argument matching
-@code{ly:music?} has to be either a music identifier or a music
-expression enclosed in @code{@{}@dots{}@code{@}} or
-@code{<<}@dots{}@code{>>} explicitly, so that possibly following
-optional durations or postevents can't be confused with additional
-arguments.  One obvious place is before a @code{ly:duration?}
-predicate.  Another is as the last argument of a scheme function when it
-is used in a place where such optional parts could be considered either
-part of the music argument or not.
-
-In those rare cases, you have to delimit your music arguments
-appropriately to spare LilyPond from getting confused.
+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.
+
+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
+@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
+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.
+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
+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
 
@@ -264,14 +306,14 @@ 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
 
 @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}.
+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}.
@@ -289,39 +331,32 @@ Installed Files:
 
 @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.
+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.  There are no special restrictions
-on the argument list.
+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{_}}).  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
+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.  All trailing arguments of the music function
-with the predicate @code{ly:music?} will get parsed also as chord
-constituents.
+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
@@ -347,10 +382,10 @@ using a @code{pair?} variable:
 @example
 manualBeam =
 #(define-music-function
-     (parser location beg-end)
+     (beg-end)
      (pair?)
    #@{
-     \once \override Beam #'positions = $beg-end
+     \once \override Beam.positions = #beg-end
    #@})
 
 \relative c' @{
@@ -366,10 +401,10 @@ 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)
+     \once \override Beam.positions = #(cons beg end)
    #})
 
 \relative c' {
@@ -377,6 +412,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 (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
@@ -387,21 +471,21 @@ addition to simple substitution,
 @lilypond[quote,verbatim,ragged-right]
 AltOn =
 #(define-music-function
-     (parser location mag)
+     (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' {
-  c2 \AltOn #0.5 c4 c
+\relative {
+  c'2 \AltOn #0.5 c4 c
   \AltOn #1.5 c c \AltOff c2
 }
 @end lilypond
@@ -412,19 +496,19 @@ 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)
-     \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' {
-  c2 \withAlt #0.5 { c4 c }
+\relative {
+  c'2 \withAlt #0.5 { c4 c }
   \withAlt #1.5 { c c } c2
 }
 @end lilypond
@@ -446,10 +530,10 @@ 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 #@}
+       #@{ \once \override Score.BarNumber.break-visibility = ##f #@}
        #@{#@}))
 @end example
 
@@ -482,10 +566,10 @@ 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?)
+@lilypond[quote,verbatim,ragged-right]
+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
@@ -510,21 +594,49 @@ 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:
+
+@example
+(markup @var{expr})
+@end example
+
+To see a markup expression in its Scheme form, use the
+@code{\displayScheme} command:
 
-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")))
+\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.  Using @code{#@{
@@ -536,11 +648,12 @@ Scheme-only solution.
 @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
@@ -627,11 +740,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
@@ -676,6 +789,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
 
@@ -747,10 +880,10 @@ padding.
   "Draw a double box around text."
   (interpret-markup layout props
     #@{\markup \override #'(box-padding . 0.4) \box
-            \override #'(box-padding . 0.6) \box @{ $text @}#@}))
+            \override #'(box-padding . 0.6) \box @{ #text @}#@}))
 @end lisp
 
-or, equivalently 
+or, equivalently
 
 @lisp
 #(define-markup-command (double-box layout props text) (markup?)
@@ -789,9 +922,9 @@ now as follows:
                 (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 @} #@}))
 @end lisp
 
 Again, the equivalent version using the markup macro would be:
@@ -825,9 +958,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
@@ -850,7 +983,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))
@@ -867,7 +1000,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))
@@ -883,8 +1016,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
@@ -919,12 +1052,18 @@ 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.
@@ -933,7 +1072,7 @@ indented.  The indent width is taken from the @code{props} argument.
 #(define-markup-list-command (paragraph layout props args) (markup-list?)
    #:properties ((par-indent 2))
    (interpret-markup-list layout props
-     #@{\markuplines \justified-lines @{ \hspace #$par-indent $args @} #@}))
+     #@{\markuplist \justified-lines @{ \hspace #par-indent #args @} #@}))
 @end example
 
 
@@ -962,7 +1101,7 @@ 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.
@@ -991,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
@@ -1019,20 +1270,24 @@ 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
+(@rinternals{ApplyOutputEvent}).  Its syntax is either
 @example
-\applyOutput @var{context} @var{proc}
+\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
@@ -1051,15 +1306,22 @@ 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
 
+To have @var{function} interpreted at the @code{Score} or @code{Staff}
+level use these forms
+
+@example
+\applyOutput Score@dots{}
+\applyOutput Staff@dots{}
+@end example
+
 
 @node Callback functions
 @section Callback functions
@@ -1068,17 +1330,17 @@ 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,
+Properties can also be set to a Scheme procedure:
 
-@lilypond[fragment,verbatim,quote,relative=2]
-\override Stem #'thickness = #(lambda (grob)
+@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
@@ -1099,38 +1361,19 @@ Properties that typically use callbacks include
 
 The procedure always takes a single argument, being the grob.
 
-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
+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
-(ly:make-simple-closure (ly:make-simple-closure (list @var{proc})))
+\relative @{
+  \override Flag.X-offset = #(lambda (flag)
+    (let ((default (ly:flag::calc-x-offset flag)))
+      (* default 4.0)))
+  c''4. d8 a4. g8
+@}
 @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:
 
@@ -1139,25 +1382,30 @@ 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
+@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
+\relative @{
+  c''4^\F c4_\F
 @}
 @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.
@@ -1170,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
 
@@ -1184,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
@@ -1244,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'' {
-  \override Tie #'after-line-breaking =
+\relative {
+  \override Tie.after-line-breaking =
   #my-callback
-  c1 ~ \break
-  c2 ~ c
+  c''1 ~ \break
+  c2 ~ 2
 }
 @end lilypond
 
@@ -1268,9 +1517,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
@@ -1286,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
-