A complete example

The following example defines a markup command to draw a double box around a piece of text.

Firstly, we need to build an approximative result using markups. Consulting the Text markup commands shows us the \box command is useful:

\markup \box \box HELLO

[image of music]

Now, we consider that more padding between the text and the boxes is preferable. According to the \box documentation, this command uses a box-padding property, which defaults to 0.2. The documentation also mentions how to override it:

\markup \box \override #'(box-padding . 0.6) \box A

[image of music]

Then, the padding between the two boxes is considered too small, so we override it too:

\markup \override #'(box-padding . 0.4) \box
     \override #'(box-padding . 0.6) \box A

[image of music]

Repeating this lengthy markup would be painful. This is where a markup command is needed. Thus, we write a double-box markup command, taking one argument (the text). This draws the two boxes, with some padding.

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

or, equivalently

#(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 is the name of the command argument, and markup? its type: it identifies it as a markup. The interpret-markup function is used in most of markup commands: it builds a stencil, using layout, props, and a markup. In the second case, this markup is built using the markup Scheme macro, see Markup construction in Scheme. The transformation from \markup expression to Scheme markup expression is straight-forward.

The new command can be used as follow:

\markup \double-box A

It would be nice to make the double-box command customizable: here, the box-padding values are hard coded, and cannot be changed by the user. Also, it would be better to distinguish the padding between the two boxes, from the padding between the inner box and the text. So we will introduce a new property, inter-box-padding, for the padding between the two boxes. The box-padding will be used for the inner padding. The new code is now as follows:

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

Again, the equivalent version using the markup macro would be:

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

Here, the #:properties keyword is used so that the inter-box-padding and box-padding properties are read from the props argument, and default values are given to them if the properties are not defined.

Then, these values are used to override the box-padding properties used by the two \box commands. Note the backquote and the comma in the \override argument: they allow you to introduce a variable value into a literal expression.

Now, the command can be used in a markup, and the boxes padding be customized:

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

[image of music]


Extending LilyPond v2.25.21 (development-branch).