]> git.donarmstrong.com Git - lilypond.git/blobdiff - Documentation/user/programming-interface.itely
*** empty log message ***
[lilypond.git] / Documentation / user / programming-interface.itely
index ff923a66c66005873e11a4e270f6677d82e62c07..535714da983c53fde169f9f9b0621f18c6d95282 100644 (file)
@@ -1,3 +1,4 @@
+@c -*-texinfo-*-
 @node Interfaces for programmers
 @appendix Interfaces for programmers
 
@@ -5,17 +6,19 @@
 
 @menu
 * Programmer interfaces for input ::  
-* Markup programmer interface::         
-* Contexts for programmers::   
+* Markup programmer interface::  
+* Contexts for programmers::    
 @end menu
 
 @node Programmer interfaces for input 
 @appendixsec Programmer interfaces for input 
 
 @menu
-* Input variables and Scheme:: 
+* Input variables and Scheme::  
 * Internal music representation::  
-* Manipulating music expressions::  
+* Extending music syntax::      
+* Manipulating music expressions:: 
+* Using LilyPond syntax inside Scheme::   
 @end menu
 
 @node Input variables and Scheme
@@ -83,6 +86,9 @@ written as
   \score @{ #(ly:export (make-sequential-music newLa)) @}
 @end example
 
+@refbugs
+
+Mixing Scheme and lily identifiers is not possible with @code{--safe}.
 
 @node Internal music representation
 @appendixsubsec Internal music representation
@@ -103,8 +109,10 @@ expressions}.
 
 @item
   `type' or interface: Each music name has several `types' or interface,
-  for example, a note is an @code{event}, but it is also a @code{note-event},
-  a @code{rhythmic-event} and a @code{melodic-event}.
+  for example, a note is an @code{event},
+  but it is also a @code{note-event},
+  a @code{rhythmic-event} and
+   a @code{melodic-event}.
 
   All classes of music are listed in the internals manual, under
   @internalsref{Music classes}.
@@ -133,14 +141,85 @@ and @internalsref{GraceMusic} has its single argument in
 @code{element}. The body of a repeat is in @code{element} property of
 @internalsref{RepeatedMusic}, and the alternatives in @code{elements}.
 
+
+
+
+@node Extending music syntax
+@appendixsubsec Extending music syntax
+
+The syntax of composite music expressions, like
+@code{\repeat}, @code{\transpose} and @code{\context}
+follows the general form of
+
+@example
+  \@code{keyword} @var{non-music-arguments} @var{music-arguments}
+@end example
+
+Such syntax can also be defined as user code. To do this, it is
+necessary to create a @emph{music function}. This is a specially marked
+Scheme function. For example, the music function @code{\applymusic} applies
+a user-defined function to a music expression.  Its syntax is
+
+@example
+\applymusic #@var{func} @var{music}
+@end example
+
+A music function is created with @code{ly:make-music-function},
+
+@example
+  (ly:make-music-function
+@end example
+
+@code{\applymusic} takes a Scheme function and a Music expression as
+argument. This is encoded in its first argument,
+
+@example
+   (list procedure? ly:music?)
+@end example
+
+The function itself takes another argument, an Input location
+object. That object is used to provide error messages with file names
+and line numbers.  The definition is the second argument of
+@code{ly:make-music-function}. The body is function simply calls the
+function
+
+@example
+  (lambda (where func music)
+   (func music))
+@end example
+
+The above Scheme code only defines the functionality. The tag
+@code{\applymusic} is selected by defining
+
+@example
+  applymusic = #(ly:make-music-function
+                  (list procedure? ly:music?)
+                  (lambda (location func music)
+                    (func music)))
+@end example
+
+A @code{def-music-function} macro is introduced on top of
+@code{ly:make-music-function} to ease the definition of music
+functions:
+
+@example
+  applymusic = #(def-music-function (location func music) (procedure? ly:music?)
+                  (func music))
+@end example
+
+Examples of the use of @code{\applymusic} are in the next section.
+
+@seealso
+@file{ly/music-functions-init.ly}.
+
 @node Manipulating music expressions
 @appendixsubsec Manipulating music expressions
 
 Music objects and their properties can be accessed and manipulated
