Jump to content

Centering markup on note heads automatically

From LilyPond wiki

For technical reasons, text scripts attached to note heads cannot easily be centered on a note head's width, unlike articulations.

Instead of using trial-and-error offset tweaks, this snippet uses a Scheme engraver to reset the horizontal parent of each markup to a NoteColumn. This also allows text to follow note heads which have been shifted via force-hshift.

\version "2.24.0"

#(define (Text_align_engraver ctx)
  (let ((scripts '())
        (note-column #f))
    (make-engraver
     (acknowledgers
      ((note-column-interface trans grob source)
       ;; cache NoteColumn in this Voice context
       (set! note-column grob))
      ((text-script-interface trans grob source)
       ;; whenever a TextScript is acknowledged,
       ;; add it to `scripts' list
       (set! scripts (cons grob scripts))))
     ((stop-translation-timestep trans)
      ;; if any TextScript grobs exist,
      ;; set NoteColumn as X-parent
      (for-each (lambda (script)
		  (set! (ly:grob-parent script X) note-column))
		scripts)
      ;; clear scripts ready for next timestep
      (set! scripts '())))))

\layout {
  \context {
    \Voice
    \consists #Text_align_engraver
    \override TextScript.X-offset =
      #ly:self-alignment-interface::aligned-on-x-parent
    \override TextScript.self-alignment-X = #CENTER
  }
}

%% Remark:
%% Once the LSR moves to 2.20 the engraver could be deleted,
%% sufficient would be:
%{
\layout {
  \context {
    \Voice
    \override TextScript.self-alignment-X = #CENTER
    \override TextScript.parent-alignment-X = #CENTER
  }
}
%}

\new Staff <<
  \relative c'' {
    \override NoteColumn.force-hshift = #3
    c1-\markup { \arrow-head #Y #DOWN ##t }
  }
  \\
  \relative c' {
    a4 a-\markup { \huge ^ } a a
  }
>>