86 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			86 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
Better_Merge_rests_engraver =
 | 
						|
#(lambda (context)
 | 
						|
  (define (has-one-or-less? lst) (or (null? lst) (null? (cdr lst))))
 | 
						|
  (define (has-at-least-two? 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 (measure-count-eqv? a b)
 | 
						|
    (eqv?
 | 
						|
     (ly:grob-property a 'measure-count)
 | 
						|
     (ly:grob-property b 'measure-count)))
 | 
						|
 | 
						|
  (define (rests-all-unpitched? rests)
 | 
						|
    "Returns true when all rests do not override the staff-position grob
 | 
						|
    property. When a rest has a position set we do not want to merge rests at
 | 
						|
    that position."
 | 
						|
    (every (lambda (rest) (null? (ly:grob-property rest 'staff-position))) rests))
 | 
						|
 | 
						|
  (define (less-by-layer a b)
 | 
						|
    (<
 | 
						|
      (ly:grob-property b 'layer 0)
 | 
						|
      (ly:grob-property a 'layer 0)))
 | 
						|
 | 
						|
  (define (merge-mmrests mmrests)
 | 
						|
    "Move all multimeasure rests to the single voice location."
 | 
						|
    (if (all-equal? mmrests measure-count-eqv?)
 | 
						|
        (begin
 | 
						|
          (for-each
 | 
						|
           (lambda (rest) (ly:grob-set-property! rest 'direction CENTER))
 | 
						|
           mmrests)
 | 
						|
          (for-each
 | 
						|
           (lambda (rest) (ly:grob-set-property! rest 'transparent #t))
 | 
						|
           (cdr (sort mmrests less-by-layer))))))
 | 
						|
 | 
						|
  (define (merge-rests rests)
 | 
						|
    (for-each
 | 
						|
     (lambda (rest) (ly:grob-set-property! rest 'staff-position 0))
 | 
						|
     rests)
 | 
						|
    (for-each
 | 
						|
     (lambda (rest) (ly:grob-set-property! rest 'transparent #t))
 | 
						|
     (cdr (sort rests less-by-layer))))
 | 
						|
 | 
						|
  (let ((mmrests '())
 | 
						|
        (rests '())
 | 
						|
        (dots '()))
 | 
						|
    (make-engraver
 | 
						|
     ((start-translation-timestep translator)
 | 
						|
      (set! rests '())
 | 
						|
      (set! mmrests '())
 | 
						|
      (set! dots '()))
 | 
						|
     (acknowledgers
 | 
						|
      ((dot-column-interface engraver grob source-engraver)
 | 
						|
       (if (not (ly:context-property context 'suspendRestMerging #f))
 | 
						|
           (set!
 | 
						|
            dots
 | 
						|
            (append (ly:grob-array->list (ly:grob-object grob 'dots))
 | 
						|
                    dots))))
 | 
						|
      ((rest-interface engraver grob source-engraver)
 | 
						|
       (cond
 | 
						|
        ((ly:context-property context 'suspendRestMerging #f)
 | 
						|
         #f)
 | 
						|
        ((grob::has-interface grob 'multi-measure-rest-interface)
 | 
						|
         (set! mmrests (cons grob mmrests)))
 | 
						|
        (else
 | 
						|
         (set! rests (cons grob rests))))))
 | 
						|
     ((stop-translation-timestep translator)
 | 
						|
      (let (;; get a list of the rests 'duration-lengths, 'duration-log does
 | 
						|
            ;; not take dots into account
 | 
						|
            (durs
 | 
						|
             (map
 | 
						|
              (lambda (g)
 | 
						|
                (ly:duration->moment
 | 
						|
                 (ly:prob-property
 | 
						|
                  (ly:grob-property g 'cause)
 | 
						|
                  'duration)))
 | 
						|
              rests)))
 | 
						|
        (if (and
 | 
						|
             (has-at-least-two? rests)
 | 
						|
             (all-equal? durs equal?)
 | 
						|
             (rests-all-unpitched? rests))
 | 
						|
            (begin
 | 
						|
              (merge-rests rests)
 | 
						|
              ;; ly:grob-suicide! works nicely for dots, as opposed to rests.
 | 
						|
              (if (pair? dots) (for-each ly:grob-suicide! (cdr dots)))))
 | 
						|
        (if (has-at-least-two? mmrests)
 | 
						|
            (merge-mmrests mmrests))))))) |