A complete example (Extending LilyPond)

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

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

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

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

#### Extending LilyPond v2.26.0 (stable-branch).

- 1 Scheme tutorial
  - 1.1 Introduction to Scheme
    - 1.1.1 Scheme sandbox
    - 1.1.2 Scheme variables
    - 1.1.3 Scheme simple data types
    - 1.1.4 Scheme compound data types
      - Pairs
      - Lists
      - Association lists (alists)
      - Hash tables
    - 1.1.5 Calculations in Scheme
    - 1.1.6 Scheme procedures
      - Defining procedures
      - Predicates
      - Return values
    - 1.1.7 Scheme conditionals
      - if
      - cond
  - 1.2 Scheme in LilyPond
    - 1.2.1 LilyPond Scheme syntax
    - 1.2.2 LilyPond variables
    - 1.2.3 Debugging Scheme code
    - 1.2.4 Input variables and Scheme
    - 1.2.5 Importing Scheme in LilyPond
    - 1.2.6 Object properties
    - 1.2.7 LilyPond compound variables
      - Offsets
      - Fractions
      - Extents
      - Property alists
      - Alist chains
    - 1.2.8 LilyPond’s box model
    - 1.2.9 Internal music representation
  - 1.3 Building complicated functions
    - 1.3.1 A first approach (example)
    - 1.3.2 Displaying music expressions
    - 1.3.3 Music properties
    - 1.3.4 Doubling a note with slurs (example)
    - 1.3.5 Adding articulation to notes (example)
- 2 Interfaces for programmers
  - 2.1 LilyPond code blocks
  - 2.2 Scheme functions
    - 2.2.1 Scheme function definitions
    - 2.2.2 Scheme function usage
    - 2.2.3 Void Scheme functions
  - 2.3 Music functions
    - 2.3.1 Music function definitions
    - 2.3.2 Music function usage
    - 2.3.3 Simple substitution functions
    - 2.3.4 Intermediate substitution functions
    - 2.3.5 Mathematics in functions
    - 2.3.6 Functions without arguments
    - 2.3.7 Void music functions
  - 2.4 Event functions
  - 2.5 Markup functions
    - 2.5.1 Markup construction in Scheme
    - 2.5.2 How markups work internally
    - 2.5.3 New markup command definition
      - Markup command definition syntax
      - On properties
      - A complete example
      - Adapting builtin commands
      - Converting markups to strings
    - 2.5.4 New markup list command definition
  - 2.6 Contexts for programmers
    - 2.6.1 Context evaluation
    - 2.6.2 Running a function on all layout objects
  - 2.7 Callback functions
  - 2.8 Unpure-pure containers
  - 2.9 Difficult tweaks
- 3 LilyPond Scheme interfaces
- Appendix A GNU Free Documentation License
- Appendix B Index