Previous: Markup construction in scheme, Up: Markup programmer interface



C.2.2 Markup command definition

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

     (def-markup-command (command-name paper 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
paper
the `paper' definition
props
a list of alists, containing all active properties.

As a simple example, we show how to add a \smallcaps command, which selects TeX's 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 def-markup-command. The command should take a single argument, of markup type. Therefore, the start of the definition should read

       (def-markup-command (smallcaps paper props argument) (markup?)

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

         (interpret-markup paper  ... 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 consing 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 needed translation, and uses the newly defined \smallcaps command:

#(def-markup-command (character paper props name) (string?)
   "Print the character name in small caps, translated to the left and
   top. Syntax: \\character #\"name\""
   (interpret-markup paper props 
    (markup "" #:translate (cons -4 2) #: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 ("") before the translated text. Now the "" 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:

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

[image of music]

We have used the caps font shape, but suppose that our font that 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:

     #(def-markup-command (smallcaps paper props str) (string?)
        "Print the string argument in small caps."
        (interpret-markup paper 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 paper and props arguments.

Read comments on this page, or add one.

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

Report errors to <bug-lilypond@gnu.org>.