GNU LilyPond Notation Reference: 6.4.3 New markup command definition

### 6.4.3 New 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 are

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,

>     \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 must 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 moved a bit to the left and top. We will define a `\character` command which 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 Text markup commands, for details.

#### Known issues and warnings

Currently, the available combinations of arguments (after the standard layout and props arguments) to a markup command defined with `define-markup-command` are limited as follows.

(no argument)
list
markup
markup markup
scm
scm markup
scm scm
scm scm markup
scm scm markup markup
scm markup markup
scm scm scm

In the above table, scm represents native Scheme data types like ‘number’ or ‘string’.

As an example, it is not possible to use a markup command `foo` with four arguments defined as

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

If you apply it as, say,

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

`lilypond` complains that it cannot parse `foo` due to its unknown Scheme signature.

Other languages: español.

#### Notation Reference