LSR/744/code

< LSR‎ | 744
Zur Navigation springen Zur Suche springen
%% http://lsr.di.unimi.it/LSR/Item?id=744
%% see also http://lilypond.org/doc/v2.18/Documentation/snippets/vocal-music

#(define linebreakindicator "\\")

% \nl command that inserts the placeholder event into a lyrics
nl = #(make-music 'LineBreakEvent)

%% Function to extract strings from lyrics.
%  
#(define (lyrics->list lyrics)
  "Return only syllables and hyphens from  @code{lyrics}."
  (if (ly:music? lyrics)
      (cond 
        ((music-is-of-type? lyrics 'lyric-event)
          (let* ((art (ly:music-property lyrics 'articulations))
                 (hyphen?
                   (not (null?
                     (filter
                       (lambda (m)
                         (music-is-of-type? m 'hyphen-event))
                       art))))
                 (text (ly:music-property lyrics 'text)))
            (if hyphen? (list text hyphen?) (list text))))
        ((music-is-of-type? lyrics 'line-break-event)
         (list linebreakindicator))
        (else 
          (let ((elt (ly:music-property lyrics 'element))
                (elts (ly:music-property lyrics 'elements)))
            (if (ly:music? elt)
                (lyrics->list elt)
                (if (null? elts)
                    '()
                    (map 
                      (lambda(x) (lyrics->list x))
                      elts))))))
      '()))
                
#(define (flatten-nonmarkup-list x)
  "Unnest list one level, but don't flatten markup constructs!"
  ;; The check for markup? is likely not needed
  ;; We let it in for clarity
  (append-map (lambda (e) (if (markup? e) e `(,@e))) x))

#(define (reduce-hyphens text) 
  (if (not (null? text))
      (let eat ((wd (car text)) (wds (cdr text)))
              (cond 
                ((null? wds) (list wd))
                ((and (boolean? (car wds))
                      (not (null? (cdr wds))))
                 (eat (markup #:concat (wd (cadr wds)))
                      (cddr wds)))
                (else (cons wd (eat (car wds) (cdr wds))))))
      '()))
  
#(define-markup-command (verse layout props lyrics) (ly:music?)
  #:properties ((display-nl #f)
                (make-line make-justify-markup))
  "Verse command that marks up a column of \\nl-separated lines"
  (let* ((unnested-lyr-ls 
           (reduce-hyphens (flatten-nonmarkup-list (lyrics->list lyrics))))
         (split-cond? 
           (lambda (a) 
             (and (not display-nl)
                  (equal? a linebreakindicator))))
         (list-of-lines 
           (map 
             (lambda (l) (make-line l))
             (split-list-by-separator unnested-lyr-ls split-cond?))))
    (if (null? unnested-lyr-ls)
        (begin
          (ly:warning "lyrics is empty, returning empty-stencil")
          empty-stencil)
        (interpret-markup layout props (make-column-markup list-of-lines)))))
    
%%%%%%%%%%%%%%%%

mus = \relative c'' { \partial 4. g8 a g e c r4 r8 g' a g | f[ d] }

words = \lyricmode { 
  \override LyricHyphen.minimum-distance = #1.2
  Du lil -- le \markup \italic fis -- \markup \italic ker \nl 
  Du \markup \italic lil -- \markup \italic le fis -- ker 
}

%{
<<
  \new Voice = "mel" \mus
  \new Lyrics \lyricsto "mel" \words
>>
%}

\mus
\addlyrics { \words }

\markup \line \bold { With line breaks (no overrides) }
\markup { \verse #words }

\markup \line \bold { With visible line break character }
\markup { \override #'(display-nl . #t) \verse #words }
%{ 
%%  To have left-aligned word-wrapping with 
%%  long lines, use 
\markup { \override #`(make-line . ,make-wordwrap-markup) \verse #words }
%%  (the default is make-justify-markup)
%}