\version "2.23.9" #(set-object-property! 'annotationText 'translation-type? markup?) #(define (Annotation_spanner_engraver context) (let* ((last-annot (make-symbol "unique")) (spanner #f)) (make-engraver ((process-music engraver) (let* ((raw-annot (ly:context-property context 'annotationText)) (annot (if (markup? raw-annot) raw-annot "")) (parenthesized-annot (if (markup? raw-annot) (make-concat-markup (list "(" raw-annot ")")) "")) (bracketed-annot (if (markup? raw-annot) (make-concat-markup (list "[" raw-annot "]")) ""))) (if (not (equal? annot last-annot)) (let ((musical-column (ly:context-property context 'currentMusicalColumn)) (non-musical-column (ly:context-property context 'currentCommandColumn)) (previous-spanner spanner)) (set! last-annot annot) (if spanner (begin (ly:spanner-set-bound! spanner RIGHT non-musical-column) (ly:engraver-announce-end-grob engraver spanner '()) (set! spanner #f))) (set! spanner (ly:engraver-make-grob engraver 'TextSpanner '())) (ly:spanner-set-bound! spanner LEFT musical-column) (ly:grob-set-property! spanner 'bound-details `((left (text . ,annot) (attach-dir . ,LEFT)) (left-broken (text . ,parenthesized-annot) (end-on-note . #t)) (right) (right-broken (text)))) (if previous-spanner (ly:grob-set-property! previous-spanner 'after-line-breaking (lambda (broken-previous-spanner) (let ((broken-non-musical-column (ly:spanner-bound broken-previous-spanner RIGHT))) (if (eqv? LEFT (ly:item-break-dir broken-non-musical-column)) (ly:grob-set-nested-property! broken-previous-spanner '(bound-details right text) (make-general-align-markup X RIGHT bracketed-annot))))))) (ly:grob-set-property! spanner 'font-shape '()) (ly:grob-set-property! spanner 'style 'none) ;; Use Stem.direction to recognize which voice this is. It'd ;; be nicer if \voiceOne etc. were events ... (let* ((def (ly:context-grob-definition context 'Stem)) (dir (assq-ref def 'direction))) (if (number? dir) (ly:grob-set-property! spanner 'direction dir))))))) (acknowledgers ((note-column-interface engraver grob source-engraver) (ly:pointer-group-interface::add-grob spanner 'note-columns grob))) ((finalize engraver) (if spanner (let ((non-musical-column (ly:context-property context 'currentCommandColumn))) (ly:spanner-set-bound! spanner RIGHT non-musical-column))))))) \layout { \context { \Voice \consists #Annotation_spanner_engraver } } annotation = \set annotationText = \etc noAnnotation = \unset annotationText << \new Staff { \repeat unfold 14 { c'1 } } \new Staff { \annotation "a 2" c'1 1 \break 1 1 1 ~ \break 1 1 \key c\minor \time 2/2 \annotation "a 3" 1 \break 1 \annotation "a 4" \break 1 2 \annotation "a 42" 2 1 \noAnnotation \break 1 \break \annotation "a laturca" 1 } >> << { \annotation "a 2" c''1 \break 1 } \\ { \annotation "a 2" c'1 1 } >>