\version "2.18.0" alignGrob = #(define-music-function (parser location grob-to-align reference-grob dir extra-displacement) (symbol-list? symbol-list? number-or-pair? number-or-pair?) #{ \override $grob-to-align . extra-offset = #(lambda (grob) (let* ((sys (ly:grob-system grob)) (array (ly:grob-object sys 'all-elements)) (default-coord (ly:grob-relative-coordinate grob sys X)) ;; We only want the name of the grob we're aligning to. If ;; input is Context.Grob, deal with it silently. (reference-grob (if (pair? reference-grob) (car (reverse reference-grob)) reference-grob)) (grob-name (lambda (x) (assq-ref (ly:grob-property x 'meta) 'name))) (lst (filter (lambda (x) (eq? reference-grob (grob-name x))) (ly:grob-array->list array))) ;; Find the grob with the X-coordinate closest to object to be aligned. (ref (reduce (lambda (elem prev) (if (< (abs (- default-coord (ly:grob-relative-coordinate elem sys X))) (abs (- default-coord (ly:grob-relative-coordinate prev sys X)))) elem prev)) '() lst)) ;; If user specified single direction, use it for both objects. (dir (if (pair? dir) dir (cons dir dir))) ;; Select requested alignment. Note: fractional values are ;; leveled off to RIGHT or LEFT. (proc (lambda (x) (cond ((= x 0) interval-center) ((< x 0) car) (else cdr)))) (grob-side (proc (car dir))) (ref-side (proc (cdr dir))) (extra-X-offset (if (pair? extra-displacement) (car extra-displacement) 0.0)) (extra-Y-offset (if (pair? extra-displacement) (cdr extra-displacement) extra-displacement))) (if (ly:grob? ref) (cons (+ (- (ref-side (ly:grob-extent ref sys X)) (grob-side (ly:grob-extent grob sys X))) extra-X-offset) extra-Y-offset) (cons 0.0 0.0)))) #} ) ln = \markup \with-color #red \draw-line #'(0 . 6) uparrow = \markup \combine \arrow-head #Y #UP ##f \draw-line #'(0 . -2) downarrow = \markup \combine \arrow-head #Y #DOWN ##f \draw-line #'(0 . 2) \relative c' { %% bar 1 \time 3/4 \key d \major d \alignGrob TextScript KeySignature #CENTER #6 e-\ln \alignGrob TextScript Clef #RIGHT #5.5 fis-\ln %% bar 2 \time 5/4 \alignGrob TextScript BarLine #CENTER #-5.5 e^\ln \alignGrob TextScript Hairpin #RIGHT #1 d(_\ln \alignGrob TextScript Slur #CENTER #0 e_\uparrow \alignGrob TextScript StaffSymbol #CENTER #0 fis^\markup \center-column { "mid-staff" \downarrow } d)\< %% bar 3 \time 3/4 \alignGrob TextScript TimeSignature #LEFT #-5 e^\ln \alignGrob TextScript TimeSignature #RIGHT #-5 fis^\ln d %% bar 5 \alignGrob TextScript Stem #CENTER #-5.5 e\!^\ln fis \alignGrob TextScript Accidental #CENTER #0 d!_\uparrow %% bar 6 \time 2/4 \alignGrob Stem NoteHead #CENTER #0 fis \alignGrob Stem NoteHead #CENTER #0 \alignGrob Script BarLine #CENTER #0.5 \alignGrob TextScript StaffSymbol #RIGHT #0 d\fermata _"end" \bar "||" } thickln = \markup { \override #'(thickness . 5) \with-color #red \draw-line #'(0 . 6) } \new Staff { \relative c' { \override Staff.TimeSignature.layer = #2 \time 3/4 \alignGrob TextScript TimeSignature #'(1 . -1) #5.5 %% alternately: %% \alignGrob TextScript TimeSignature #(cons RIGHT LEFT) #5.5 s2.-\thickln \time 3/4 \alignGrob TextScript TimeSignature #'(0 . -1) #5.5 s-\thickln \time 3/4 \alignGrob TextScript TimeSignature #'(-1 . -1) #5.5 s-\thickln \alignGrob TextScript TimeSignature #'(1 . 0) #5.5 \time 3/4 s-\thickln \alignGrob TextScript TimeSignature #'(0 . 0) #5.5 \time 3/4 s-\thickln \alignGrob TextScript TimeSignature #'(-1 . 0) #5.5 \time 3/4 s-\thickln \alignGrob TextScript TimeSignature #'(1 . 1) #5.5 \time 3/4 s-\thickln \alignGrob TextScript TimeSignature #'(0 . 1) #5.5 \time 3/4 s-\thickln \alignGrob TextScript TimeSignature #(cons LEFT RIGHT) #5.5 \time 3/4 s-\thickln } } %} \new Staff { \override Staff.StaffSymbol.width = 50 \alignGrob Score.BarLine StaffSymbol #RIGHT #'(0.08 . 0) c''4 d e f s2. }