@c -*- coding: utf-8; mode: texinfo; -*-
@ignore
- Translation of GIT committish: 7b70644b95f383b4281e9ffa146d315d2ada11d3
+ Translation of GIT committish: 70aaf0159410169678942abd39eb13c876521437
When revising a translation, copy the HEAD committish of the
version that you are working on. For details, see the Contributors'
Guide, node Updating translation committishes..
@end ignore
-@c \version "2.12.0"
+@c \version "2.13.36"
@c Translators: Till Paala
Fortgeschrittene Anpassungen können mithilfe der Programmiersprache
Scheme vorgenommen werden. Wenn Sie Scheme nicht kennen, gibt
es eine grundlegende Einleitung in LilyPonds
-@rlearning{Scheme-Übung}.
+@ref{Scheme-Übung}.
@menu
* Musikalische Funktionen::
-* Schnittstelle für Programmierer::
-* Komplizierte Funktionen erstellen::
-* Programmierungsschnittstelle für Textbeschriftungen::
+* Textbeschriftungsfunktionen::
* Kontexte für Programmierer::
-* Scheme-Vorgänge als Eigenschaften::
-* Scheme-Code anstelle von \tweak verwenden::
+* Callback-Funktionen::
+* Scheme-Code innerhalb LilyPonds::
* Schwierige Korrekturen::
@end menu
@translationof Music functions
Dieser Abschnitt behandelt die Erstellung von musikalischen Funktionen
-innerhalb von LilyPond.
+innerhalb von LilyPond. @emph{Musikalische Funktionen} sind Scheme-Prozeduren,
+die musikalische Ausdrücke automatisch erstellen können und dadurch die
+Eingabedatei maßgeblich vereinfachen können.
@menu
-* Überblick über musikalische Funktionen::
+* Syntax der musikalischen Funktionen::
* Einfache Ersetzungsfunktionen::
-* Paarige Ersetzungsfunktionen::
+* Mittlere Ersetzungsfunktionen::
* Mathematik in Funktionen::
-* Leere Funktionen::
* Funktionen ohne Argumente::
-* Überblick über vorhandene musikalische Funktionen::
+* Leere Funktionen::
@end menu
-@node Überblick über musikalische Funktionen
-@subsection Überblick über musikalische Funktionen
-@translationof Overview of music functions
+@node Syntax der musikalischen Funktionen
+@subsection Syntax der musikalischen Funktionen
+@translationof Music function syntax
-Es ist einfach, eine Funktion zu erstellen, die Variablen
-im LilyPond-Code ersetzt. Die allgemeine Form derartiger
-Funktionen ist
+Die allgemeine Form von musikalischen Funktionen ist:
@example
function =
-#(define-music-function (parser location @var{var1} @var{var2}...@var{vari}... )
- (@var{var1-type?} @var{var2-type?}...@var{vari-type?}...)
- #@{
- @emph{...Noten...}
- #@})
+#(define-music-function
+ (parser location @var{Arg1} @var{Arg2} @dots{})
+ (@var{Typ1?} @var{Typ2?} @dots{})
+ @var{Noten})
@end example
@noindent
wobei
@multitable @columnfractions .33 .66
-@item @var{vari} @tab die @var{i}te Variable
-@item @var{vari-type?} @tab die Art der @var{i}ten Variable
-@item @var{...Noten...} @tab normaler LilyPond-Code, in dem Variablen
-wie @code{#$var1} usw. benutzt werden.
-@end multitable
+@item @var{ArgN}
+@tab das @var{n}te Argument
-Die folgenden Eingabetypen können als Variablen in einer musikalischen
-Funktion benutzt werden. Diese Liste ist nicht vollständig -- siehe
-auch andere Dokumentationen überScheme für weitere Variablenarten.
+@item @var{TypN?}
+@tab ein Scheme-Typenprädikat (engl. type predicate), für welches
+@code{@var{ArgN}} @code{#t} ausgeben muss
+
+@item @var{...Noten...}
+@tab ein musikalischer Ausdruck, optional in Scheme geschrieben, mit allem
+LilyPond-Code in Raute/geschweifte Klammer eingeschlossen
+(@tie{}@w{@code{#@{@dots{}#@}}}@tie{}). Innerhalb der LilyPond-Codeumgebungen
+wird @code{$} eingesetzt, um auf Funktionsargumente zu verweisen (etwa
+@samp{$Arg1}), oder ein neuer Scheme-Ausdruck muss begonnen werden,
+der die Funktionsargumente enthält (etwa @w{@samp{$(cons Arg1 Arg2)}}).
-@multitable @columnfractions .33 .66
-@headitem Eingabetyp @tab @var{vari-type?}-Notation
-@item Ganzzahl @tab @code{integer?}
-@item Float (Dezimalzahl) @tab @code{number?}
-@item Zeichenkette @tab @code{string?}
-@item Textbeschriftung @tab @code{markup?}
-@item Musikalischer Ausdruck @tab @code{ly:music?}
-@item Ein Variablenpaar @tab @code{pair?}
@end multitable
-Die Argumente @code{parser} und @code{location} sind zwingend erforderlich
-und werden in einigen fortgeschrittenen Situationen eingesetzt. Das
-Argument @code{parser} wird benutzt, um auf den Wert einer weiteren
-LilyPond-Variable zuzugreifen. Das Argument @code{location} wird
-benutzt, um den @qq{Ursprung} des musikalischen Ausdrucks zu definieren, der von
-der musikalischen Funktion erzeugt wird. Das hilft, wenn ein
-Syntaxfehler auftaucht: in solchen Fällen kann LilyPond mitteilen,
-an welcher Stelle in der Eingabedatei sich der Fehler befindet.
+Eine Liste der möglichen Typenprädikate findet sich in
+@ruser{Vordefinierte Typenprädikate}. Durch den Benutzer definierte
+Typenprädikate sind auch erlaubt.
+@seealso
-@node Einfache Ersetzungsfunktionen
-@subsection Einfache Ersetzungsfunktionen
-@translationof Simple substitution functions
+Notationsreferenz:
+@ruser{Vordefinierte Typenprädikate}.
-Hier ist ein einfaches Beispiel:
+Installierte Dateien:
+@file{lily/music-scheme.cc},
+@file{scm/c++.scm},
+@file{scm/lily.scm}.
-@lilypond[quote,verbatim,ragged-right]
-padText = #(define-music-function (parser location padding) (number?)
- #{
- \once \override TextScript #'padding = #$padding
- #})
-
-\relative c''' {
- c4^"piu mosso" b a b
- \padText #1.8
- c4^"piu mosso" d e f
- \padText #2.6
- c4^"piu mosso" fis a g
-}
-@end lilypond
-Musikalische Ausdrücke können auch ersetzt werden:
-
-@lilypond[quote,verbatim,ragged-right]
-custosNote = #(define-music-function (parser location note)
- (ly:music?)
- #{
- \once \override Voice.NoteHead #'stencil =
- #ly:text-interface::print
- \once \override Voice.NoteHead #'text =
- \markup \musicglyph #"custodes.mensural.u0"
- \once \override Voice.Stem #'stencil = ##f
- $note
- #})
-
-{ c' d' e' f' \custosNote g' }
-@end lilypond
-
-Mehrere Variablen können benutzt werden:
+@node Einfache Ersetzungsfunktionen
+@subsection Einfache Ersetzungsfunktionen
+@translationof Simple substitution functions
-@lilypond[quote,verbatim,ragged-right]
-tempoPadded = #(define-music-function (parser location padding tempotext)
- (number? string?)
-#{
- \once \override Score.MetronomeMark #'padding = $padding
- \tempo \markup { \bold $tempotext }
-#})
+Einfache Ersetzungsfunktionen sind musikalische Funktionen, deren
+musikalische Ausgabe-Funktion im LilyPond-Format geschrieben ist
+und Funktionsargumente in der Ausgabefunktion enthält. Sie werden
+beschrieben in @ruser{Beispiele der Ersetzungsfunktionen}
-\relative c'' {
- \tempo \markup { "Low tempo" }
- c4 d e f g1
- \tempoPadded #4.0 #"High tempo"
- g4 f e d c1
-}
-@end lilypond
+@node Mittlere Ersetzungsfunktionen
+@subsection Mittlere Ersetzungsfunktionen
+@translationof Intermediate substitution functions
-@node Paarige Ersetzungsfunktionen
-@subsection Paarige Ersetzungsfunktionen
-@translationof Paired substitution functions
+Mittlere Ersetzungsfunktionen setzen sich aus einer Mischung von
+Scheme-Code und LilyPond-Code in der musikalischen Ausgabe-Funktion
+zusammen.
Einige @code{\override}-Befehle benötigen ein Zahlenpaar
-(als @code{cons}-Zelle in Scheme bezeichnet). Um beide Zahlen
-einer Funktion zuzuweisen, kann entweder die Variable @code{pair?}
-benutzt werden oder die @code{cons} in die musikalische Funktion
-eingefügt werden.
+(als @code{cons}-Zelle in Scheme bezeichnet).
+
+Das Paar kann direkt an die musikalische Funktion
+mit der Variable @code{pair?} weitergeleitet werden:
-@quotation
@example
manualBeam =
-#(define-music-function (parser location beg-end)
- (pair?)
-#@{
- \once \override Beam #'positions = #$beg-end
-#@})
-
-\relative @{
+#(define-music-function
+ (parser location beg-end)
+ (pair?)
+ #@{
+ \once \override Beam #'positions = $beg-end
+ #@})
+
+\relative c' @{
\manualBeam #'(3 . 6) c8 d e f
@}
@end example
-@end quotation
-@noindent
-oder
+Anstelle dessen können auch die Zahlen, aus denen das Paar besteht,
+einzeln als eigenständige Argumente weitergeleitet und der
+Scheme-Code, der das Paar erstellt, in die musikalische Funktion
+augenommen werden:
@lilypond[quote,verbatim,ragged-right]
manualBeam =
-#(define-music-function (parser location beg end)
- (number? number?)
-#{
- \once \override Beam #'positions = #(cons $beg $end)
-#})
-
-\relative {
+#(define-music-function
+ (parser location beg end)
+ (number? number?)
+ #{
+ \once \override Beam #'positions = $(cons beg end)
+ #})
+
+\relative c' {
\manualBeam #3 #6 c8 d e f
}
@end lilypond
auch Scheme-Programmcode enthalten:
@lilypond[quote,verbatim,ragged-right]
-AltOn = #(define-music-function (parser location mag) (number?)
- #{ \override Stem #'length = #$(* 7.0 mag)
+AltOn =
+#(define-music-function
+ (parser location mag)
+ (number?)
+ #{
+ \override Stem #'length = $(* 7.0 mag)
\override NoteHead #'font-size =
- #$(inexact->exact (* (/ 6.0 (log 2.0)) (log mag))) #})
+ $(inexact->exact (* (/ 6.0 (log 2.0)) (log mag)))
+ #})
AltOff = {
\revert Stem #'length
\revert NoteHead #'font-size
}
-{ c'2 \AltOn #0.5 c'4 c'
- \AltOn #1.5 c' c' \AltOff c'2 }
+\relative c' {
+ c2 \AltOn #0.5 c4 c
+ \AltOn #1.5 c c \AltOff c2
+}
@end lilypond
@noindent
zu integrieren:
@lilypond[quote,verbatim,ragged-right]
-withAlt = #(define-music-function (parser location mag music) (number? ly:music?)
- #{ \override Stem #'length = #$(* 7.0 mag)
+withAlt =
+#(define-music-function
+ (parser location mag music)
+ (number? ly:music?)
+ #{
+ \override Stem #'length = $(* 7.0 mag)
\override NoteHead #'font-size =
- #$(inexact->exact (* (/ 6.0 (log 2.0)) (log mag)))
+ $(inexact->exact (* (/ 6.0 (log 2.0)) (log mag)))
$music
\revert Stem #'length
- \revert NoteHead #'font-size #})
+ \revert NoteHead #'font-size
+ #})
-{ c'2 \withAlt #0.5 {c'4 c'}
- \withAlt #1.5 {c' c'} c'2 }
+\relative c' {
+ c2 \withAlt #0.5 { c4 c }
+ \withAlt #1.5 { c c } c2
+}
@end lilypond
-@node Leere Funktionen
-@subsection Leere Funktionen
-@translationof Void functions
-
-Eine musikalische Funktion muss einen musikalischen Ausdruck
-ausgeben, aber in manchen Fällen müssen Funktionen erstellt werden,
-die keine Notation enthalten (wie etwa eine Funktion, mit der
-man @qq{Point and Click} ausschalten kann). Um das vornehmen zu
-können, wird ein @code{leere}r musikalischer Ausdruck ausgegeben.
-
-Das ist der Grund, warum die Form, die ausgegeben wird,
-@code{(make-music ...)} heißt. Wird die Eigenschaft
-@code{'void} (engl. für @qq{leer}) auf @code{#t} gesetzt, wird der
-Parser angewiesen, den ausgegebenen musikalischen Ausdruck zu ignorieren.
-Der maßgebliche Teil der @code{'void}-Funktion ist also die Verarbeitung,
-die die Funktion vornimmt, nicht der musikalische Ausdruck, der ausgegeben
-wird.
-
-@example
-noPointAndClick =
-#(define-music-function (parser location) ()
- (ly:set-option 'point-and-click #f)
- (make-music 'SequentialMusic 'void #t))
-...
-\noPointAndClick % disable point and click
-@end example
-
-
@node Funktionen ohne Argumente
@subsection Funktionen ohne Argumente
@translationof Functions without arguments
@example
displayBarNum =
-#(define-music-function (parser location) ()
+#(define-music-function
+ (parser location)
+ ()
(if (eq? #t (ly:get-option 'display-bar-numbers))
#@{ \once \override Score.BarNumber #'break-visibility = ##f #@}
#@{#@}))
aufgerufen werden.
-@node Überblick über vorhandene musikalische Funktionen
-@subsection Überblick über vorhandene musikalische Funktionen
-@translationof Overview of available music functions
-
-@c fixme ; this should be move somewhere else?
-Die folgenden Befehle sind musikalische Funktionen:
-
-@include identifiers.tely
-
-
-
-@node Schnittstelle für Programmierer
-@section Schnittstelle für Programmierer
-@translationof Programmer interfaces
-
-Dieser Abschnitt zeigt, wie LilyPond und
-Scheme gemischt werden können.
-
-@menu
-* Eingabevariablen und Scheme::
-* Interne Repräsentation der Musik::
-@end menu
-
-
-@node Eingabevariablen und Scheme
-@subsection Eingabevariablen und Scheme
-@translationof Input variables and Scheme
-
-Das Eingabeformat unterstützt die Notation von Variablen: im
-folgenden Beispiel wird ein musikalischer Ausdruck einer Variable
-mit der Bezeichnung @code{traLaLa} zugewiesen:
-
-@example
-traLaLa = @{ c'4 d'4 @}
-@end example
-
-Der Geltungsbereich von Variablen ist beschränkt: im folgenden
-Beispiel enthält die @code{\layout}-Umgebung auch eine
-@code{traLaLa}-vVariable, die unabhängig von der äußeren
-@code{\traLaLa}-Variable ist:
-
-@example
-traLaLa = @{ c'4 d'4 @}
-\layout @{ traLaLa = 1.0 @}
-@end example
-
-Grundsätzlich ist jede Eingabedatei ein Geltungsbereich, und
-alle @code{\header}-, @code{\midi}- und @code{\layout}-Umgebungen
-sind Geltungsbereiche, die unterhalb des globalen Geltungsbereiches
-angeordnet sind.
-
-Sowohl Variablen als auch Geltungsbereiche sind in Form des
-GUILE-Modulsystems implementiert. Ein anonymes Scheme-Modul
-wird an jeden Geltunsbereich angehängt. Eine Zuweisung der form
-
-@example
-traLaLa = @{ c'4 d'4 @}
-@end example
-
-@noindent
-wird intern in die Scheme-Definition
-
-@example
-(define traLaLa @var{Scheme-Wert von `@code{... }'})
-@end example
-@noindent
-umgewandelt.
-
-Das bedeutet, dass Eingabe- und Scheme-Variablen frei vermischt
-werden können. Im nächsten Beispiel wird ein Notenfragment in
-der Variable @code{traLaLa} gespeichert und mithilfe von Schme
-dupliziert. Das Ergebnis wird in eine @code{\score}-Umgebung
-mit der zweiten Variable @code{twice} integriert:
-
-@lilypond[verbatim]
-traLaLa = { c'4 d'4 }
-
-%% dummy action to deal with parser lookahead
-#(display "this needs to be here, sorry!")
-
-#(define newLa (map ly:music-deep-copy
- (list traLaLa traLaLa)))
-#(define twice
- (make-sequential-music newLa))
-
-{ \twice }
-@end lilypond
-
-In diesem Beispiel geschieht die Zuweisung, nachdem der Parser
-festgestellt hat, dass nichts interessantes mehr nach
-@code{traLaLa = @{ ... @}} vorkommt. Ohne die Pseudovariable
-in dem Beispiel würde die @code{newLa}-Devinition ausgeführt
-werden, bevor @code{traLaLa} definiert ist, was zu einem
-Syntax-Fehler führen würde.
-
-Das obige Beispiel zeigt, wie man musikalische Ausdrücke
-von der Eingabe in den Scheme-Interpretierer @qq{exportieren}
-kann. Es geht auch in die andere Richtung. Indem man einen
-Scheme-Wert in die Funktion @code{ly:export} einpackt, wird
-der Scheme-Wert interpretiert als ob er in LilyPond-Syntax
-notiert worden wäre. Anstatt @code{\twice} zu definieren,
-hätte man also auch schreiben können:
+@node Leere Funktionen
+@subsection Leere Funktionen
+@translationof Void functions
-@example
-...
-@{ #(ly:export (make-sequential-music (list newLa))) @}
-@end example
+Eine musikalische Funktion muss einen musikalischen Ausdruck
+ausgeben, aber in manchen Fällen müssen Funktionen erstellt werden,
+die keine Noten enthalten (wie etwa eine Funktion, mit der
+man @qq{Point and Click} ausschalten kann). Um das vornehmen zu
+können, wird ein @code{leere}r musikalischer Ausdruck ausgegeben.
-Scheme-Code wird sofort ausgewertet, wenn der Parser darauf
-stößt. Um Scheme-Code in einem Makro zu definieren (das dann
-erst später aufgerufen werden soll), müssen leere Funktionen
-benutzt werden (siehe @ref{Leere Funktionen}) oder das Folgende:
+Das ist der Grund, warum die Form, die ausgegeben wird,
+@w{@code{(make-music @dots{})}} heißt. Wird die Eigenschaft
+@code{'void} (engl. für @qq{leer}) auf @code{#t} gesetzt, wird der
+Parser angewiesen, den ausgegebenen musikalischen Ausdruck zu ignorieren.
+Der maßgebliche Teil der @code{'void}-Funktion ist also die Verarbeitung,
+die die Funktion vornimmt, nicht der musikalische Ausdruck, der ausgegeben
+wird.
@example
-#(define (nopc)
- (ly:set-option 'point-and-click #f))
-
+noPointAndClick =
+#(define-music-function
+ (parser location)
+ ()
+ (ly:set-option 'point-and-click #f)
+ (make-music 'SequentialMusic 'void #t))
...
-#(nopc)
-@{ c'4 @}
-@end example
-
-@knownissues
-
-Scheme- und LilyPond-Variablen können im LilyPond-Modus mit der
-@code{--safe}-Option nicht vermischt werden.
-
-
-@node Interne Repräsentation der Musik
-@subsection Interne Repräsentation der Musik
-@translationof Internal music representation
-
-Wenn ein musikalischer Ausdruck ausgewertet wird, wird er in eine
-Anzahl von musikalischen Scheme-Objekten konvertiert. Die Eigenschaft, die ein
-musikalisches Objekt definiert, ist, dass es Zeit einnimmt. Zeit ist
-eine rationale Zahl, die die Länge eines Stückes in ganzen Noten
-misst.
-
-Ein musikalisches Objekt hat drei Typusarten:
-@itemize
-@item
-musikalische Bezeichnung: Jeder musikalische Ausdruck hat eine Bezeichnung.
-Eine Note beispielsweise führt zu einem @rinternals{NoteEvent} und
-@code{\simultaneous} führt zu @rinternals{SimultaneousMusic}. Eine Liste
-aller möglichen Ausdrücke findet sich in der Referenz der Interna, unter
-@rinternals{Music expressions}.
-
-@item
-@q{Typ} oder Schnittstelle: Jede musikalische Bezeichnung hat mehrere
-@qq{Typen} oder Schnittstellten, beispielsweise ist eine Note ein
-@code{event}, ober sie ist auch ein @code{note-event}, ein
-@code{rhythmic-event} und ein @code{melodic-event}. Alle diese
-Notationsklassen finden sich in der Referenz der Interna unter
-@rinternals{Music classes}.
-
-@item
-C++-Objekt: Jedes musikalische Objekt wird von einem Objekt der
-C++-Klasse @code{Music} repräsentiert.
-@end itemize
-
-Die eigentlich Information eines musikalischen Ausdrucks ist in
-Eigenschaften gespeichert. Ein @rinternals{NoteEvent} hat zum
-Beispiel @code{pitch}- und @code{duration}-Eigenschaften, die
-die Tonhöhe und die Dauer dieser Note speichern. Eine Liste aller
-verfügbaren Eigenschaften findet sich in der Referenz der Interna unter
-@rinternals{Music properties}.
-
-Ein zusammengesetzter musikalischer Ausdruck ist ein musikalisches
-Objekt, das andere Objekte in seinen Eigenschaften enthält. Eine Liste
-der Objekte kann in der @code{elements}-Eigenschaft eines
-musikalischen Objektes gespeichert werden, oder ein einziges
-@qq{Kind}-Objekt in der @code{element}-Eigenschaft. Sa hat etwa
-@rinternals{SequentialMusic} seine @qq{Kinder} in @code{elements},
-und @rinternals{GraceMusic} hat sein einziges Argument in
-@code{element}. Der Hauptteil einer Wiederholung wird in der
-@code{element}-Eigenschaft von @rinternals{RepeatedMusic} gespeichert,
-und die Alternativen in @code{elements}.
-
-
-
-@node Komplizierte Funktionen erstellen
-@section Komplizierte Funktionen erstellen
-@translationof Building complicated functions
-
-Dieser Abschnitt zeigt, wie man Information zusammensucht,
-um komplizierte musikalische Funktionen zu erstellen.
-
-@menu
-* Musikalische Funktionen darstellen::
-* Eigenschaften von Musikobjekten::
-* Verdoppelung einer Note mit Bindebögen (Beispiel)::
-* Artikulationszeichen zu Noten hinzufügen (Beispiel)::
-@end menu
-
-
-@node Musikalische Funktionen darstellen
-@subsection Musikalische Funktionen darstellen
-@translationof Displaying music expressions
-
-@cindex interne Speicherung
-@cindex Musikausdrücke anzeigen
-@cindex Anzeigen von Musikausdrücken
-
-@funindex displayMusic
-@funindex \displayMusic
-
-Wenn man eine musikalische Funktion erstellt, ist es oft
-hilfreich sich anzuschauen, wie musikalische Funktionen
-intern gespeichert werden. Das kann mit der Funktion
-@code{\displayMusic} erreicht werden:
-
-@example
-@{
- \displayMusic @{ c'4\f @}
-@}
+\noPointAndClick % Point and Click ausschalten
@end example
-@noindent
-zeigt:
-@example
-(make-music
- 'SequentialMusic
- 'elements
- (list (make-music
- 'EventChord
- 'elements
- (list (make-music
- 'NoteEvent
- 'duration
- (ly:make-duration 2 0 1 1)
- 'pitch
- (ly:make-pitch 0 0 0))
- (make-music
- 'AbsoluteDynamicEvent
- 'text
- "f")))))
-@end example
-
-Normalerweise gibt LilyPond diese Ausgabe auf der Konsole mit
-allen anderen Nachrichten aus. Um die wichtigen Nachrichten
-in einer Datei zu speichern, kann die Ausgabe in eine Datei
-umgeleitet werden:
-
-@example
-lilypond file.ly >display.txt
-@end example
-
-Mit etwas Umformatierung ist die gleiche Information sehr viel
-einfacher zu lesen:
-
-@example
-(make-music 'SequentialMusic
- 'elements (list (make-music 'EventChord
- 'elements (list (make-music 'NoteEvent
- 'duration (ly:make-duration 2 0 1 1)
- 'pitch (ly:make-pitch 0 0 0))
- (make-music 'AbsoluteDynamicEvent
- 'text "f")))))
-@end example
-
-Eine musikalische @code{@{ ... @}}-Sequenz hat die Bezeichnung
-@code{SequentialMusic} und ihre inneren Ausdrücke werden als
-Liste in seiner @code{'elements}-Eigenschaft gespeichert. Eine
-Note ist als als ein @code{EventChord}-Ausdruck dargestellt,
-der ein @code{NoteEvent}-Objekt (welches Dauer und
-Tonhöhe speichert) und zusätzliche Information enthält (in
-diesem Fall ein @code{AbsoluteDynamicEvent} mit einer
-@code{"f"}-Text-Eigenschaft.
-
-
-@node Eigenschaften von Musikobjekten
-@subsection Eigenschaften von Musikobjekten
-@translationof Music properties
-
-Das @code{NoteEvent}-Objekt ist das erste Objekt der
-@code{'elements}-Eigenschaft von @code{someNote}.
-
-@example
-someNote = c'
-\displayMusic \someNote
-===>
-(make-music
- 'EventChord
- 'elements
- (list (make-music
- 'NoteEvent
- 'duration
- (ly:make-duration 2 0 1 1)
- 'pitch
- (ly:make-pitch 0 0 0))))
-@end example
-
-Die @code{display-scheme-music}-Funktion ist die Funktion, die von
-@code{\displayMusic} eingesetzt wird, um die Scheme-Repräsentation
-eines musikalischen Ausdrucks anzuzeigen.
-
-@example
-#(display-scheme-music (first (ly:music-property someNote 'elements)))
-===>
-(make-music
- 'NoteEvent
- 'duration
- (ly:make-duration 2 0 1 1)
- 'pitch
- (ly:make-pitch 0 0 0))
-@end example
-Danach wird die Tonhöhe der Note von der @code{'pitch}-Eigenschaft
-des @code{NoteEvent}-Objektes gelesen:
-
-@example
-#(display-scheme-music
- (ly:music-property (first (ly:music-property someNote 'elements))
- 'pitch))
-===>
-(ly:make-pitch 0 0 0)
-@end example
-
-Die Tonhöhe einer Note kann geändert werden, indem man diese
-@code{'pitch}-Eigenschaft umdefiniert:
-
-@funindex \displayLilyMusic
-@funindex displayLilyMusic
-
-@example
-#(set! (ly:music-property (first (ly:music-property someNote 'elements))
- 'pitch)
- (ly:make-pitch 0 1 0)) ;; Die Tonhöhen auf d' verändern.
-\displayLilyMusic \someNote
-===>
-d'
-@end example
-
-
-@node Verdoppelung einer Note mit Bindebögen (Beispiel)
-@subsection Verdoppelung einer Note mit Bindebögen (Beispiel)
-@translationof Doubling a note with slurs (example)
-
-In diesem Abschnitt soll gezeigt, werden, wie man eine
-Funktion erstellt, die eine Eingabe wie @code{a}
-nach @code{a( a)} umdefiniert. Dazu wird zuerst die
-interne Repräsentation der Musik betrachtet, die
-das Endergebnis darstellt:
-
-@example
-\displayMusic@{ a'( a') @}
-===>
-(make-music
- 'SequentialMusic
- 'elements
- (list (make-music
- 'EventChord
- 'elements
- (list (make-music
- 'NoteEvent
- 'duration
- (ly:make-duration 2 0 1 1)
- 'pitch
- (ly:make-pitch 0 5 0))
- (make-music
- 'SlurEvent
- 'span-direction
- -1)))
- (make-music
- 'EventChord
- 'elements
- (list (make-music
- 'NoteEvent
- 'duration
- (ly:make-duration 2 0 1 1)
- 'pitch
- (ly:make-pitch 0 5 0))
- (make-music
- 'SlurEvent
- 'span-direction
- 1)))))
-@end example
-
-Eine schlechte Nachricht ist, dass die
-@code{SlurEvent}-Ausdrücke @qq{innerhalb}
-der Noten (bzw. innerhalb der
-@code{EventChord}-Ausdrücke) hinzugefügt werden müssen.
-
-Jetzt folgt eine Betrachtung der Eingabe:
-
-@example
-(make-music
- 'SequentialMusic
- 'elements
- (list (make-music
- 'EventChord
- 'elements
- (list (make-music
- 'NoteEvent
- 'duration
- (ly:make-duration 2 0 1 1)
- 'pitch
- (ly:make-pitch 0 5 0))))))
-@end example
-
-In der gewünschten Funktion muss also dieser Ausdruck
-kopiert werden (sodass zwei Noten vorhanden sind, die
-eine Sequenz bilden), dann müssen @code{SlurEvent}
-zu der @code{'elements}-Eigenschaft jeder Noten hinzugefügt
-werden, und schließlich muss eine @code{SequentialMusic}
-mit den beiden @code{EventChords} erstellt werden.
-
-@example
-doubleSlur = #(define-music-function (parser location note) (ly:music?)
- "Return: @{ note ( note ) @}.
- `note' is supposed to be an EventChord."
- (let ((note2 (ly:music-deep-copy note)))
- (set! (ly:music-property note 'elements)
- (cons (make-music 'SlurEvent 'span-direction -1)
- (ly:music-property note 'elements)))
- (set! (ly:music-property note2 'elements)
- (cons (make-music 'SlurEvent 'span-direction 1)
- (ly:music-property note2 'elements)))
- (make-music 'SequentialMusic 'elements (list note note2))))
-@end example
-
-
-@node Artikulationszeichen zu Noten hinzufügen (Beispiel)
-@subsection Artikulationszeichen zu Noten hinzufügen (Beispiel)
-@translationof Adding articulation to notes (example)
-
-Am einfachsten können Artikulationszeichen zu Noten
-hinzugefügt werden, indem man zwei musikalische Funktionen
-in einen Kontext einfügt, wie erklärt in
-@ref{Kontexte erstellen}. Hier soll jetzt eine musikalische
-Funktion entwickelt werden, die das vornimmt.
-
-Eine @code{$variable} innerhalb von @code{#@{...#@}} ist das
-gleiche wie die normale Befehlsform @code{\variable} in
-üblicher LilyPond-Notation. Es ist bekannt dass
-
-@example
-@{ \music -. -> @}
-@end example
-
-@noindent
-in LilyPond nicht funktioniert. Das Problem könnte vermieden
-werden, indem das Artikulationszeichen an eine Pseudonote
-gehängtwird:
-
-@example
-@{ << \music s1*0-.-> @}
-@end example
-
-@noindent
-aber in diesem Beispiel soll gezeigt werden, wie man das in
-Scheme vornimmt. Zunächst wird die Eingabe und die gewünschte
-Ausgabe examiniert:
-
-@example
-% Eingabe
-\displayMusic c4
-===>
-(make-music
- 'EventChord
- 'elements
- (list (make-music
- 'NoteEvent
- 'duration
- (ly:make-duration 2 0 1 1)
- 'pitch
- (ly:make-pitch -1 0 0))))
-=====
-% gewünschte Ausgabe
-\displayMusic c4->
-===>
-(make-music
- 'EventChord
- 'elements
- (list (make-music
- 'NoteEvent
- 'duration
- (ly:make-duration 2 0 1 1)
- 'pitch
- (ly:make-pitch -1 0 0))
- (make-music
- 'ArticulationEvent
- 'articulation-type
- "marcato")))
-@end example
-
-Dabei ist zu sehen, dass eine Note (@code{c4}) als @code{EventChord}
-repräsentiert ist, mit einem @code{NoteEvent}-Ausdruck in ihrer
-Elementenliste. Um eine Marcato-Artikulation hinzuzufügen, muss
-ein @code{ArticulationEvent}-Ausdrcuk zu der Elementeigenschaft
-des @code{EventChord}-Ausdrucks hinzugefügt werden.
-
-Um diese Funktion zu bauen, wird folgerndermaßen begonnen:
-
-@example
-(define (add-marcato event-chord)
- "Add a marcato ArticulationEvent to the elements of `event-chord',
- which is supposed to be an EventChord expression."
- (let ((result-event-chord (ly:music-deep-copy event-chord)))
- (set! (ly:music-property result-event-chord 'elements)
- (cons (make-music 'ArticulationEvent
- 'articulation-type "marcato")
- (ly:music-property result-event-chord 'elements)))
- result-event-chord))
-@end example
-
-Die erste Zeile definiert eine Funktion in Scheme: Die Bezeichnung
-der Funktion ist @code{add-marcato} und sie hat eine Variable
-mit der Bezeichnung @code{event-chord}. In Scheme geht der Typ
-einer Variable oft direkt aus der Bezeichnung hervor (das ist auch
-eine gute Methode für andere Programmiersprachen).
-
-@example
-"Add a marcato..."
-@end example
-
-@noindent
-ist eine (englische) Beschreibung, was diese Funktion tut. Sie ist
-nicht unbedingt notwendig, aber genauso wie klare Variablen-Bezeichnungen
-ist auch das eine gute Methode.
-
-@example
-(let ((result-event-chord (ly:music-deep-copy event-chord)))
-@end example
-
-@code{let} wird benutzt, um die lokalen Variablen zu definieren. Hier
-wird eine lokale Variable benutzt: @code{result-event-chord}. Sie erhält
-den Wert @code{(ly:music-deep-copy event-chord)}. @code{ly:music-deep-copy}
-ist eine LilyPond-spezifische Funktion, die wie alle Funktionen mit dem
-Präfix @code{ly:} versehen ist. Sie wird benutzt, um eine Kopie eines
-musikalischen Ausdrucks anzufertigen. Hier wird @code{event-chord}
-(der Parameter der Funktion) kopiert. Die Funktion soll ja nur ein
-Artikulationszeichen an einen @code{EventChord} gehängt werden, deshalb ist es besser,
-den @code{EventChord}, der als Argument gegeben wurde, nicht zu
-verändern, weil er woanders benutzt werden könnte.
-
-Jetzt gibt es @code{result-event-chord}, wobei es sich um einen
-@code{NoteEventChord}-Ausdruck handelt, welcher gleichzeigt eine Kopie
-von @code{event-chord} ist. Das Makro wird seiner Eigenschaftsliste
-hinzugefügt:
-
-@example
-(set! place new-value)
-@end example
-
-Was in diesem Fall @qq{gesetzt} werden soll (@qq{place}) ist die
-@q{elements}-Eigenschaft des @code{result-event-chord}-Ausdrucks.
-
-@example
-(ly:music-property result-event-chord 'elements)
-@end example
-
-@code{ly:music-property} ist die Funktion, mit der musikalische
-Eigenschaften erreicht werden können (die @code{'elements},
-@code{'duration}, @code{'pitch} usw., die in der Ausgabe von
-@code{\displayMusic} weiter oben angezeigt werden). Der neue
-Wert ist, was ehemals die Elemtneigenschaft war, mit einem
-zusätzlichen Element: dem @code{ArticulationEvent}-Ausdruck,
-der aus der Ausgabe von
-@code{\displayMusic} kopiert werden kann:
-
-@example
-(cons (make-music 'ArticulationEvent
- 'articulation-type "marcato")
- (ly:music-property result-event-chord 'elements))
-@end example
-
-@code{cons} wird benutzt, um ein Element zu einer Liste hinzuzufügen,
-ohne dass die originale Liste verändert wird. Das ist es, was die
-Funktion tun soll: die gleiche Liste, aber mit dem neuen
-@code{ArticulationEvent}-Ausdruck. Die Reihenfolge innerhalb
-der Elementeeigenschaft ist hier nicht relevant.
-
-Wenn schließlich die Marcato-Artikulation zu der entsprechenden
-@code{elements}-Eigenschaft hinzuzugefügt ist, kann
-@code{result-event-chord} ausgegeben werden, darum die letzte Zeile
-der Funktion.
-
-Jetzt wird die @code{add-marcato}-Funktion in eine musikalische
-Funktion umgewandelt:
-
-@example
-addMarcato = #(define-music-function (parser location event-chord)
- (ly:music?)
- "Add a marcato ArticulationEvent to the elements of `event-chord',
- which is supposed to be an EventChord expression."
- (let ((result-event-chord (ly:music-deep-copy event-chord)))
- (set! (ly:music-property result-event-chord 'elements)
- (cons (make-music 'ArticulationEvent
- 'articulation-type "marcato")
- (ly:music-property result-event-chord 'elements)))
- result-event-chord))
-@end example
-
-Eine Überprüfung, dass die Funktion richtig arbeitet, geschieht
-folgendermaßen:
-
-@example
-\displayMusic \addMarcato c4
-@end example
-
-
-@node Programmierungsschnittstelle für Textbeschriftungen
-@section Programmierungsschnittstelle für Textbeschriftungen
-@translationof Markup programmer interface
+@node Textbeschriftungsfunktionen
+@section Textbeschriftungsfunktionen
+@translationof Markup functions
Textbeschriftungselemente sind als besondere Scheme-Funktionen
-definiert, die ein Stencil-Objekt erstellen, dem eine Anzahl
+definiert, die ein @code{Stencil}-Objekt erstellen, dem eine Anzahl
an Argumenten übergeben wird.
@menu
* Beschriftungskonstruktionen in Scheme::
* Wie Beschriftungen intern funktionieren::
* Neue Definitionen von Beschriftungsbefehlen::
-* Neue Definitionen von Beschriftungsbefehlen für Listen::
+* Neue Definitionen von Beschriftungslistenbefehlen::
@end menu
@item @code{\markup Text1} @tab @code{(markup Text1)}
@item @code{\markup @{ Text1 Text2 ... @}} @tab
@code{(markup Text1 Text2 ... )}
-@item @code{\Befehl} @tab @code{#:Befehl}
+@item @code{\Beschriftungsbefehl} @tab @code{#:Beschriftungsbefehl}
@item @code{\Variable} @tab @code{Variable}
@item @code{\center-column @{ ... @}} @tab @code{#:center-column ( ... )}
@item @code{Zeichenkette} @tab @code{"Zeichenkette"}
-@item @code{#scheme-arg} @tab @code{scheme-arg}
+@item @code{#scheme-Arg} @tab @code{scheme-Arg}
@end multitable
@end quotation
@var{die "Textbeispiel"-Beschriftung})
@end example
-Die @code{raise-markup}-Funktion erstellt zunächt den Stencil für die
+Die @code{raise-markup}-Funktion erstellt zunächst den Stencil für die
@code{Textbeispiel}-Beschriftung und verschiebt dann diesen Stencil
um 0.5 Notenlinienzwischenräume nach oben. Das ist ein einfaches
Beispiel. Weitere, kompliziertere Beispiele finden sich nachfolgend
in diesem Abschnitt und in der Datei
-@file{scm/@/define@/-markup@/-commands@/.scm}.
+@file{scm/define-markup-commands.scm}.
@node Neue Definitionen von Beschriftungsbefehlen
@subsection Neue Definitionen von Beschriftungsbefehlen
@translationof New markup command definition
+Dieser Abschnitt behandelt die Definition von neuen Textbeschriftungsbefehlen.
+
+@menu
+* Syntax der Definition von Textbeschriftungsbefehlen::
+* Über Eigenschaften::
+* Ein vollständiges Bespiel::
+* Eingebaute Befehle anpassen::
+@end menu
+
+@node Syntax der Definition von Textbeschriftungsbefehlen
+@unnumberedsubsubsec Syntax der Definition von Textbeschriftungsbefehlen
+@translationof Markup command definition syntax
+
Neue Textbeschriftungsbefehle können mit dem
@code{define-markup-command}-Scheme-Makro definiert werden.
@lisp
-(define-markup-command (@var{befehl-bezeichnung} @var{layout} @var{props} @var{arg1} @var{arg2} ...)
- (@var{arg1-type?} @var{arg2-type?} ...)
+(define-markup-command (@var{befehl-bezeichnung} @var{layout} @var{props} @var{Arg1} @var{Arg2} ...)
+ (@var{Arg1-typ?} @var{Arg2-typ?} ...)
+ [ #:properties ((@var{Eigenschaft1} @var{Standard-Wert1})
+ ...) ]
..Befehlkörper..)
@end lisp
Die Argumente sind:
@table @var
-@item argi
-@var{i}te Befehlsargument
-@item argi-type?
-eine Eigenschaft für das @var{i}te Argument
-@item layout
+@item @var{befehl-bezeichnung}
+die Bezeichnung des Befehls
+
+@item @var{layout}
die @q{layout}-Definition
+
@item props
-eine Liste an alists, in der alle aktiven Eigenschaften enthalten sind
+eine Liste an assoziativen Listen, in der alle aktiven Eigenschaften enthalten sind
+
+@item @var{argi}
+das @var{i}te Befehlsargument
+
+@item @var{argi-type?}
+eine Eigenschaft für das @var{i}te Argument
@end table
-Als einfaches Beispiel soll gezeigt werden, wie man einen
-@code{\smallcaps}-Befehl hinzufügen kann, der die Kapitälchen
-für die Schriftzeichen auswählt. Normalerweise würde man Kapitälchen
-folgendermaßen auswählen:
+Wenn der Befehl Eigenschaften des @code{props}-Arguments benutzt,
+kann das @code{#:properties}-Schlüsselwort benutzt werden um zu
+bestimmen, welche Eigenschaften mit welchen Standard-Werten benutzt
+werden.
-@example
-\markup @{ \override #'(font-shape . caps) Text-in-Kapitälchen @}
-@end example
+Argumente werden nach ihrem Typ unterschieden:
-@noindent
-Damit wird die Kapitälchenschriftart ausgewählt, indem die
-@code{font-shape}-Eigesnchaft auf @code{#'caps} gesetzt wird,
-während @code{Text-in-caps} interpretiert wird.
+@itemize
+@item eine Textbeschriftung entspricht einem Typenprädikat @code{markup?};
+@item eine Textbeschriftungsliste entspricht einem Typenprädikat
+@code{markup-list?};
+@item jedes andere Scheme-Objekt entspricht Typenprädikaten wie etwa
+@code{list?}, @code{number?}, @code{boolean?}, usw.
+@end itemize
-Damit diese Funkion als @code{\smallcaps}-Befehl zur Verfügung
-gestellt werden kann, muss eine Funktion mit @code{define-markup-command}
-definiert werden. Der Befehl braucht ein Argument vom Typ @code{markup}.
-Darum sollte der Beginn der Funktion lauten:
+Es gibt keine Einschränkung in der Reihenfolge der Argumente (nach
+den Standard-Argumenten @code{layout} und @code{props}). Textbeschriftungsfunktionen,
+die als letztes Argument eine Textbeschriftung haben, haben die
+Besonderheit, dass sie auf Textbeschriftungslisten angewendet werden
+können, und das Resultat ist eine Textbeschriftungsliste, in der
+die Textbeschriftungsfuktion (mit den angegebenen Argumenten am Anfang)
+auf jedes Element der originalen Textbeschriftungsliste angewendet
+wurde.
-@example
-(define-markup-command (smallcaps layout props argument) (markup?)
-@end example
+Da das Wiederholen der Argumente am Anfang bei der Anwendung einer
+Textbeschriftungsfunktion auf eine Textbeschriftungsliste for allem
+für Scheme-Argumente sparsam ist, kann man Leistungseinbußen vermeiden,
+indem man nur Scheme-Argumente für die Argumente am Anfang einsetzt,
+wenn es sich um Textbeschriftungsfunktionen handelt, die eine Textbeschriftung
+als letztes Argument haben.
-@noindent
-Was jetzt folgt, ist der eigentliche Inhalt des Befehls: das
-@code{argument} soll als Beschriftung (markup) interpretiert werden,
-also:
+@node Über Eigenschaften
+@unnumberedsubsubsec Über Eigenschaften
+@translationof On properties
-@example
-(interpret-markup layout @dots{} argument)
-@end example
+Die @code{layout}- und @code{props}-Argumente der Textbeschriftungsbefehle
+bringen einen Kontext für die Interpretation der Beschriftung:
+Schriftgröße, Zeilenlänge usw.
-@noindent
-Diese Interpretation sollte @code{'(font-shape . caps)} zu den
-aktiven Eigenschaften hinzufügen, weshalb wir das Folgende anstelle
-der @dots{} in dem Beispiel einfügen:
+Das @code{layout}-Argument greift auf Eigenschaften zu, die in der
+@code{paper}-Umgebung definiert werden, indem man die @code{ly:output-def-lookup}-Funktion
+benutzt. Beispielsweise liest man die Zeilenlänge (die gleiche, die auch in
+Partituren benutzt wird) aus mit:
@example
-(cons (list '(font-shape . caps) ) props)
+(ly:output-def-lookup layout 'line-width)
@end example
-@noindent
-Die Variable @code{props} ist eine Liste an alists, und mit @code{cons}
-wird ihr eine zusätzliche Einstellung hinzugefügt.
+Das @code{props}-Argument stellt einige Eigenschaften für die Textbeschriftungsbefehle
+zur Verfügung. Beispielsweise wenn der Überschrifttext einer
+@code{book}-Umgebung interpretiert wird, werden alle Variablen, die
+in der @code{\header}-Umgebung definiert werden, automatisch zu @code{props}
+hinzugefügt, sodass die Beschriftung auf Titel, Komponist usw. der
+@code{book}-Umgebung zugreifen kann. Das ist auch eine Möglichkeit, das
+Verhalten eines Beschriftungsbefehls zu konfigurieren: Wenn etwa ein
+Befehl die Schriftgröße während der Verarbeitung einsetzt, wird die
+Schriftgröße aus den @code{props} ausgelesen und nicht mit einem eigenen
+@code{font-size}-Argument definiert. Beim Aufruf des Beschriftungsbefehls
+kann der Wert der Schriftgröße geändert werden, womit sich auch das Verhalten
+des Befehls verändert. Benutzen Sie das @code{#:properties}-Schlüsselwort
+von @code{define-markup-command} um zu definieren, welche Eigenschaften aus den
+@code{props}-Argumenten ausgelesen werden sollen.
-Man könnte sich auch vorstellen, dass ein Rezitativ einer Oper
-gesetzt werden soll, und ein Befehl wäre sehr bequem, mit dem
-man die Namen der Charaktere auf eine eigene Art darstellen könnte.
-Namen sollen in Kapitälchen gesetzt werden und etwas nach links und
-oben verschoben werden. Man kann also einen @code{\character}-Befehl
-definieren, der die nötige Verschiebung berücksichtigt und
-den neuen @code{\smallcaps}-Befehl einsetzt:
+Das Beispiel im nächsten Abschnitt illustriert, wie man auf Eigenschaften
+in einem Beschriftungsbefehl zugreifen und sie verändern kann.
-@example
-#(define-markup-command (character layout props name) (string?)
- "Print the character name in small caps, translated to the left and
- top. Syntax: \\character #\"name\""
+
+@node Ein vollständiges Bespiel
+@unnumberedsubsubsec Ein vollständiges Bespiel
+@translationof A complete example
+
+Das folgende Beispiel definiert einen Beschriftungsbefehl, der einen
+doppelten Kasten um einen Text zeichnet.
+
+Zuerst wollen wir ein annäherndes Ergebnis mit Textbeschriftungen definieren.
+Nach Stöbern in @ruser{Textbeschriftungsbefehle} finden wir den Befehl
+@code{\box}:
+
+@lilypond[quote,verbatim,ragged-right]
+\markup \box \box HELLO
+@end lilypond
+
+Wir wollen aber etwas mehr Abstand (engl. padding) zwischen dem Text und dem Kasten.
+Nach der Dokumentation von @code{\box} hat der Befehl eine
+@code{box-padding}-Eigenschaft, die den Standardwert von 0.2 hat. Die
+Dokumentation zeit auch, wir man den Wert verändert:
+
+@lilypond[quote,verbatim,ragged-right]
+\markup \box \override #'(box-padding . 0.6) \box A
+@end lilypond
+
+Auch der Abstand zwischen den zwei Kästen ist uns zu klein und soll auch
+vergrößert werden:
+
+@lilypond[quote,verbatim,ragged-right]
+\markup \override #'(box-padding . 0.4) \box \override #'(box-padding . 0.6) \box A
+@end lilypond
+
+Diese lange Textbeschriftung immer wieder schreiben zu müssen, ist
+anstrengend. Hier kömmt ein Textbeschriftungsbefehl ins Spiel. Wir
+schreiben uns alle einen @code{double-box}-Beschriftungsbefehl, der
+ein Argument annimmt (den Text). Er zeichnet zwei Kästen mit genügend Abstand:
+
+@lisp
+#(define-markup-command (double-box layout props text) (markup?)
+ "Draw a double box around text."
(interpret-markup layout props
- (markup #:hspace 0 #:translate (cons -3 1) #:smallcaps name)))
-@end example
+ (markup #:override '(box-padding . 0.4) #:box
+ #:override '(box-padding . 0.6) #:box text)))
+@end lisp
-Hier ist eine Komplikation, die erklärt werden muss: Text über oder
-unter dem Notensystem wird vertikal verschoben um in einem bestimmten
-Abstand von dem System und den Noten zu sein (das wird als @qq{padding}
-bezeichnet). Um sicherzugehen, dass dieser Mechanismus nicht die
-vertikale Verschiebung von @code{#:translate} annulliert, wird
-die leere Zeichenkette (@code{#:hspace 0}) vor den zu verschiebenden
-Text gesetzt. Das @code{#:hspace 0} wird jetzt also über die Noten
-gesetzt und @code{name} dann relativ zu der leeren Zeichenkette
-verschoben. Im Endeffekt wird der Text nach links oben verschoben.
+@code{text} ist die Bezeichnung des Arguments dieses Befehls,
+und @code{markup?} ist seine Art: hiermit wird der Befehl als
+Beschriftungsbefehl identifiziert. Die @code{interpret-markup}-Funktion
+wird in den meisten Beschriftungsbefehlen benutzt: sie erstellt einen
+Stencil, wobei @code{layout}, @code{props} und eine Beschriftung benutzt
+werden. In unserem Fall wird diese Beschriftung durch das
+@code{markup}-Scheme-Makro erstellt, siehe auche @ref{Beschriftungskonstruktionen in Scheme}.
+Die Transformation des @code{\markup}-Ausdrucks in einen
+Scheme-Beschriftungsausdruck geschieht durch umschreiben des LilyPond-Codes
+in Scheme-Code.
-Das Resultat sieht folgendermaßen aus:
+Der neue Befehl kann wie folgt benutzt werden:
@example
-@{
- c''^\markup \character #"Cleopatra"
- e'^\markup \character #"Giulio Cesare"
-@}
+\markup \double-box A
@end example
-@lilypond[quote,ragged-right]
-#(define-markup-command (smallcaps layout props str) (string?)
- "Print the string argument in small caps. Syntax: \\smallcaps #\"string\""
+Es wäre schön, den @code{double-box}-Befehl noch konfigurierbar zu gestalten:
+in unserem Fall sind die Werte von @code{box-padding} direkt definiert und
+können nicht mehr vom Benutzer verändert werden. Es wäre auch besser, wenn
+der Abstand zwischen den beiden Kästen vom Abstand zwischen dem inneren Kasten
+und dem Text unterschieden werden könnte. Eine neue Eigenschaft muss also
+definiert werden: @code{inter-box-padding} für den Abstand zwischen den Kästen.
+@code{box-padding} wird für den inneren Abstand benutzt. Der neue Befehl wird
+so definiert:
+
+@lisp
+#(define-markup-command (double-box layout props text) (markup?)
+ #:properties ((inter-box-padding 0.4)
+ (box-padding 0.6))
+ "Draw a double box around text."
(interpret-markup layout props
- (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)))))
-
-#(define-markup-command (character layout props name) (string?)
- "Print the character name in small caps, translated to the left and
- top. Syntax: \\character #\"name\""
+ (markup #:override `(box-padding . ,inter-box-padding) #:box
+ #:override `(box-padding . ,box-padding) #:box text)))
+@end lisp
+
+In diesem Code wird das @code{#:properties}-Schlüsselwort benutzt, sodass
+die Eigenschaften @code{inter-box-padding} und @code{box-padding} aus dem
+@code{props}-Argument ausgelesen werden, und Standardwerte werden gegeben,
+falls die Eigenschaften nicht definiert sein sollten.
+
+Dann werden diese Werte benutzt, um die @code{box-padding}-Eigenschaft
+zu verändert, die von beiden @code{\box}-Befehlen benutzt wird. Beachten
+Sie Akzent und das Komma des @code{\override}-Arguments: hiermit kann man
+einen Variablenwert in einen wörtlichen Ausdruck überführen.
+
+Jetzt kann der Befehl in Beschriftungen benutzt werden und der Abstand
+der Kästen kann angepasst werden:
+
+@lilypond[quote,verbatim,ragged-right]
+#(define-markup-command (double-box layout props text) (markup?)
+ #:properties ((inter-box-padding 0.4)
+ (box-padding 0.6))
+ "Draw a double box around text."
(interpret-markup layout props
- (markup #:hspace 0 #:translate (cons -3 1) #:smallcaps name)))
+ (markup #:override `(box-padding . ,inter-box-padding) #:box
+ #:override `(box-padding . ,box-padding) #:box text)))
-{
- c''^\markup \character #"Cleopatra" c'' c'' c''
- e'^\markup \character #"Giulio Cesare" e' e' e'
-}
+\markup \double-box A
+\markup \override #'(inter-box-padding . 0.8) \double-box A
+\markup \override #'(box-padding . 1.0) \double-box A
@end lilypond
-In diesen Befehlen wurden Kapitälchen eingesetzt, aber es kann
-vorkommen, dass die Schriftart keine Kapitälchen zur Verfügung
-stellt. In diesem Fall können die Kapitälchen nachempfunden
-werden, indem man Großbuchstaben setzt, deren Anfangsbuchstabe
-etwas größer gesetzt wird:
+@node Eingebaute Befehle anpassen
+@unnumberedsubsubsec Eingebaute Befehle anpassen
+@translationof Adapting builtin commands
-@example
-#(define-markup-command (smallcaps layout props str) (string?)
- "Print the string argument in small caps."
- (interpret-markup layout 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
+Ein guter Weg, einen neuen Beschriftungsbefehl zu schreiben, ist es, als Vorbild
+einen existierenden zu nehmen. Die meisten Beschriftungsbefehle, die
+LilyPond mitbringt, finden sich in der Datei
+@file{scm/define-markup-commands.scm}.
-Der @code{smallcaps}-Befehl spaltet die Argumente zuerst in
-Einzelstücke auf, die von Leerzeichen getrennt sind
-(@code{(string-split str #\Space)}); für jedes Einzelstück
-wird dann eine Beschriftung aufgebaut, deren erster Buchstabe
-vergrößert wird und als Versalbuchstabe gesetzt wird
-(@code{#:large (string-upcase (substring s 0 1))}), und eine
-zweite Versalbuchstaben gesetzt werden
-(@code{#:tiny (string-upcase (substring s 1))}). Wenn
-LilyPond ein Leerzeichen zwischen Beschriftungen einer Zeile
-entdeckt, wird die zweite Beschriftung nach links verschoben
-(@code{#:translate (cons -0.6 0) ...}). Dann werden die
-Beschriftungen für jedes Einzelstück in eine Zeile gesetzt
-@code{(make-line-markup ...)}. Schließlich wird die resultierende
-Beschriftung an die @code{interpret-markup}-Funktion zusammen
-mit den Argumenten @code{layout} und @code{props} weitergereicht.
-
-Achtung: ist gibt keinen internen Befehl @code{\smallCaps}, der
-benutzt werden kann, um Text in Kapitälchen zu setzen. Siehe auch
-@ref{Text markup commands}.
+Man könnte beispielsweise den Befehl @code{\draw-line}, der eine Linie
+zeichnet, anpassen, sodass er eine Doppellinie zeichnet. Der
+Befehl @code{\draw-line} ist wie folgend definiert (Dokumentation entfernt):
-@knownissues
+@lisp
+(define-markup-command (draw-line layout props dest)
+ (number-pair?)
+ #:category graphic
+ #:properties ((thickness 1))
+ "..documentation.."
+ (let ((th (* (ly:output-def-lookup layout 'line-thickness)
+ thickness))
+ (x (car dest))
+ (y (cdr dest)))
+ (make-line-stencil th 0 0 x y)))
+@end lisp
-Im Moment sind die möglichen Kombinationen von Argumenten (nach den
-Standardargumenten @var{layout} und @var{props}), die mit
-@code{define-markup-command} definiert werden, wie folgt
-limitiert:
-
-@table @asis
-@item (kein Argument)
-@itemx @var{list}
-@itemx @var{markup}
-@itemx @var{markup markup}
-@itemx @var{scm}
-@itemx @var{scm markup}
-@itemx @var{scm scm}
-@itemx @var{scm scm markup}
-@itemx @var{scm scm markup markup}
-@itemx @var{scm markup markup}
-@itemx @var{scm scm scm}
-@end table
+Um einen neuen Befehl, der auf einem existierenden basiert, zu definieren,
+wird die Befehlsdefinition kopiert und die Bezeichnung des Befehls
+geändert. Das @code{#:category}-Schlagwort kann entfernt werden,
+weil es nur zur Erstellung der LilyPond-Dokumentation eingesetzt wird
+und keine Bedeutung für selbstdefinierte Befehle hat.
-@noindent
-Hier stellt @var{scm} native Scheme-Datentypen dar wie
-@q{number} oder @q{string}.
+@lisp
+(define-markup-command (draw-double-line layout props dest)
+ (number-pair?)
+ #:properties ((thickness 1))
+ "..documentation.."
+ (let ((th (* (ly:output-def-lookup layout 'line-thickness)
+ thickness))
+ (x (car dest))
+ (y (cdr dest)))
+ (make-line-stencil th 0 0 x y)))
+@end lisp
-Es ist beispielsweise nicht möglich, einen Beschriftungsbefehl
-@code{foo} mit vier Argumenten in folgender Weise zu nutzen:
+Dann braucht man eine Eigenschaft, um den Abstand zwischen den zwei
+Linien zu definieren, als @code{line-gap} bezeichnet und etwa mit
+dem Standardwert 0.6:
-@example
-#(define-markup-command (foo layout props
- num1 str1 num2 str2)
- (number? string? number? string?)
- ...)
-@end example
+@lisp
+(define-markup-command (draw-double-line layout props dest)
+ (number-pair?)
+ #:properties ((thickness 1)
+ (line-gap 0.6))
+ "..documentation.."
+ ...
+@end lisp
-@noindent
-Wenn es folgendermaßen eingesetzt wird:
+Schließlich wird der Code, der die zwei Linien zeichnet, hinzugefügt.
+Zwei Aufrufe an @code{make-line-stencil} werden benutzt, um beide Linien
+zu zeichnen, und die beiden sich daraus ergebenden Stencils werden mit
+@code{ly:stencil-add} kombiniert:
-@example
-\markup \foo #1 #"bar" #2 #"baz"
-@end example
+@lilypond[quote,verbatim,ragged-right]
+#(define-markup-command (my-draw-line layout props dest)
+ (number-pair?)
+ #:properties ((thickness 1)
+ (line-gap 0.6))
+ "..documentation.."
+ (let* ((th (* (ly:output-def-lookup layout 'line-thickness)
+ thickness))
+ (dx (car dest))
+ (dy (cdr dest))
+ (w (/ line-gap 2.0))
+ (x (cond ((= dx 0) w)
+ ((= dy 0) 0)
+ (else (/ w (sqrt (+ 1 (* (/ dx dy) (/ dx dy))))))))
+ (y (* (if (< (* dx dy) 0) 1 -1)
+ (cond ((= dy 0) w)
+ ((= dx 0) 0)
+ (else (/ w (sqrt (+ 1 (* (/ dy dx) (/ dy dx))))))))))
+ (ly:stencil-add (make-line-stencil th x y (+ dx x) (+ dy y))
+ (make-line-stencil th (- x) (- y) (- dx x) (- dy y)))))
+
+\markup \my-draw-line #'(4 . 3)
+\markup \override #'(line-gap . 1.2) \my-draw-line #'(4 . 3)
+@end lilypond
-@cindex Scheme signature
-@cindex Signatur, Scheme
-@noindent
-beschwert sich @command{lilypond}, dass @code{foo} wegen einer ungekannten
-Scheme Signatur nicht analysiert werden kann.
-@node Neue Definitionen von Beschriftungsbefehlen für Listen
-@subsection Neue Definitionen von Beschriftungsbefehlen für Listen
+@node Neue Definitionen von Beschriftungslistenbefehlen
+@subsection Neue Definitionen von Beschriftungslistenbefehlen
@translationof New markup list command definition
Beschriftungslistenbefehle können mit dem Scheme-Makro
@code{define-markup-command}-Makro, das schon beschrieben
wurde in @ref{Neue Definitionen von Beschriftungsbefehlen}. Ein Unterschied
ist, dass bei diesem Listen-Makro eine ganze Liste an
-Stecils ausgegeben wird.
+Stencils ausgegeben wird.
Im folgenden Beispiel wird ein @code{\paragraph}-Beschriftungslistenbefehl
definiert, welcher eine Liste von Zeilen im Blocksatz ausgibt, von
args)))))
@end example
-Neben den üblichen @code{layout} und @code{props}-Argumenten, nimmt der
+Neben den üblichen @code{layout} und @code{props}-Argumenten nimmt der
@code{paragraph}-Beschriftungslistenbefehl als Argument eine Beschriftungsliste,
die @code{args} genannt wird. Das Prädikat für Beschriftungslisten ist
@code{markup-list?}.
@}
\override-lines #'(par-indent . 4) \paragraph @{
Diese Platte wurde dann mit Druckerschwärze versehen, so dass sie
- in den geschnittenen und gestempelten Vertiefungen blieb. Diese
+ in den geschnittenen und gestempelten Vertiefungen blieb. Diese
Vertiefungen schwärzten dann ein auf die Platte gelegtes Papier.
Das Gravieren wurde vollständig von Hand erledigt.
@}
@var{function} sollte eine Scheme-Funktion sein, die ein
einziges Argument braucht, welches der Kontext ist, auf den
sie ausgeführt werden soll. Der folgende Code schreibt
-die aktuelle Taktzahlshould in die Standardausgabe
+die aktuelle Taktzahl in die Standardausgabe
während der Kompilation.
@example
@funindex \applyOutput
Der vielfältigste Weg, ein Objekt zu beeinflussen, ist
-@code{\applyOutput}. Die Syntax lautet:
+@code{\applyOutput}. Das funktioniert, indem ein musikalisches
+Ereignis in den angegebenen Kontext eingefügt wird
+(@rinternals{ApplyOutputEvent}). Die Syntax lautet:
@example
\applyOutput @var{Kontext} @var{proc}
wobei @var{proc} eine Scheme-Funktion ist, die drei Argumente
benötigt.
-Während der Interpretation wird die Funktion @var{proc} für
-jedes Layoutobjekt aufgerufen, dass im Kontext @var{Kontext}
+Während der Interpretation wird die Funktion @code{@var{proc}} für
+jedes Layoutobjekt aufgerufen, dass im Kontext @code{@var{Kontext}}
vorgefunden wird, und zwar mit folgenden Argumenten:
@itemize
der musikalische Ausdruck oder das Objekt, das für seine Erstellung
verantwortlich war, in der Objekteigenschaft @code{cause}.
Für einen Notenkopf beispielsweise ist das ein
-@rinternals{NoteHead}-Ereignis, und für einen Notenhals
-(ein @rinternals{Stem}-Objekt) ist es ein @rinternals{NoteHead}-Objekt.
+@rinternals{NoteHead}-Ereignis, und für einen Notenhals ist es
+ein @rinternals{Stem}-Objekt.
Hier ist eine Funktion, die mit @code{\applyOutput} benutzt
-werden kann; sie macht Notenköpfe auf der Mittellinie unsichtbar:
+werden kann; sie macht Notenköpfe auf und neben der Mittellinie unsichtbar:
@lilypond[quote,verbatim,ragged-right]
#(define (blanker grob grob-origin context)
(if (and (memq 'note-head-interface (ly:grob-interfaces grob))
- (eq? (ly:grob-property grob 'staff-position) 0))
+ (< (abs (ly:grob-property grob 'staff-position)) 2))
(set! (ly:grob-property grob 'transparent) #t)))
-\relative {
- e4 g8 \applyOutput #'Voice #blanker b d2
+\relative c' {
+ a'4 e8 <<\applyOutput #'Voice #blanker a c d>> b2
}
@end lilypond
-@node Scheme-Vorgänge als Eigenschaften
-@section Scheme-Vorgänge als Eigenschaften
-@translationof Scheme procedures as properties
+@node Callback-Funktionen
+@section Callback-Funktionen
+@translationof Callback functions
-Eigenschaften (wie Dicke, Richtung usw.) können mit
-@code{\override} auf feste Werte gesetzt werden, etwa:
+Eigenschaften (wie Dicke (@code{thickness}), Richtung (@code{direction})
+usw.) können mit @code{\override} auf feste Werte gesetzt werden, etwa:
@example
\override Stem #'thickness = #2.0
@end lilypond
@noindent
-In diesem Fall wird die Prozedur ausgeführt, sobal der Wert der
+In diesem Fall wird die Prozedur ausgeführt, sobald der Wert der
Eigenschaft während das Formatierungsprozesses angefordert wird.
-Der größte Teil der Satzmaschinierie funtioniert mit derartigen
+Der größte Teil der Satzmaschinierie funktioniert mit derartigen
Callbacks. Eigenschaften, die üblicherweise Callbacks
benutzen, sind u. A.:
@table @code
@item stencil
- Die Druckfunktion, die eine Ausgabe des Symbols ervorruft
+ Die Druckfunktion, die eine Ausgabe des Symbols hervorruft
@item X-offset
Die Funktion, die die horizontale Position setzt
@item X-extent
Resultat der Funktion ausgegeben wird und nicht das
@code{simple-closure}-Objekt.
+Aus dem Callback heraus kann man eine Beschriftung am einfachsten mit
+@code{grob-interpret-markup} auswerten. Beispielsweise:
+
+@example
+mein-callback = #(lambda (grob)
+ (grob-interpret-markup grob (markup "foo")))
+@end example
+
+
+
+
+
-@node Scheme-Code anstelle von \tweak verwenden
-@section Scheme-Code anstelle von @code{ weak} verwenden
-@translationof Using Scheme code instead of \tweak
+@node Scheme-Code innerhalb LilyPonds
+@section Scheme-Code innerhalb LilyPonds
+@translationof Inline Scheme code
Der hauptsächliche Nachteil von @code{\tweak} ist seine
syntaktische Inflexibilität. Folgender Code beispielsweise
@end itemize
Diese Funktion muss in @rinternals{Tie} (Bindebogen) installiert
-werden, und der letzte Teil eines gebrochenen Bindebogens wird
-nach oben verschoben.
+werden, damit der letzte Teil eines gebrochenen Bindebogens
+neu ausgerichtet wird.
@lilypond[quote,verbatim,ragged-right]
#(define (my-callback grob)
auch das alte @code{after-line-breaking}-Callback aufrufen,
wenn es vorhanden ist. Wenn diese Funktion etwa mit
@code{Hairpin} (Crescendo-Klammer) eingesetzt wird, sollte auch
-@code{ly:hairpin::after-line-breaking} aufgerufen werden.
+@code{ly:spanner::kill-zero-spanned-time} aufgerufen werden.
@item
@end example
Es sollte angemerkt werden, dass @code{\override}, wenn man es auf
-@code{NonMusicalPaperColumn} und @code{PaperColumn} anwendet, immernoch
+@code{NonMusicalPaperColumn} und @code{PaperColumn} anwendet, immer noch
innerhalb der @code{\context}-Umgebung funktioniert.
@end itemize
+
+
+
+@node LilyPond Scheme-Schnittstellen
+@chapter LilyPond Scheme-Schnittstellen
+@translationof LilyPond Scheme interfaces
+
+Dieses Kapitel behandelt die verschiedenen Werkzeuge, die LilyPond als
+Hilfe für Scheme-Programmierer zur Verfügung stellt, um Information in
+den Musik-Stream zu senden und aus ihm herauszubekommen.
+
+TODO: was gehört hier eigentlich hin?