Markup command definition - GNU LilyPond
Description: GNU LilyPond

Previous: How markups work internally, Up: Markup programmer interface

#### 11.2.3 Markup command definition

New markup commands can be defined with the `define-markup-command` scheme macro.

    (define-markup-command (command-name layout props arg1 arg2 ...)
                (arg1-type? arg2-type? ...)
      ..command body..)

The arguments signify

argi
  ith command argument
argi-type?
  a type predicate for the ith argument
layout
  the `layout' definition
props
  a list of alists, containing all active properties.

As a simple example, we show how to add a `\smallcaps` command, which selects a small caps font. Normally, we could select the small caps font as follows:

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

This selects the caps font by setting the `font-shape` property to `#'caps` for interpreting `Text-in-caps`.

To make the above available as `\smallcaps` command, we have to define a function using `define-markup-command`. The command should take a single argument, of type markup. Therefore, the start of the definition should read

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

What follows is the content of the command: we should interpret the `argument` as a markup, i.e.,

    (interpret-markup layout ... argument)

This interpretation should add `'(font-shape . caps)` to the active properties, so we substitute the following for the ... in the above example:

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

The variable `props` is a list of alists, and we prepend to it by cons'ing a list with the extra setting.

Suppose that we are typesetting a recitative in an opera, and we would like to define a command that will show character names in a custom manner. Names should be printed with small caps and translated a bit to the left and top. We will define a `\character` command that takes into account the necessary translation, and uses the newly defined `\smallcaps` command:

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

There is one complication that needs explanation: texts above and below the staff are moved vertically to be at a certain distance (the `padding` property) from the staff and the notes. To make sure that this mechanism does not annihilate the vertical effect of our `#:translate`, we add an empty string (`#:hspace 0`) before the translated text. Now the `#:hspace 0` will be put above the notes, and the `name` is moved in relation to that empty string. The net effect is that the text is moved to the upper left.

The final result is as follows:

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

We have used the `caps` font shape, but suppose that our font does not have a small-caps variant. In that case we have to fake the small caps font by setting a string in upcase with the first letter a little larger:

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

The `smallcaps` command first splits its string argument into tokens separated by spaces (`(string-split str #\Space)`); for each token, a markup is built with the first letter made large and upcased (`#:large (string-upcase (substring s 0 1))`), and a second markup built with the following letters made tiny and upcased (`#:tiny (string-upcase (substring s 1))`). As LilyPond introduces a space between markups on a line, the second markup is translated to the left (`#:translate (cons -0.6 0) ...`). Then, the markups built for each token are put in a line by `(make-line-markup ...)`. Finally, the resulting markup is passed to the `interpret-markup` function, with the `layout` and `props` arguments.

Note: there is now an internal command `\smallCaps` which can be used to set text in small caps. See Overview of text markup commands for details.

This page is for LilyPond-2.8.8 (stable-branch).

Other languages: English.
Using automatic language selection.