\version "2.18.0" % Merge identical TextScript objects in multiple voices of a staff, % like they are produced by the partcombiner. % Based on an engraver by Jay Anderson, from % "http://www.mail-archive.com/lilypond-user%40gnu.org/msg69608.html" % Engraver listening for TextScript grobs. % When two or more TextScripts are present at the same moment % and their text content is identical, all but the first one % are omitted through setting their 'stencil property to false. #(define merge-markups-engraver (lambda (context) (let ((markups '()) (processed-markups '())) `((start-translation-timestep . ,(lambda (trans) (set! markups '()))) (stop-translation-timestep . ,(lambda (trans) (if (> (length markups) 1) (begin ;; There are more than one markups at the time-step (set! processed-markups '()) (for-each (lambda (mkup) ;; Retrieve the text content for the iterated markup grob (let ((text (markup->string (ly:grob-property mkup 'text)))) (if (member text processed-markups) ;; If we have already encountered this text omit the grob ... (ly:grob-set-property! mkup 'stencil #f) ;; ... else accept it this time and add it to the list of ;; encountered texts (set! processed-markups (append processed-markups (list text)))))) (reverse markups)))))) (acknowledgers (text-interface . ,(lambda (engraver grob source-engraver) (if (member (assoc-ref (ly:grob-property grob 'meta) 'name) '(TextScript DynamicText )) (set! markups (cons grob markups)))))))))) %%{ musica = \relative c'' { \partcombineApart c1^\markup "Test" c1^\markup "Test" c1^\markup "Test" %%%%%%%%%%%% % TODO % Also handle hairpins (or other spanners). % Obviously removing the stencil of the middle \p doesn't do any harm % to the behaviour of the hairpins. c1 \< c1 \p c1 \> c1 \! } musicb = \relative c' { c1_\markup "Test" c1_\markup "Prost" c1 _\markup "Test" ^\markup "Test-alternative" c1 \< c1 \p c1 \> c1 \! } \score { \new Staff \with { \consists #merge-markups-engraver } \partcombine \musica \musicb \layout {} } %}