B.4.3 Neue Definitionen von Beschriftungsbefehlen

Neue Textbeschriftungsbefehle können mit dem define-markup-command-Scheme-Makro definiert werden.

 
(define-markup-command (befehl-bezeichnung layout props arg1 arg2 ...)
            (arg1-type? arg2-type? ...)
  ..Befehlkörper..)

Die Argumente sind:

argi

ite Befehlsargument

argi-type?

eine Eigenschaft für das ite Argument

layout

die ‚layout‘-Definition

props

eine Liste an alists, in der alle aktiven Eigenschaften enthalten sind

Als einfaches Beispiel soll gezeigt werden, wie man einen \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:

\markup { \override #'(font-shape . caps) Text-in-Kapitälchen }

Damit wird die Kapitälchenschriftart ausgewählt, indem die font-shape-Eigesnchaft auf #'caps gesetzt wird, während Text-in-caps interpretiert wird.

Damit diese Funkion als \smallcaps-Befehl zur Verfügung gestellt werden kann, muss eine Funktion mit define-markup-command definiert werden. Der Befehl braucht ein Argument vom Typ markup. Darum sollte der Beginn der Funktion lauten:

(define-markup-command (smallcaps layout props argument) (markup?)

Was jetzt folgt, ist der eigentliche Inhalt des Befehls: das argument soll als Beschriftung (markup) interpretiert werden, also:

(interpret-markup layout … argument)

Diese Interpretation sollte '(font-shape . caps) zu den aktiven Eigenschaften hinzufügen, weshalb wir das Folgende anstelle der … in dem Beispiel einfügen:

(cons (list '(font-shape . caps) ) props)

Die Variable props ist eine Liste an alists, und mit cons wird ihr eine zusätzliche Einstellung hinzugefügt.

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 \character-Befehl definieren, der die nötige Verschiebung berücksichtigt und den neuen \smallcaps-Befehl einsetzt:

#(define-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 layout props
   (markup #:hspace 0 #:translate (cons -3 1) #:smallcaps name)))

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 „padding“ bezeichnet). Um sicherzugehen, dass dieser Mechanismus nicht die vertikale Verschiebung von #:translate annulliert, wird die leere Zeichenkette (#:hspace 0) vor den zu verschiebenden Text gesetzt. Das #:hspace 0 wird jetzt also über die Noten gesetzt und name dann relativ zu der leeren Zeichenkette verschoben. Im Endeffekt wird der Text nach links oben verschoben.

Das Resultat sieht folgendermaßen aus:

{
  c''^\markup \character #"Cleopatra"
  e'^\markup \character #"Giulio Cesare"
}

[image of music]

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:

#(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)))))

Der smallcaps-Befehl spaltet die Argumente zuerst in Einzelstücke auf, die von Leerzeichen getrennt sind ((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 (#:large (string-upcase (substring s 0 1))), und eine zweite Versalbuchstaben gesetzt werden (#:tiny (string-upcase (substring s 1))). Wenn LilyPond ein Leerzeichen zwischen Beschriftungen einer Zeile entdeckt, wird die zweite Beschriftung nach links verschoben (#:translate (cons -0.6 0) ...). Dann werden die Beschriftungen für jedes Einzelstück in eine Zeile gesetzt (make-line-markup ...). Schließlich wird die resultierende Beschriftung an die interpret-markup-Funktion zusammen mit den Argumenten layout und props weitergereicht.

Achtung: ist gibt keinen internen Befehl \smallCaps, der benutzt werden kann, um Text in Kapitälchen zu setzen. Siehe auch @ref{Text markup commands}.

Bekannte Probleme und Warnungen

Im Moment sind die möglichen Kombinationen von Argumenten (nach den Standardargumenten layout und props), die mit define-markup-command definiert werden, wie folgt limitiert:

(kein Argument)
list
markup
markup markup
scm
scm markup
scm scm
scm scm markup
scm scm markup markup
scm markup markup
scm scm scm

Hier stellt scm native Scheme-Datentypen dar wie ‚number‘ oder ‚string‘.

Es ist beispielsweise nicht möglich, einen Beschriftungsbefehl foo mit vier Argumenten in folgender Weise zu nutzen:

#(define-markup-command (foo layout props
                         num1    str1    num2    str2)
                        (number? string? number? string?)
  ...)

Wenn es folgendermaßen eingesetzt wird:

\markup \foo #1 #"bar" #2 #"baz"

beschwert sich lilypond, dass foo wegen einer ungekannten Scheme Signatur nicht analysiert werden kann.


Andere Sprachen: English, español.

LilyPond – Extending