Alternatively (as long as we do not want to parse parallel music in order) we 
can use a music function like this:

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\version "2.24"

typing-text = "Goddag Fru Direktör
Det meddelande du sände den andra har landat."
%When I uncomment these dynamics the text jumps around
rhythm = { 4%\f 
           8 8 16 16 8 16 8%\p 
           16 16 8 16 r16 16 r8 8 r8 4 16 16 16 16 4}

typing-list = #(string->list 
                (string-map
                 (lambda (char)
                   (case char
                       ((#\space) #\x2423)
                       ((#\nl) #\x21B5)
                       (else char)))
                 typing-text))

typing-index = 0

mapLettersToRhythm =
#(define-music-function (typing-list rhythm) (list? ly:music?)
   (define index 0)
   (define typing-vector (list->vector typing-list))
   (define (impl mus)
     (display-lily-music mus)
     (if (music-is-of-type? mus 'note-event)
         (begin
          (ly:music-set-property!
           mus 'text
           #{ \markup \typewriter \fontsize #-2 #(string (vector-ref typing-
vector index)) #})
          (set! index (modulo (1+ index) (length typing-list))))
         (let* ((elts (ly:music-property mus 'elements))
                (elt (ly:music-property mus 'element)))
           (if (not (null? elt))
               (impl elt))
           (map impl elts))))
   (impl rhythm)
   rhythm)

\new RhythmicStaff \with {
  \override StaffSymbol.line-count = #0
  \override NoteHead.stem-attachment = #'(0 . 2)
  \override NoteHead.text =
  #(lambda (grob)
     (let* ((cause (ly:grob-property grob 'cause))
            (mcause (ly:event-property cause 'music-cause)))
       (ly:music-property mcause 'text empty-markup)))
  \override NoteHead.stencil = #ly:text-interface::print
}
\mapLettersToRhythm #typing-list \rhythm
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

Cheers,
Valentin

Am Sonntag, 8. Oktober 2023, 13:40:39 CEST schrieb Jean Abou Samra:
> > It was not intentional, that was the actual problem.  When I compiled it
> > without the dynamics it came out in the same order as the input, but that
> > was only a lucky coincidence then, right?
> 
> Yes.
> 
> > Do you have any suggestions for how to get them ordered?
> 
> When you need to process grobs ordered by time, use an engraver:
> 
> 
> 
> \version "2.24.2"
> 
> typing-text = "Goddag Fru Direktör
> Det meddelande du sände den andra har landat."
> rhythm = {
>   4\f
>   8 8 16 16 8 16 8\p
>   16 16 8 16 r16 16 r8 8 r8 4 16 16 16 16 4
> }
> 
> 
> transformed-text =
> #(string-map
>   (lambda (char)
>      (case char
>        ((#\space) #\x2423)
>        ((#\nl) #\x21B5)
>        (else char)))
>              typing-text)
> 
> #(define (Letters_engraver context)
>    (let ((index 0))
>      (make-engraver
>       (acknowledgers
>        ((note-head-interface engraver grob source-engraver)
>         (let ((char (string-ref transformed-text index)))
>           (set! index (modulo (1+ index) (string-length transformed-text)))
>           (ly:grob-set-property! grob 'text (string char))))))))
> 
> \new RhythmicStaff \with {
>   \override StaffSymbol.line-count = #0
>   \override NoteHead.stem-attachment = #'(0 . 2)
>   \consists #Letters_engraver
>   \override NoteHead.stencil = #ly:text-interface::print
> }
> \rhythm

Attachment: signature.asc
Description: This is a digitally signed message part.

Reply via email to