lilypond-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Using lyrics in a markup


From: jakob lund
Subject: Re: Using lyrics in a markup
Date: Tue, 18 Jan 2011 16:10:13 +0100

2011/1/18 Jan-Peter Voigt <address@hidden>:
> Hello List,
>
> this is a very cool snippet! I also thought of trying this excersize ...
> perhaps tomorrow ;-)
> I think it should be posted to LSR!
> There is one thing I tried: If you have markups in your lyrics:
>
> words = \lyricmode { This is my ex -- am -- ple \markup { \italic text } }
>
> this function will fail.
> Perhaps someone is willing to play this scheme-game a bit further?
>


Sure... You have to play the game, right?

To allow markups, we have to use (markup #:concat ( . . )) instead of
string-concatenate. The flatten-list function also has to be adjusted
to leave the markups intact.

There is no need to call flatten-list from inside the recursion in
lyrics->list. It probably doesn't do any harm in this case, but I
wonder if the original function (extract-named-music) is ever used on
any `heavy' nested music structures, because if so, it might be a good
idea to redefine it? (Theoretically, calling flatten-list from inside
the recursion may result in N^2 calls to flatten-list when returning N
elements from extract-named-music...)

#(define (lyrics->list lyrics)
"Return only syllables and hyphens from  @code{lyrics}."
         (if (ly:music? lyrics)
             (if (memq (ly:music-property lyrics 'name) '(LyricEvent
HyphenEvent))
                 (begin (if (eq? (ly:music-property lyrics 'name) 'LyricEvent)
                            (list (ly:music-property lyrics 'text))
                            (list "--")))
                 (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, but don't flatten markup constructs!"
  (cond ((null? x) '())
        ((not (pair? x)) (list x))
        (else (append (if (markup? (car x))
                          (list (car x))
                          (flatten-nonmarkup-list (car x)))
                      (flatten-nonmarkup-list (cdr x))))))

#(define (reduce-hyphens text)
         ;; Define initial first-word 'wd' and remaining-words 'wds'
         (let eat ((wd (car text)) (wds (cdr text)))
                 (cond
                   ;; Last syllable reached: Terminate recursion
                   ((null? wds) (list wd))
                   ((and (equal? "--" (car wds)) (not (null? (cdr wds))))
                    ;; The next word is a hyphen AND there is a
syllable after that hyphen
                    ;; Concatenate the syllable after the hyphen onto
wd, and recurse
                    (eat (markup #:concat ((markup wd) (markup (cadr wds))))
                         (cddr wds)))
                   ;; Not a hyphen, just use wd as the first word on
the list, and then recurse.
                   (else (cons wd (eat (car wds) (cdr wds)))))))

#(define (lyrics->text lyrics)
         (reduce-hyphens (flatten-nonmarkup-list (lyrics->list lyrics))))


snip

Jakob

> Best regards,
> Jan-Peter
>
>
> On 18.01.2011 12:56, jakob lund wrote:
>>
>> 2011/1/18 Marc Hohl<address@hidden>:
>>>
>>> Am 15.01.2011 21:51, schrieb Neil Puttock:
>>>>
>>>> On 15 January 2011 19:01, Marc Hohl<address@hidden>    wrote:
>>>>
>>>>> Now I wonder whether it is possible to create a kind of text book by
>>>>> including the lyrics in a markup, perhaps with a scheme function which
>>>>> replaces the " -- " by "".
>>>>>
>>>>> Is it possible to store the text in a variable?
>>>>
>>>> [...]
>>>>
>>>> For simplicity I've ignored hyphens, but it shouldn't be too difficult
>>>> to add them (or use their position in the list of strings to restore
>>>> the hyphenated words).
>>>
>>> This is what I got so far:
>>>
>>> \version "2.13.46"
>>>
>>> words = \lyricmode { This is my ex -- am -- ple text }
>>>
>>> #(define (lyrics->list lyrics)
>>> "Return a flat list containing all syllables and hyphens from
>>> address@hidden"
>>>   (let ((extracted-list
>>>          (if (ly:music? lyrics)
>>>              (if (memq (ly:music-property lyrics 'name) '(LyricEvent
>>> HyphenEvent))
>>>                  (begin (if (eq? (ly:music-property lyrics 'name)
>>> 'LyricEvent)
>>>                             (list (ly:music-property lyrics 'text))
>>>                             (list "--")))
>>>                  (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)))))
>>>              '())))
>>>     (flatten-list extracted-list)))
>>>
>>>
>>> text = #(lyrics->list words)
>>>
>>> melody = \relative c' { c4 d e f | g a c2 }
>>>
>>> \new Voice { \melody }
>>> \addlyrics { \words }
>>>
>>> #(markup* (make-line-markup text))
>>>
>>> The function liyrics->list extracts the syllables and the hyphens.
>>
>> Cool!
>>
>>> The second part (eliminating the hyphens in the list and concatenate the
>>> surrounding
>>> syllables) seems a bit harder, but I try to find a solution.
>>
>> That's a nice scheme exercise... The following would work (but not if
>> there are consecutive hyphens)
>>
>> #(define (reduce-hyphens text)
>>          ;; Define initial first-word 'wd' and remaining-words 'wds'
>>          (let eat ((wd (car text)) (wds (cdr text)))
>>                  (cond
>>                    ;; Last syllable reached: Terminate recursion
>>                    ((null? wds) (list wd))
>>                    ((and (equal? "--" (car wds)) (not (null? (cdr wds))))
>>                     ;; The first remaining word is a hyphen AND there
>> is a syllable after that
>>                     ;; Concatenate that syllable onto wd, and recurse
>>                     (eat (string-concatenate (list wd (cadr wds))) (cddr
>> wds)))
>>                    ;; Not a hyphen, just use wd as the first word on
>> the list, and then recurse.
>>                    (else (cons wd (eat (car wds) (cdr wds)))))))
>>
>> #(define (lyrics->text lyrics) (reduce-hyphens (lyrics->list lyrics)))
>>
>> text = #(lyrics->text words)
>>
>> Cheers
>> Jakob.
>>
>>> Regards,
>>>
>>> Marc
>>>
>>> _______________________________________________
>>> lilypond-user mailing list
>>> address@hidden
>>> http://lists.gnu.org/mailman/listinfo/lilypond-user
>>>
>> _______________________________________________
>> lilypond-user mailing list
>> address@hidden
>> http://lists.gnu.org/mailman/listinfo/lilypond-user
>>
>
>
> _______________________________________________
> lilypond-user mailing list
> address@hidden
> http://lists.gnu.org/mailman/listinfo/lilypond-user
>



reply via email to

[Prev in Thread] Current Thread [Next in Thread]