-@c -*-texinfo-*-
+@c -*- coding: latin-1; mode: texinfo; -*-
@node Interfaces for programmers
@chapter Interfaces for programmers
* Input variables and Scheme::
* Internal music representation::
* Extending music syntax::
-* Manipulating music expressions::
-* Using LilyPond syntax inside Scheme::
+* Manipulating music expressions::
+* Using LilyPond syntax inside Scheme::
@end menu
@node Input variables and Scheme
example, a music expression is assigned to a variable with the name
@code{traLaLa}.
@example
- traLaLa = \notes @{ c'4 d'4 @}
+ traLaLa = @{ c'4 d'4 @}
@end example
@noindent
There is also a form of scoping: in the following example, the
-@code{\paper} block also contains a @code{traLaLa} variable, which is
+@code{\layout} block also contains a @code{traLaLa} variable, which is
independent of the outer @code{\traLaLa}.
@example
- traLaLa = \notes @{ c'4 d'4 @}
- \paper @{ traLaLa = 1.0 @}
+ traLaLa = @{ c'4 d'4 @}
+ \layout @{ traLaLa = 1.0 @}
@end example
@c
In effect, each input file is a scope, and all @code{\header},
-@code{\midi} and @code{\paper} blocks are scopes nested inside that
+@code{\midi} and @code{\layout} blocks are scopes nested inside that
toplevel scope.
Both variables and scoping are implemented in the GUILE module system.
An anonymous Scheme module is attached to each scope. An assignment of
the form
@example
- traLaLa = \notes @{ c'4 d'4 @}
+ traLaLa = @{ c'4 d'4 @}
@end example
@noindent
is internally converted to a Scheme definition
@example
- (define traLaLa @var{Scheme value of ``@code{\notes ... }''})
+ (define traLaLa @var{Scheme value of ``@code{... }''})
@end example
This means that input variables and Scheme variables may be freely
imported in a @code{\score} by means of a second variable
@code{twice}:
@example
- traLaLa = \notes @{ c'4 d'4 @}
+ traLaLa = @{ c'4 d'4 @}
#(define newLa (map ly:music-deep-copy
(list traLaLa traLaLa)))
#(define twice
(make-sequential-music newLa))
- \score @{ \twice @}
+ @{ \twice @}
@end example
In the above example, music expressions can be `exported' from the
input to the Scheme interpreter. The opposite is also possible. By
wrapping a Scheme value in the function @code{ly:export}, a Scheme
-value is interpreted as if it were entered in LilyPond syntax: instead
+value is interpreted as if it were entered in LilyPond syntax. Instead
of defining @code{\twice}, the example above could also have been
written as
@example
@dots{}
- \score @{ #(ly:export (make-sequential-music newLa)) @}
+ @{ #(ly:export (make-sequential-music newLa)) @}
@end example
@refbugs
-Mixing Scheme and lily identifiers is not possible with @code{--safe}.
+Mixing Scheme and LilyPond identifiers is not possible with the
+@code{--safe} option.
@node Internal music representation
@subsection Internal music representation
music object in the @code{element} object. For example,
@internalsref{SequentialMusic} has its children in @code{elements},
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}.
+@code{element}. The body of a repeat is stored in the @code{element}
+property of @internalsref{RepeatedMusic}, and the alternatives in
+@code{elements}.
functions:
@example
- applymusic = #(def-music-function (location func music) (procedure? ly:music?)
+ applymusic = #(def-music-function (location func music)
+ (procedure? ly:music?)
(func music))
@end example
@end example
@noindent
-This means that the scheme function @var{func} is called with
+This means that the Scheme function @var{func} is called with
@var{music} as its argument. The return value of @var{func} is the
result of the entire expression. @var{func} may read and write music
properties using the functions @code{ly:music-property} and
@code{ly:music-set-property!}.
An example is a function that reverses the order of elements in
-its argument:
+its argument,
@lilypond[verbatim,raggedright]
#(define (rev-music-1 m)
(ly:music-set-property! m 'elements (reverse
(ly:music-property m 'elements)))
m)
- \score { \notes \applymusic #rev-music-1 { c4 d4 } }
+ \applymusic #rev-music-1 { c4 d4 }
@end lilypond
The use of such a function is very limited. The effect of this
function is void when applied to an argument which is does not have
-multiple children. The following function application has no effect:
+multiple children. The following function application has no effect
@example
\applymusic #rev-music-1 \grace @{ c4 d4 @}
@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{\applymusic} 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
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
-LilyPond input to other formats (@inputfileref{input/test,to-xml.ly})
+exporting LilyPond input to other formats
+(@inputfileref{input/test,to-xml.ly})
+
+@cindex internal storage
+@cindex @code{\displayMusic}
+When writing a music function, it is often instructive to inspect how
+a music expression is stored internally. This can be done with the
+music function @code{\displayMusic}
@seealso
@node Using LilyPond syntax inside Scheme
@subsection 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
+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.
+Scheme, with the dedicated @code{#@{ ... #@}} syntax.
The following two expressions give equivalent music expressions:
@example
mynotes = @{ \override Stem #'thickness = #4
- \notes @{ c'8 d' @} @}
+ @{ c'8 d' @} @}
#(define mynotes #@{ \override Stem #'thickness = #4
- \notes @{ c'8 d' @} #@})
+ @{ 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.
+@code{SequentialMusic} music object, is then returned and usable in Scheme.
-Arbitrary scheme forms, including variables, can be used in @code{#@{ ... #@}}
+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
#(use-modules (ice-9 optargs))
#(define* (textpad padding #:optional once?)
(ly:export ; this is necessary for using the expression
- ; directly inside a \notes block
+ ; directly inside a 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'^"5"
}
- }
@end lilypond
Here, the variable @code{padding} is a number; music expression
$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
this new expression. Thus, this example is equivalent to:
@example
- \score @{
- \notes @{
+ @{
c'^"1"
@{ \override TextScript #'padding = #3
@{ c'^"2" c'^"3"@}
@}
c'^"4"
@}
- @}
@end example
This function may also be defined as a music function:
$music
\revert TextScript #'padding #})
- \score {
- \notes {
+ {
c'^"1"
\withPadding #3
{ c'^"2" c'^"3"}
c'^"4"
}
- }
@end lilypond
@node Markup programmer interface
@section Markup programmer interface
+Markups implemented as special Scheme functions. When applied with as
+arguments an output definition (@code{\layout} or @code{\paper}),
+and a list of properties and other arguments, produce a Stencil
+object.
@menu
-* Markup construction in scheme::
+* Markup construction in Scheme::
+* How markups work internally ::
* Markup command definition::
@end menu
-@node Markup construction in scheme
-@subsection Markup construction in scheme
+@node Markup construction in Scheme
+@subsection Markup construction in Scheme
@cindex defining markup commands
@noindent
This example exposes the main translation rules between regular
-LilyPond markup syntax and scheme markup syntax, which are summed up
+LilyPond markup syntax and Scheme markup syntax, which are summed up
is this table:
@multitable @columnfractions .5 .5
@item @b{LilyPond} @tab @b{Scheme}
@end lisp
is illegal. One should use the @code{make-line-markup} (resp
@code{make-center-markup}, @code{make-column-markup}) function
-instead:
+instead,
@lisp
(markup (make-line-markup (fun-that-returns-markups)))
@end lisp
+@node How markups work internally
+@subsection How markups work internally
+
+In a markup like
+
+@example
+ \raise #0.5 "foo"
+@end example
+
+@noindent
+@code{\raise} is actually represented by the @code{raise-markup}
+function. The markup expression is stored as
+
+@example
+ (list raise-markup 0.5 (list simple-markup 'latin1 "foo"))
+@end example
+
+@noindent
+In this case, @code{latin1} is the input encoding, which is set with
+the @code{\encoding} command.
+
+When the markup is converted to printable objects (Stencils), the
+raise markup is called as
+
+@example
+ (apply raise-markup
+ @var{\layout object}
+ @var{list of property alists}
+ 0.5
+ @var{the "foo" markup})
+@end example
+
+The @code{raise-markup} first creates the stencil for the @code{foo}
+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}.
+
@node Markup command definition
@subsection Markup command definition
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} ...)
+(def-markup-command (@var{command-name} @var{layout} @var{props} @var{arg1} @var{arg2} ...)
(@var{arg1-type?} @var{arg2-type?} ...)
..command body..)
@end lisp
@var{i}th command argument
@item argi-type?
a type predicate for the i@var{th} argument
-@item paper
-the `paper' definition
+@item layout
+the `layout' definition
@item props
a list of alists, containing all active properties.
@end table
take a single argument, of markup type. Therefore, the start of the
definition should read
@example
- (def-markup-command (smallcaps paper props argument) (markup?)
+ (def-markup-command (smallcaps layout props argument) (markup?)
@end example
@noindent
the @code{argument} as a markup, i.e.
@example
- (interpret-markup paper @dots{} argument)
+ (interpret-markup layout @dots{} argument)
@end example
@noindent
defined @code{\smallcaps} command:
@verbatim
-#(def-markup-command (character paper props name) (string?)
+#(def-markup-command (character layout props name) (string?)
"Print the character name in small caps, translated to the left and
top. Syntax: \\character #\"name\""
- (interpret-markup paper props
+ (interpret-markup layout props
(markup "" #:translate (cons -4 2) #:smallcaps name)))
@end verbatim
The final result is as follows:
@verbatim
-\score {
- \notes { \fatText
+ { \fatText
c''^\markup \character #"Cleopatra"
e'^\markup \character #"Giulio Cesare"
}
-}
@end verbatim
@lilypond[raggedright]
-#(def-markup-command (smallcaps paper props str) (string?)
+#(def-markup-command (smallcaps layout props str) (string?)
"Print the string argument in small caps. Syntax: \\smallcaps #\"string\""
- (interpret-markup paper props
+ (interpret-markup layout props
(make-line-markup
(map (lambda (s)
(if (= (string-length s) 0)
#:tiny (string-upcase (substring s 1)))))
(string-split str #\Space)))))
-#(def-markup-command (character paper props name) (string?)
+#(def-markup-command (character layout props name) (string?)
"Print the character name in small caps, translated to the left and
top. Syntax: \\character #\"name\""
- (interpret-markup paper props
+ (interpret-markup layout props
(markup "" #:translate (cons -4 0) #:smallcaps name)))
-\score {
- \notes { \fatText
+ { \fatText
c''^\markup \character #"Cleopatra"
e'^\markup \character #"Giulio Cesare"
}
-}
@end lilypond
We have used the @code{caps} font shape, but suppose that our font
letter a little larger:
@example
-#(def-markup-command (smallcaps paper props str) (string?)
+#(def-markup-command (smallcaps layout props str) (string?)
"Print the string argument in small caps."
- (interpret-markup paper props
+ (interpret-markup layout props
(make-line-markup
(map (lambda (s)
(if (= (string-length s) 0)
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
+to the @code{interpret-markup} function, with the @code{layout} and
@code{props} arguments.