\version "2.15.16"

boxNotes = #(define-music-function (parser location extra-Y music)
                                                   (number? ly:music?)
 #{
   \once \override TextSpanner #'style = #'line
   \once \override TextSpanner #'bound-details #'left #'attach-dir = #-1
   \once \override TextSpanner #'bound-details #'left #'padding = #-1
   \once \override TextSpanner #'bound-details #'right #'attach-dir = #1
   \once \override TextSpanner #'bound-details #'right #'padding = #-1
   \once \override TextSpanner #'after-line-breaking = #(lambda (grob)
     (let* ((sys (ly:grob-system grob))
            (columns (ly:grob-array->list (ly:grob-object grob 'note-columns)))
            (stems (map (lambda (n) (ly:grob-object n 'stem)) columns))
            (stem-extents-up (map (lambda (n) (cdr (ly:grob-property n 'Y-extent))) stems))
            (stem-extents-down (map (lambda (n) (car (ly:grob-property n 'Y-extent))) stems))
            (highest (apply max stem-extents-up))
            (lowest (apply min stem-extents-down))
            (stem-dy (- highest lowest))
            (left-X (ly:grob-relative-coordinate grob sys X))
            (right-X (ly:grob-relative-coordinate (ly:spanner-bound grob RIGHT) sys X))
            (dx (- right-X left-X))
            (ln (lambda (dir)
              (string-append
                "0.1 setlinewidth 0 -"
                (number->string (+ 1 stem-dy $extra-Y))
                " rlineto "
                (number->string (* dx dir))
                " 0 rlineto stroke"))))

    ;; uncommenting any of the following lines will "kill" the left and right
    ;; text of the spanner

      ;(display (ly:grob-relative-coordinate grob sys Y)) (newline)
      ;(display (ly:grob-extent grob sys Y)) (newline)
      ;(display (ly:grob-relative-coordinate grob (ly:grob-parent grob Y) Y)) (newline)
      ;(display (ly:grob-extent grob (ly:grob-parent grob Y) Y)) (newline)

       (ly:grob-set-nested-property! grob '(bound-details left text)
         (markup #:small #:bold #:concat
           (#:postscript (ln 1))))

       (ly:grob-set-nested-property! grob '(bound-details right text)
         (markup #:small #:bold #:concat
           (#:postscript (ln -1))))))

   #(begin
      (let* ((elts (ly:music-property $music 'elements)))
        (set! (ly:music-property (car elts) 'elements)
          (cons (make-music 'TextSpanEvent 'span-direction -1)
                (ly:music-property (car elts) 'elements)))
        (set! (ly:music-property (car (reverse elts)) 'elements)
          (cons (make-music 'TextSpanEvent 'span-direction 1)
                (ly:music-property (car (reverse elts)) 'elements)))
        (ly:export (make-music 'SequentialMusic 'elements (list $music)))))
#})

\relative c'' {
  \boxNotes #0.5 { a c e a }
}


