On 2024-11-09 11:25, Kieren MacMillan wrote:
Hi Stu,

I managed to underline a single word using the LilyPond '\underline', but would 
like to underline phrases without spaces and durations appended.
Surround them in quotes, not braces.

The output shows:
The 'skip' at the beginning appears to be ignored;
No, the lyrics are simply center-aligned, so it looks that way — use layout { 
ragged-right = ##f } to see what I mean.

In lyricmode, there's an override for italic, e.g.:
   \override Lyrics.LyricText.font-shape = #'italic
Is there something similar for underline?
Not exactly… but I found a decade-old Scheme engraver that I believe does what 
you want.

Hope it helps!
Kieren.

%%%  SNIPPET BEGINS
\version "2.25.11"

#(define (add-bound-item spanner item)
    (if (null? (ly:spanner-bound spanner LEFT))
        (ly:spanner-set-bound! spanner LEFT item)
        (ly:spanner-set-bound! spanner RIGHT item)))

#(define (axis-offset-symbol axis)
    (if (eq? axis X) 'X-offset 'Y-offset))

#(define (set-axis! grob axis)
    (if (not (number? (ly:grob-property grob 'side-axis)))
        (begin
          (set! (ly:grob-property grob 'side-axis) axis)
          (ly:grob-chain-callback
           grob
           (if (eq? axis X)
               ly:side-position-interface::x-aligned-side
               ly:side-position-interface::y-aligned-side)
           (axis-offset-symbol axis)))))

#(define (underline-engraver context)
    (let ((span '())
          (finished '())
          (current-event '())
          (event-drul '(() . ())))
      (list (cons 'listeners
                  (list (cons 'text-span-event
                              (lambda (engraver event)
                                (if (= START (ly:event-property event 
'span-direction))
                                    (set-car! event-drul event)
                                    (set-cdr! event-drul event))))))
            (cons 'acknowledgers
                  (list (cons 'lyric-syllable-interface
                              (lambda (engraver grob source-engraver)
                                (if (ly:spanner? span)
                                    (begin
                                      (ly:pointer-group-interface::add-grob 
span 'note-columns grob)
                                      (add-bound-item span grob)))
                                (if (ly:spanner? finished)
                                    (begin
                                      (ly:pointer-group-interface::add-grob 
finished 'note-columns grob)
                                      (add-bound-item finished grob)))))))
            (cons 'process-music
                  (lambda (trans)
                    (if (ly:stream-event? (cdr event-drul))
                        (if (null? span)
                            (ly:warning "cannot find start of underline")
                            (begin (set! finished span)
                                   (ly:engraver-announce-end-grob trans 
finished current-event)
                                   (set! span '())
                                   (set! current-event '())
                                   (set-cdr! event-drul '()))))
                    (if (ly:stream-event? (car event-drul))
                        (begin (set! current-event (car event-drul))
                               (set! span (ly:engraver-make-grob trans 
'TextSpanner current-event))
                               (set-axis! span Y)
                               (set-car! event-drul '())))))
            (cons 'stop-translation-timestep
                  (lambda (trans)
                    (if (and (ly:spanner? span)
                             (null? (ly:spanner-bound span LEFT)))
                        (set! (ly:spanner-bound span LEFT)
                              (ly:context-property context 
'currentMusicalColumn)))
                    (if (ly:spanner? finished)
                        (begin
                          (if (null? (ly:spanner-bound finished RIGHT))
                              (set! (ly:spanner-bound finished RIGHT)
                                    (ly:context-property context 
'currentMusicalColumn)))
                          (set! finished '())
                          (set! event-drul '(() . ()))))))
            (cons 'finalize
                  (lambda (trans)
                    (if (ly:spanner? finished)
                        (begin
                          (if (null? (ly:spanner-bound finished RIGHT))
                              (set! (ly:spanner-bound finished RIGHT)
                                    (ly:context-property context 
'currentMusicalColumn)))
                          (set! finished '())))
                    (if (ly:spanner? span)
                        (begin
                          (ly:warning "unterminated underline")
                          (ly:grob-suicide! span)
                          (set! span '()))))))))

\layout {
   ragged-right = ##f
   indent = 0
   \context {
     \Lyrics
     \consists #underline-engraver
     \override TextSpanner.direction = #DOWN
     \override TextSpanner.style = #'line
     \override TextSpanner.outside-staff-priority = ##f
     \override TextSpanner.padding = #0.2 % sets the distance of the line from 
the lyrics
     \override TextSpanner.bound-details =
     #`((left . ((Y . 0)
                 (padding . 0)
                 (attach-dir . ,LEFT)))
        (left-broken . ((end-on-note . #t)))
        (right . ((Y . 0)
                  (padding . 0)
                  (attach-dir . ,RIGHT))))
   }
}

eighthNotes = {
   c'8 8 8 8 \break
   c'8 8 8 8
}

words = \lyricmode {
   \skip 8 Two4 \startTextSpan Four8 Five Six \stopTextSpan Seven8 Eight
   }

   <<
   \new Voice = "one" \eighthNotes
   \new Lyrics \lyricsto "one" \words
%%%  SNIPPET ENDS

______________________________________________

My work day may look different than your work day. Please do not feel obligated 
to read or respond to this email outside of your normal working hours.

That's wonderful Kiernan!
I'm not much of a Scheme writer, so I couldn't have come up with your solution.
I would like to have the whole bar on a single line.
If I remove the break, the result is wrong.
I changed the two definitions as follows:
eighthNotes = {
  c'8 8 8 8 \break
  c'8 8 8 8
  c'8 8 8 8 8 8 8 8
}
words = \lyricmode {
  \skip 8 Two4 \startTextSpan Four8 Five Six \stopTextSpan Seven8 Eight
  \skip 8 Two4 \startTextSpan Four8 Five Six \stopTextSpan Seven8 Eight
}

The second bar loses the '\skip 8'.


Reply via email to