Adapting builtin commands

A good way to start writing a new markup command, is to take example on a builtin one. Most of the markup commands provided with LilyPond can be found in file scm/define-markup-commands.scm.

For instance, we would like to adapt the \draw-line command, to draw a double line instead. The \draw-line command is defined as follow (documentation stripped):

(define-markup-command (draw-line layout props dest)
  (number-pair?)
  #:category graphic
  #:properties ((thickness 1))
  "…documentation…"
  (let ((th (* (ly:output-def-lookup layout 'line-thickness)
               thickness))
        (x (car dest))
        (y (cdr dest)))
    (make-line-stencil th 0 0 x y)))

To define a new command based on an existing one, copy the definition, and change the command name. The #:category keyword can be safely removed, as it is only used for generating LilyPond documentation, and is of no use for user-defined markup commands.

(define-markup-command (draw-double-line layout props dest)
  (number-pair?)
  #:properties ((thickness 1))
  "…documentation…"
  (let ((th (* (ly:output-def-lookup layout 'line-thickness)
               thickness))
        (x (car dest))
        (y (cdr dest)))
    (make-line-stencil th 0 0 x y)))

Then, a property for setting the gap between two lines is added, called line-gap, defaulting, e.g., to 0.6:

(define-markup-command (draw-double-line layout props dest)
  (number-pair?)
  #:properties ((thickness 1)
                (line-gap 0.6))
  "…documentation…"
  …

Finally, the code for drawing two lines is added. Two calls to make-line-stencil are used to draw the lines, and the resulting stencils are combined using ly:stencil-add:

#(define-markup-command (my-draw-line layout props dest)
   (number-pair?)
   #:properties ((thickness 1)
                 (line-gap 0.6))
   "..documentation.."
   (let* ((th (* (ly:output-def-lookup layout 'line-thickness)
                 thickness))
          (dx (car dest))
          (dy (cdr dest))
          (w (/ line-gap 2.0))
          (x (cond ((= dx 0) w)
                   ((= dy 0) 0)
                   (else (/ w (sqrt (+ 1 (* (/ dx dy) (/ dx dy))))))))
          (y (cond ((= dy 0) w)
                   ((= dx 0) 0)
                   (else (/ w (sqrt (+ 1 (* (/ dy dx) (/ dy dx))))))))
          (y (* (if (< (* dx dy) 0) 1 -1) y)))
     (ly:stencil-add
      (make-line-stencil th x y (+ dx x) (+ dy y))
      (make-line-stencil th (- x) (- y) (- dx x) (- dy y)))))

\markup \my-draw-line #'(4 . 3)
\markup \override #'(line-gap . 1.2) \my-draw-line #'(4 . 3)
[image of music]

Extending LilyPond v2.27.0 (development-branch).