| [ < ] | [ > ] | [ << ] | [ Nach oben ] | [ >> ] | [Anfang] | [Inhalt] | [Index] | [ ? ] |
@translationof Markup functions
Textbeschriftungselemente sind als besondere Scheme-Funktionen
definiert, die ein Stencil-Objekt erstellen, dem eine Anzahl
an Argumenten übergeben wird.
| 2.5.1 Beschriftungskonstruktionen in Scheme | ||
| 2.5.2 Wie Beschriftungen intern funktionieren | ||
| 2.5.3 Neue Definitionen von Beschriftungsbefehlen | ||
| 2.5.4 Neue Definitionen von Beschriftungslistenbefehlen |
| [ < ] | [ > ] | [ << ] | [ Nach oben ] | [ >> ] | [Anfang] | [Inhalt] | [Index] | [ ? ] |
@translationof Markup construction in Scheme
Das markup-(Textbeschriftungs)Makro erstellt Textbeschriftungs-Ausdrücke
in Scheme, wobei eine LilyPond-artige Syntax benutzt wird. Beispielsweise
ist
(markup #:column (#:line (#:bold #:italic "hello" #:raise 0.4 "world")
#:larger #:line ("foo" "bar" "baz")))
|
identisch mit
#{ \markup \column { \line { \bold \italic "hello" \raise #0.4 "world" }
\larger \line { foo bar baz } } #}
|
Dieses Beispiel zeigt die hauptsächlichen Übersetzungsregeln
zwischen normaler Textbeschriftungssyntax von LilyPond und der
Textbeschriftungssyntax in Scheme. Es ist meistens der beste
Weg, #{ … #} zur Eingabe von LilyPond-Syntax zu
benützen, aber es soll auch erklärt werden, wie man das
markup-Makro einsetzt, um eine Lösung nur in Scheme zu bekommen.
LilyPond Scheme \markup Text1(markup Text1)\markup { Text1 Text2 ... }(markup Text1 Text2 ... )\Beschriftungsbefehl#:Beschriftungsbefehl\VariableVariable\center-column { ... }#:center-column ( ... )Zeichenkette"Zeichenkette"#scheme-Argscheme-Arg
Die gesamte Scheme-Sprache ist innerhalb des markup-Makros
zugänglich. Man kann also beispielsweise Funktionen innerhalb
eines markup aufrufen, um Zeichenketten zu manipulieren.
Das ist nützlich, wenn neue Beschriftungsbefehle definiert werden
sollen (siehe auch
Neue Definitionen von Beschriftungsbefehlen).
Das Beschriftungslistenargument von Befehlen wie #:line,
#:center und #:column kann keine Variable oder
das Resultat eines Funktionsaufrufen sein.
(markup #:line (Funktion-die-Textbeschriftung-ausgibt)) |
ist ungültig. Man sollte anstatt dessen die Funktionen
make-line-markup, make-center-markup oder
make-column-markup benutzen:
(markup (make-line-markup (Funktion-die-Textbeschriftung-ausgibt))) |
| [ < ] | [ > ] | [ << ] | [ Nach oben ] | [ >> ] | [Anfang] | [Inhalt] | [Index] | [ ? ] |
@translationof How markups work internally
In einer Textbeschriftung wie
\raise #0.5 "Textbeispiel" |
ist \raise unter der Haube durch die raise-markup-Funktion
repräsentiert. Der Beschriftungsausdruck wird gespeichert als
(list raise-markup 0.5 (list simple-markup "Textbeispiel")) |
Wenn die Beschriftung in druckbare Objekte (Stencils) umgewandelt ist,
wir die raise-markup-Funktion folgendermaßen aufgerufen:
(apply raise-markup
\layout object
Liste der Eigenschafts-alists
0.5
die "Textbeispiel"-Beschriftung)
|
Die raise-markup-Funktion erstellt zunächst den Stencil für die
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
‘scm/define-markup-commands.scm’.
| [ < ] | [ > ] | [ << ] | [ Nach oben ] | [ >> ] | [Anfang] | [Inhalt] | [Index] | [ ? ] |
@translationof New markup command definition
Dieser Abschnitt behandelt die Definition von neuen Textbeschriftungsbefehlen.
| Syntax der Definition von Textbeschriftungsbefehlen | ||
| Über Eigenschaften | ||
| Ein vollständiges Bespiel | ||
| Eingebaute Befehle anpassen |
| [ < ] | [ > ] | [ << ] | [ Nach oben ] | [ >> ] | [Anfang] | [Inhalt] | [Index] | [ ? ] |
@translationof Markup command definition syntax
Neue Textbeschriftungsbefehle können mit dem
define-markup-command-Scheme-Makro definiert werden.
(define-markup-command (befehl-bezeichnung layout props Arg1 Arg2 ...)
(Arg1-typ? Arg2-typ? ...)
[ #:properties ((Eigenschaft1 Standard-Wert1)
...) ]
..Befehlkörper..)
|
Die Argumente sind:
die Bezeichnung des Befehls
die ‚layout‘-Definition
eine Liste an assoziativen Listen, in der alle aktiven Eigenschaften enthalten sind
das ite Befehlsargument
eine Eigenschaft für das ite Argument
Wenn der Befehl Eigenschaften des props-Arguments benutzt,
kann das #:properties-Schlüsselwort benutzt werden um zu
bestimmen, welche Eigenschaften mit welchen Standard-Werten benutzt
werden.
Argumente werden nach ihrem Typ unterschieden:
markup?;
markup-list?;
list?, number?, boolean?, usw.
Es gibt keine Einschränkung in der Reihenfolge der Argumente (nach
den Standard-Argumenten layout und 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.
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.
| [ < ] | [ > ] | [ << ] | [ Nach oben ] | [ >> ] | [Anfang] | [Inhalt] | [Index] | [ ? ] |
@translationof On properties
Die layout- und props-Argumente der Textbeschriftungsbefehle
bringen einen Kontext für die Interpretation der Beschriftung:
Schriftgröße, Zeilenlänge usw.
Das layout-Argument greift auf Eigenschaften zu, die in der
paper-Umgebung definiert werden, indem man die ly:output-def-lookup-Funktion
benutzt. Beispielsweise liest man die Zeilenlänge (die gleiche, die auch in
Partituren benutzt wird) aus mit:
(ly:output-def-lookup layout 'line-width) |
Das props-Argument stellt einige Eigenschaften für die Textbeschriftungsbefehle
zur Verfügung. Beispielsweise wenn der Überschrifttext einer
book-Umgebung interpretiert wird, werden alle Variablen, die
in der \header-Umgebung definiert werden, automatisch zu props
hinzugefügt, sodass die Beschriftung auf Titel, Komponist usw. der
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 props ausgelesen und nicht mit einem eigenen
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 #:properties-Schlüsselwort
von define-markup-command um zu definieren, welche Eigenschaften aus den
props-Argumenten ausgelesen werden sollen.
Das Beispiel im nächsten Abschnitt illustriert, wie man auf Eigenschaften in einem Beschriftungsbefehl zugreifen und sie verändern kann.
| [ < ] | [ > ] | [ << ] | [ Nach oben ] | [ >> ] | [Anfang] | [Inhalt] | [Index] | [ ? ] |
@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
(notation)Textbeschriftungsbefehle in Abschnitt ‘Textbeschriftungsbefehle’ in Notationsreferenz finden wir den Befehl
\box:
\markup \box \box HELLO
Wir wollen aber etwas mehr Abstand (engl. padding) zwischen dem Text und dem Kasten.
Nach der Dokumentation von \box hat der Befehl eine
box-padding-Eigenschaft, die den Standardwert von 0.2 hat. Die
Dokumentation zeit auch, wir man den Wert verändert:
\markup \box \override #'(box-padding . 0.6) \box A
Auch der Abstand zwischen den zwei Kästen ist uns zu klein und soll auch vergrößert werden:
\markup \override #'(box-padding . 0.4) \box \override #'(box-padding . 0.6) \box A
Diese lange Textbeschriftung immer wieder schreiben zu müssen, ist
anstrengend. Hier kömmt ein Textbeschriftungsbefehl ins Spiel. Wir
schreiben uns alle einen double-box-Beschriftungsbefehl, der
ein Argument annimmt (den Text). Er zeichnet zwei Kästen mit genügend Abstand:
#(define-markup-command (double-box layout props text) (markup?)
"Draw a double box around text."
(interpret-markup layout props
#{\markup \override #'(box-padding . 0.4) \box
\override #'(box-padding . 0.6) \box { #text }#}))
|
oder äquivalent
#(define-markup-command (double-box layout props text) (markup?)
"Draw a double box around text."
(interpret-markup layout props
(markup #:override '(box-padding . 0.4) #:box
#:override '(box-padding . 0.6) #:box text)))
|
text ist die Bezeichnung des Arguments dieses Befehls,
und markup? ist seine Art: hiermit wird der Befehl als
Beschriftungsbefehl identifiziert. Die interpret-markup-Funktion
wird in den meisten Beschriftungsbefehlen benutzt: sie erstellt einen
Stencil, wobei layout, props und eine Beschriftung benutzt
werden. Im zweiten Fall wird diese Beschriftung durch das
markup-Scheme-Makro erstellt, siehe auche
Beschriftungskonstruktionen in Scheme.
Die Transformation des \markup-Ausdrucks in einen
Scheme-Beschriftungsausdruck geschieht durch Umschreiben des LilyPond-Codes
in Scheme-Code.
Der neue Befehl kann wie folgt benutzt werden:
\markup \double-box A |
Es wäre schön, den double-box-Befehl noch konfigurierbar zu gestalten:
in unserem Fall sind die Werte von 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: inter-box-padding für den Abstand zwischen den Kästen.
box-padding wird für den inneren Abstand benutzt. Der neue Befehl wird
so definiert:
#(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 \override #`(box-padding . ,inter-box-padding) \box
\override #`(box-padding . ,box-padding) \box
{ #text } #}))
|
Wiederum wäre die entsprechende Version mit dem markup-Makro
so aussehen:
#(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 #:override `(box-padding . ,inter-box-padding) #:box
#:override `(box-padding . ,box-padding) #:box text)))
|
In diesem Code wird das #:properties-Schlüsselwort benutzt, sodass
die Eigenschaften inter-box-padding und box-padding aus dem
props-Argument ausgelesen werden, und Standardwerte werden gegeben,
falls die Eigenschaften nicht definiert sein sollten.
Dann werden diese Werte benutzt, um die box-padding-Eigenschaft
zu verändert, die von beiden \box-Befehlen benutzt wird. Beachten
Sie Akzent und das Komma des \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:
#(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 \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 \markup \override #'(box-padding . 1.0) \double-box A
| [ < ] | [ > ] | [ << ] | [ Nach oben ] | [ >> ] | [Anfang] | [Inhalt] | [Index] | [ ? ] |
@translationof Adapting builtin commands
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 ‘scm/define-markup-commands.scm’.
Man könnte beispielsweise den Befehl \draw-line, der eine Linie
zeichnet, anpassen, sodass er eine Doppellinie zeichnet. Der
Befehl \draw-line ist wie folgend definiert (Dokumentation entfernt):
(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)))
|
Um einen neuen Befehl, der auf einem existierenden basiert, zu definieren,
wird die Befehlsdefinition kopiert und die Bezeichnung des Befehls
geändert. Das #:category-Schlagwort kann entfernt werden,
weil es nur zur Erstellung der LilyPond-Dokumentation eingesetzt wird
und keine Bedeutung für selbstdefinierte Befehle hat.
(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)))
|
Dann braucht man eine Eigenschaft, um den Abstand zwischen den zwei
Linien zu definieren, als line-gap bezeichnet und etwa mit
dem Standardwert 0.6:
(define-markup-command (draw-double-line layout props dest)
(number-pair?)
#:properties ((thickness 1)
(line-gap 0.6))
"..documentation.."
...
|
Schließlich wird der Code, der die zwei Linien zeichnet, hinzugefügt.
Zwei Aufrufe an make-line-stencil werden benutzt, um beide Linien
zu zeichnen, und die beiden sich daraus ergebenden Stencils werden mit
ly:stencil-add kombiniert:
#(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)
| [ < ] | [ > ] | [ << ] | [ Nach oben ] | [ >> ] | [Anfang] | [Inhalt] | [Index] | [ ? ] |
@translationof New markup list command definition
Beschriftungslistenbefehle können mit dem Scheme-Makro
define-markup-list-command definiert werden, welches
sich ähnlich verhält wie das
define-markup-command-Makro, das schon beschrieben
wurde in Neue Definitionen von Beschriftungsbefehlen. Ein Unterschied
ist, dass bei diesem Listen-Makro eine ganze Liste an
Stencils ausgegeben wird.
Im folgenden Beispiel wird ein \paragraph-Beschriftungslistenbefehl
definiert, welcher eine Liste von Zeilen im Blocksatz ausgibt, von
denen die erste Zeile eingerückt ist. Der Einzug wird aus dem
props-Argument entnommen.
#(define-markup-list-command (paragraph layout props args) (markup-list?)
#:properties ((par-indent 2))
(interpret-markup-list layout props
#{\markuplist \justified-lines { \hspace #par-indent #args } #}))
|
Die Version nur in Scheme ist etwas komplexer:
#(define-markup-list-command (paragraph layout props args) (markup-list?)
#:properties ((par-indent 2))
(interpret-markup-list layout props
(make-justified-lines-markup-list (cons (make-hspace-markup par-indent)
args))))
|
Neben den üblichen layout und props-Argumenten nimmt der
paragraph-Beschriftungslistenbefehl als Argument eine Beschriftungsliste,
die args genannt wird. Das Prädikat für Beschriftungslisten ist
markup-list?.
Zuerst errechnet die Funktion die Breite des Einzugs, eine Eigenschaft
mit der Bezeichnung par-indent anhand der Eigenschaftsliste
props. Wenn die Eigenschaft nicht gefunden wird, ist der
Standardwert 2. Danach wird eine Liste von Zeilen im Blocksatz
erstellt, wobei der eingebaute \justified-lines-Beschriftungslistenbefehl
eingesetzt wird, der verwandt ist mit der
make-justified-lines-markup-list-Funktion. Horizontaler
Platz wird zu Beginn eingefügt mit \hspace (oder der
make-hspace-markup-Funktion). Zuletzt wird die Beschriftungsliste
ausgewertet durch die interpret-markup-list-Funktion.
Dieser neue Beschriftungslistenbefehl kann wie folgt benutzt werden:
\markuplist {
\paragraph {
Die Kunst des Notensatzes wird auch als \italic {Notenstich} bezeichnet. Dieser
Begriff stammt aus dem traditionellen Notendruck. Noch bis vor etwa
20 Jahren wurden Noten erstellt, indem man sie in eine Zink- oder
Zinnplatte schnitt oder mit Stempeln schlug.
}
\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
Vertiefungen schwärzten dann ein auf die Platte gelegtes Papier.
Das Gravieren wurde vollständig von Hand erledigt.
}
}
|
| [ < ] | [ > ] | [ << ] | [ Nach oben ] | [ >> ] |
Dieses Dokument wurde erzeugt von gub am 13. Juli 2020 durch texi2html 1.82.
Andere Sprachen: English, español, français.
Über die automatische Sprachauswahl.