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.


Reply via email to