-directly, through the @code{\apply} mechanism.
-The syntax for @code{\apply} is
+directly, through the @code{\applymusic} mechanism.
+The syntax for @code{\applymusic} is
 @example
-\apply #@var{func} @var{music}
+\applymusic #@var{func} @var{music}
 @end example
 
 @noindent
@@ -157,7 +236,7 @@ its argument:
      (ly:music-set-property! m 'elements (reverse
        (ly:music-property m 'elements)))
      m)
-  \score { \notes \apply #rev-music-1 { c4 d4 } }
+  \score { \notes \applymusic #rev-music-1 { c4 d4 } }
 @end lilypond
 
 The use of such a function is very limited. The effect of this
@@ -165,13 +244,13 @@ function is void when applied to an argument which is does not have
 multiple children.  The following function application has no effect:
 
 @example
-  \apply #rev-music-1 \grace @{ c4 d4 @}
+  \applymusic #rev-music-1 \grace @{ c4 d4 @}
 @end example
 
 @noindent
 In this case, @code{\grace} is stored as @internalsref{GraceMusic}, which has no
 @code{elements}, only a single @code{element}. Every generally
-applicable function for @code{\apply} must -- like music expressions
+applicable function for @code{\applymusic} must -- like music expressions
 themselves -- be recursive.
 
 The following example is such a recursive function: It first extracts
@@ -211,7 +290,7 @@ above by the internal equivalent of
     \context Voice = "2" @{ \voiceTwo b @} >>
 @end example
 
-Other applications of @code{\apply} are writing out repeats
+Other applications of @code{\applymusic} are writing out repeats
 automatically (@inputfileref{input/test,unfold-all-repeats.ly}),
 saving keystrokes (@inputfileref{input/test,music-box.ly}) and
 exporting
@@ -225,6 +304,112 @@ LilyPond input to other formats  (@inputfileref{input/test,to-xml.ly})
 @inputfileref{input/test,music-box.ly}.
 
 
+@node Using LilyPond syntax inside Scheme
+@appendixsubsec Using LilyPond syntax inside Scheme
+
+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, using LilyPond usual syntax inside
+scheme, with the dedicated @code{#@{ ... #@}} syntax.
+
+The following two expressions give equivalent music expressions:
+@example
+  mynotes = @{ \override Stem #'thickness = #4
+              \notes @{ c'8 d' @} @}
+  
+  #(define mynotes #@{ \override Stem #'thickness = #4
+                      \notes @{ c'8 d' @} #@})
+@end example
+
+The content of @code{#@{ ... #@}} is enclosed in an implicit @code{@{
+... @}} block, which is parsed. The resulting music expression, a
+@code{SequentialMusic} music object, is then returned and usable in scheme.
+
+Arbitrary scheme forms, including variables, can be used in @code{#@{ ... #@}}
+expressions with the @code{$} character (@code{$$} can be used to
+produce a single $ character). This makes the creation of simple
+functions straightforward. In the following example, a function
+setting the TextScript's padding is defined:
+
+@lilypond[verbatim,raggedright]
+  #(use-modules (ice-9 optargs))
+  #(define* (textpad padding #:optional once?)
+    (ly:export   ; this is necessary for using the expression
+                 ; directly inside a \notes block
+      (if once?
+          #{ \once \override TextScript #'padding = #$padding #}
+          #{ \override TextScript #'padding = #$padding #})))
+  
+  \score {
+      \notes {
+          c'^"1"
+          #(textpad 3.0 #t) % only once
+          c'^"2"
+          c'^"3"
+          #(textpad 5.0)
+          c'^"4"
+          c'^"5"
+          
+      }
+  }
+@end lilypond
+
+Here, the variable @code{padding} is a number; music expression
+variables may also be used in a similar fashion, as in the following
+example:
+
+@lilypond[verbatim,raggedright]
+  #(define (with-padding padding)
+     (lambda (music)
+       #{ \override TextScript #'padding = #$padding
+          $music
+          \revert TextScript #'padding #}))
+  
+  \score {
+      \notes {
+          c'^"1"
+          \applymusic #(with-padding 3)
+            { c'^"2" c'^"3"}
+          c'^"4"
+      }
+  }
+@end lilypond
+
+The function created by @code{(with-padding 3)} adds @code{\override} and
+@code{\revert} statements around the music given as an argument, and returns
+this new expression. Thus, this example is equivalent to:
+
+@example
+  \score @{
+      \notes @{
+          c'^"1"
+          @{ \override TextScript #'padding = #3
+            @{ c'^"2" c'^"3"@}
+            \revert TextScript #'padding
+          @}
+          c'^"4"
+      @}
+  @}
+@end example
+
+This function may also be defined as a music function:
+
+@lilypond[verbatim,raggedright]
+  withPadding = #(def-music-function (location padding music) (number? ly:music?)
+                   #{ \override TextScript #'padding = #$padding
+                      $music 
+                      \revert TextScript #'padding #})
+  
+  \score {
+      \notes {
+          c'^"1"
+          \withPadding #3
+            { c'^"2" c'^"3"}
+          c'^"4"
+      }
+  }
+@end lilypond
+
 
 @node Markup programmer interface
 @appendixsec Markup programmer interface
@@ -232,7 +417,7 @@ LilyPond input to other formats  (@inputfileref{input/test,to-xml.ly})
 
 @menu
 * Markup construction in scheme::  
-* Markup command definition::  
+* Markup command definition::   
 @end menu
 
 @node Markup construction in scheme
@@ -278,7 +463,7 @@ instance. This proves useful when defining new markup commands (see
 
 One can not feed the @code{#:line} (resp @code{#:center},
 @code{#:column}) command with a variable or the result of a function
-call. Eg:
+call. E.g.:
 @lisp
 (markup #:line (fun-that-returns-markups))
 @end lisp
@@ -292,18 +477,27 @@ instead:
 @node Markup command definition
 @appendixsubsec Markup command definition
 
-New markup commands can be defined thanks to the @code{def-markup-command} scheme macro.
+New markup commands can be defined
+with  the @code{def-markup-command} scheme macro.
 @lisp
 (def-markup-command (@var{command-name} @var{paper} @var{props} @var{arg1} @var{arg2} ...)
             (@var{arg1-type?} @var{arg2-type?} ...)
   ..command body..)
-
-    @var{argi}: i@var{th} command argument
-    @var{argi-type?}: a type predicate for the i@var{th} argument
-    @var{paper}: the `paper' definition
-    @var{props}: a list of alists, containing all active properties. 
 @end lisp
 
+The arguments signify
+
+@table @var
+@item argi
+@var{i}th command argument
+@item argi-type?
+a type predicate for the i@var{th} argument
+@item paper
+the `paper' definition
+@item props
+a list of alists, containing all active properties. 
+@end table
+
 As a simple example, we show how to add a @code{\smallcaps} command,
 which selects @TeX{}'s small caps font.  Normally, we could select the
 small caps font as follows:
@@ -334,7 +528,7 @@ the @code{argument} as a markup, i.e.
 
 @noindent
 This interpretation should add @code{'(font-shape . caps)} to the active
-properties, so we substitute the the following for the @dots{} in the
+properties, so we substitute the  following for the @dots{} in the
 above example:
 
 @example
@@ -345,38 +539,8 @@ above example:
 The variable @code{props} is a list of alists, and we prepend to it by
 consing a list with the extra setting.
 
-However, suppose that we are using a font that does not have a
-small-caps variant. In that case, we have to fake the small caps font,
-by setting a string in upcase, with the first letter a little larger:
-
-@example
-#(def-markup-command (smallcaps paper props str) (string?)
-   "Print the string argument in small caps. Syntax: \\smallcaps #\"string\""
-   (interpret-markup paper props
-    (make-line-markup
-     (map (lambda (s)
-            (if (= (string-length s) 0)
-                s
-                (markup #:large (string-upcase (substring s 0 1))
-                        #:translate (cons -0.6 0)
-                        #:tiny (string-upcase (substring s 1)))))
-          (string-split str #\Space)))))
-@end example
-
-The @code{smallcaps} command first splits its string argument into
-tokens separated by spaces (@code{(string-split str #\Space)}); for
-each token, a markup is built with the first letter made large and
-upcased (@code{#:large (string-upcase (substring s 0 1))}), and a
-second markup built with the following letters made tiny and upcased
-(@code{#:tiny (string-upcase (substring s 1))}). As LilyPond
-introduces a space between markups on a line, the second markup is
-translated to the left (@code{#:translate (cons -0.6 0) ...}). Then,
-the markups built for each token are put in a line
-(@code{(make-line-markup ...)}). Finally, the resulting markup is
-passed to the @code{interpret-markup} function, with the @code{paper}
-and @code{props} arguments.
 
-Finally, suppose that we are typesetting a recitative in an opera, and
+Suppose that we are typesetting a recitative in an opera, and
 we would like to define a command that will show character names in a
 custom manner. Names should be printed with small caps and translated a
 bit to the left and top.  We will define a @code{\character} command
@@ -437,6 +601,38 @@ The final result is as follows:
 }
 @end lilypond
 
+We have used the @code{caps} font shape, but suppose that our font
+that does not have a small-caps variant. In that case, we have to fake
+the small caps font, by setting a string in upcase, with the first
+letter a little larger:
+
+@example
+#(def-markup-command (smallcaps paper props str) (string?)
+   "Print the string argument in small caps."
+   (interpret-markup paper props
+    (make-line-markup
+     (map (lambda (s)
+            (if (= (string-length s) 0)
+                s
+                (markup #:large (string-upcase (substring s 0 1))
+                        #:translate (cons -0.6 0)
+                        #:tiny (string-upcase (substring s 1)))))
+          (string-split str #\Space)))))
+@end example
+
+The @code{smallcaps} command first splits its string argument into
+tokens separated by spaces (@code{(string-split str #\Space)}); for
+each token, a markup is built with the first letter made large and
+upcased (@code{#:large (string-upcase (substring s 0 1))}), and a
+second markup built with the following letters made tiny and upcased
+(@code{#:tiny (string-upcase (substring s 1))}). As LilyPond
+introduces a space between markups on a line, the second markup is
+translated to the left (@code{#:translate (cons -0.6 0) ...}). Then,
+the markups built for each token are put in a line by
+@code{(make-line-markup ...)}. Finally, the resulting markup is passed
+to the @code{interpret-markup} function, with the @code{paper} and
+@code{props} arguments.
+
 
 
 @node Contexts for programmers
@@ -444,13 +640,16 @@ The final result is as follows:
 
 
 @menu
-* Context evaluation::         
-* Applyoutput::                        
+* Context evaluation::          
+* Running a function on all layout objects::  
 @end menu
 
 @node Context evaluation
 @appendixsubsec Context evaluation
 
+@cindex calling code during interpreting
+@cindex @code{\applycontext}
+
 Contexts can be modified during interpretation with Scheme code. The
 syntax for this is
 @example
@@ -470,8 +669,13 @@ current bar number on the standard output during the compile:
 
 
 
-@node Applyoutput
-@appendixsubsec Applyoutput
+@node Running a function on all layout objects
+@appendixsubsec Running a function on all layout objects
+
+
+@cindex calling code on layout objects
+@cindex @code{\applyoutput}
+
 
 The most versatile way of tuning an object is @code{\applyoutput}. Its
 syntax is
@@ -497,14 +701,15 @@ object property @code{cause}.  For example, for a note head, this is a
 @internalsref{NoteHead} event, and for a @internalsref{Stem} object,
 this is a @internalsref{NoteHead} object.
 
-Here is a simple example of @code{\applyoutput}; it blanks note-heads on the
-center-line:
+Here is a function to use for @code{\applyoutput}; it blanks
+note-heads on the center-line:
+
 @example
 (define (blanker grob grob-origin context)
   (if (and (memq (ly:grob-property grob 'interfaces)
                  note-head-interface)
            (eq? (ly:grob-property grob 'staff-position) 0))
 
-           (ly:grob-set-property! grob 'transparent #t)))
+           (set! (ly:grob-property grob 'transparent) #t)))
 @end example