%\version "2.14.2"
\version "2.12.3"

\pointAndClickOff

#(define (left-bound grob refp target-list1)
   (if (null? target-list1)
       #f
       (let* ((X-coord (lambda (q) (ly:grob-relative-coordinate q refp X)))
              (target (car target-list1)))
         (define compare (lambda (q)
           (if (not (eq? refp (ly:grob-common-refpoint grob (car q) X)))
               ; if grob to align is related to candidate (except at topmost level) use
               ; candidate as left bound
               (set! target (car q))
               ; otherwise, choose closest grob to left
               (if (and (< (X-coord (car q)) (X-coord grob))
                        (< (- (X-coord grob) (X-coord (car q)))
                           (- (X-coord grob) (X-coord target))))
                   (set! target (car q))
                   '()))
           (if (null? (cdr q))
               target
               (compare (cdr q)))))
         (compare target-list1))))

#(define (right-bound grob refp target-list2)
   ; find the grob with the X-coordinate closest to object to be aligned
   (if (null? target-list2)
       #f
       (let ((X-coord (lambda (q) (ly:grob-relative-coordinate q refp X)))
             (target (car target-list2)))
         (define compare (lambda (q)
           (if (< (abs (- (X-coord grob) (X-coord (car q))))
                  (abs (- (X-coord grob) (X-coord target))))
               (set! target (car q))
               '())
           (if (null? (cdr q))
               target
               (compare (cdr q)))))
         (compare target-list2))))

#(define ((center-between ref1 ref2 extra-Y-offset) grob)
   (let* ((refp (ly:grob-system grob))
          (all-grobs (ly:grob-array->list (ly:grob-object refp 'all-elements)))
          (X-coord (lambda (q) (ly:grob-relative-coordinate q refp X)))
          (X-extent (lambda (q) (ly:grob-extent q refp X)))
          (grob-name (lambda (q) (assq-ref (ly:grob-property q 'meta) 'name)))
          (target-list1
            (filter (lambda (q) (eq? ref1 (grob-name q))) all-grobs))
          (target-list2
            (filter (lambda (q) (eq? ref2 (grob-name q))) all-grobs))
          (target-left (left-bound grob refp target-list1))
          (target-right
            (if target-left
                (right-bound grob
                             refp
                             (remove (lambda (q) (or (not (eq? refp (ly:grob-common-refpoint grob q X)))
                                                     (<= (X-coord q) (X-coord target-left))))
                                     target-list2))
                #f)))

     ; display on console whether requested bounding grobs are present
     (if (or (not target-left)
             (not target-right))
         (begin
           (format #t "Failure to center ~a between ~a and ~a~%" grob ref1 ref2)
           (format #t "Present in system? ~a ~a  ~a ~a~%"
             ref1
             (if (null? target-list1)
                 #f #t)
             ref2
             (if (null? target-list2)
                 #f #t))
           (if (and (not (null? target-list1))
                    (not (null? target-list2)))
               (format #t "left bound: ~a  right bound: ~a~%" target-left target-right))
            (format #t "_______________________________________________~%")))

     ; center between right of grob to left and left of grob to right
     (if (and target-left target-right)
         (cons
           (- (- (interval-center (X-extent grob))
                 (/ (+ (cdr (X-extent target-left))
                       (car (X-extent target-right)))
                    2)))
           extra-Y-offset))))

centerGrobBetween =
  #(define-music-function (parser location grob-to-align ref1 ref2 extra-Y-offset)
                          (string? symbol? symbol? number?)
     #{
        \overrideProperty  $grob-to-align #'extra-offset #(center-between $ref1 $ref2 $extra-Y-offset)
     #}
  )

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

redLn = \markup \with-color #red \override #'(thickness . 2.5) \draw-line #'(0 . 6)
blueLn = \markup \with-color #blue \override #'(thickness . 2.5) \draw-line #'(0 . 6)
greenLn = \markup \with-color #green \override #'(thickness . 2.5) \draw-line #'(0 . 6)
yellowLn = \markup \with-color #yellow \override #'(thickness . 4.5) \draw-line #'(0 . 6)
uparrow = \markup \combine \arrow-head #Y #UP ##f \draw-line #'(0 . -2)
long = \markup { "zzzxxxxxxy|yxxxxxxzzz" }

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

one =
\relative c' {
  \centerGrobBetween #"TextScript" #'LeftEdge #'BarLine #7
  c'4-\redLn 
  c c c

  \centerGrobBetween #"TextScript" #'Clef #'BarLine #7
  c4-\blueLn c c c

  \centerGrobBetween #"TextScript" #'TimeSignature #'BarLine #7
  c4-\greenLn c c c

  \centerGrobBetween #"TextScript" #'Clef #'TimeSignature #8
  c4-\yellowLn c c c

  \override Score.SpacingSpanner #'shortest-duration-space = #2.5
  c
  \centerGrobBetween #"Script" #'Stem #'NoteHead #0
  d\turn e c

  c
  \centerGrobBetween #"Script" #'Stem #'Stem #0
  d\turn e c

  c
  \centerGrobBetween #"TextScript" #'Stem #'Stem #0
  d^\long e c

 a4 a a a |
 \time 5/4
 <<
  { a4 a a a a | }
  {
    \centerGrobBetween #"Score.MultiMeasureRestText" #'BarLine #'BarLine #0
    \once \override MultiMeasureRest #'transparent = ##t
     R4*5_\uparrow |
  }
 >>
 \time 4/4
 a4 a a a |
}

two =
\relative c' {
  %\centerGrobBetween #"TextScript" #'LeftEdge #'BarLine #7
  c4%-\redLn 
  c c c

  %\centerGrobBetween #"TextScript" #'Clef #'BarLine #7
  c4%-\blueLn 
  c c c

  %\centerGrobBetween #"TextScript" #'TimeSignature #'BarLine #7
  c4%-\greenLn 
  c c c

  %\centerGrobBetween #"TextScript" #'Clef #'TimeSignature #8
  c4%-\yellowLn 
  c c c

  %\override Score.SpacingSpanner #'shortest-duration-space = #2.5
  c
  \centerGrobBetween #"Script" #'Stem #'NoteHead #0
  d\turn e c

  c
  \centerGrobBetween #"Script" #'Stem #'Stem #0
  d\turn e c

  c
  \centerGrobBetween #"TextScript" #'Stem #'Stem #0
  d_\long 
  e c

 a4 a a a |
 \time 5/4
 <<
  { a4 a a a a | }
  {
    \centerGrobBetween #"Score.MultiMeasureRestText" #'BarLine #'BarLine #0
    \once \override MultiMeasureRest #'transparent = ##t
     R4*5_\uparrow |
  }
 >>
 \time 4/4
 a4 a a a |
}


\score  {
        \new StaffGroup = "0ne" <<
	\new Staff \one
	\new Staff \one
	>>
}

\markup \vspace #5

\score  {
        \new Staff = "two" <<
        	\new Voice { \voiceOne\one }
	\new Voice { \voiceTwo\two }
	>>
}

