\version "2.19.82" %% after 'Adding extra fingering with scheme' %% http://lsr.di.unimi.it/LSR/Item?id=83 endTextSpanners = #(define-music-function (parser location music) (ly:music?) (let ((script #{ \stopTextSpan #}) (do-it? #f) (last-seen #f)) (define (append-script-at! my-music prop) (set! (ly:music-property my-music prop) (append (ly:music-property my-music prop) (list (ly:music-deep-copy script)))) my-music) (map-some-music (lambda (mus) (case (ly:music-property mus 'name) ((EventChord) (set! last-seen mus) (let* ((starts (extract-typed-music mus 'text-span-event))) (cond ((and (not do-it?) (pair? starts)) (set! do-it? #t) mus) ((and do-it? (pair? starts)) (append-script-at! mus 'elements)) (else mus)))) ((NoteEvent RestEvent SkipEvent) (set! last-seen mus) (let* ((starts (extract-typed-music mus 'text-span-event))) (cond ((and (not do-it?) (pair? starts)) (set! do-it? #t) mus) ((and do-it? (pair? starts)) (append-script-at! mus 'articulations)) (else mus)))) (else #f))) music) (case (ly:music-property last-seen 'name) ((EventChord) (append-script-at! last-seen 'elements)) ((NoteEvent RestEvent SkipEvent) (append-script-at! last-seen 'articulations)) (else #f)) (set! do-it? #f) (set! last-seen #f) music)) #(define (minimum-length-from-stencil process-string?) ;; Set the minimum-length of a grob, which is supposed to be a TextSpanner, ;; to the length of the stencil of bound-details.left.text plus 0.1 (lambda (grob) (let* ((bound-details (ly:grob-property grob 'bound-details)) (lft (assoc-get 'left bound-details)) (txt (assoc-get 'text lft)) (txt-stil (if (markup? txt) (grob-interpret-markup grob (if process-string? (markup->string txt) txt)) #f)) (txt-x-ext (if txt-stil (ly:stencil-extent txt-stil X) #f)) (txt-x-length (if (and txt-x-ext (interval-sane? txt-x-ext)) (- (cdr txt-x-ext) (car txt-x-ext)) 0))) ;; debugging aid ; (newline) ; (display-scheme-music ; (list ; (cons 'txt txt) ; (cons 'txt-stil txt-stil) ; (cons 'txt-x-ext txt-x-ext) ; (cons 'txt-x-length txt-x-length))) (+ txt-x-length 0.1)))) testII = #(define-event-function (zero-dimensions? txt)((boolean? #f) markup?) ;; Don't use manual \start/stopTextSpan while using this function. #{ -\tweak style #'none -\tweak springs-and-rods #ly:spanner::set-spacing-rods -\tweak minimum-length #(minimum-length-from-stencil #f) -\tweak minimum-length-after-break 0 -\tweak font-shape #'upright -\tweak bound-details.left.text #(if zero-dimensions? (make-with-dimensions-markup empty-interval empty-interval txt) txt) -\tweak bound-details.left-broken.text ##f \startTextSpan #}) break = \break % {} \score { \new Staff << \relative { \time 2/4 c''8 d16 c c8 d16 c c2 \break c8 d16 c c8 d16 c c2 } \new Voice \endTextSpanners { s4\testII "foobar" s8\testII "foobarq" s8\testII "John & Jane Doe" s2 s4\testII "foobar" s8\testII "foobarq" s \testII ##t "John & Jane Doe" s2 } >> \layout { ragged-right = ##t \override TextSpanner.staff-padding = 2 %\override TextSpanner.direction = -1 } } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Test default TextSpanner with long left-text at line-break %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% %% \paper { ragged-right = ##t } %% { %% c'1-\tweak bound-details.left.text "John & Jane Doe" \startTextSpan %% \break %% d'\stopTextSpan %% } %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Tests for \endTextSpanners %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% %% \endTextSpanners %% { c'4-3\startTextSpan \startTextSpan r c'4 } %% %% \endTextSpanners %% { %% c'4 4\startTextSpan 4 4 %% \repeat volta 2 { %% 4\startTextSpan 4 %% \tuplet 3/2 { 4\startTextSpan 4 4 } %% } %% }