\version "2.18.0" \header { snippet-title = "merge-rests-engraver" snippet-author = "Jay Anderson" snippet-source = "http://www.mail-archive.com/lilypond-user%40gnu.org/msg69608.html" snippet-description = \markup { Merge rests of equal duration in different voice } tags = "merge, rest, rests, voice, voices" status = "ready" } #(define has-one-or-less (lambda (lst) (or (null? lst) (null? (cdr lst))))) #(define has-at-least-two (lambda (lst) (not (has-one-or-less lst)))) #(define (all-equal lst pred) (or (has-one-or-less lst) (and (pred (car lst) (cadr lst)) (all-equal (cdr lst) pred)))) #(define merge-markups-engraver (lambda (context) (let ((markups-equal? (lambda (markup-a markup-b) (string=? (markup->string markup-a) (markup->string markup-b)))) (markups '())) `((start-translation-timestep . ,(lambda (trans) (set! markups '()))) (stop-translation-timestep . ,(lambda (trans) (if (and (has-at-least-two markups) (all-equal markups markups-equal?)) (for-each (lambda (mkup) (ly:grob-set-property! mkup 'Y-offset 0)) mkup)))) (acknowledgers (text-interface . ,(lambda (engraver grob source-engraver) (if (eq? 'Markup (assoc-ref (ly:grob-property grob 'meta) 'name)) (set! markups (cons grob markups)))))))))) \score { \new Staff \with { \consists merge-markups-engraver } << \new Voice { \voiceOne c''^\markup "Test" } \new Voice { \voiceTwo c'_\markup "Test" } >> \layout {} }