Hi, all --

Attached is a function which started out as an attempt to get tempo
indications to line up with the left edge of the time signature.  It's
been generalized so that you can left-align any grob responsive to
'extra-offset to the closest grob of a specified type in that system
(as far as I can tell so far -- you could even left-align a notehead
to a barline, if you were so inclined...)

It locates the closest grob by first searching all of the grobs in a
system for every instance of the target type, then selecting the one
that is closest horizontally.  (For example, if you want to align
something to a barline, the function would determine where all the
barlines are, then choose the nearest one).

I have several questions:

(1) Is there a way to locate the nearest grob more efficiently, so the
routine doesn't have to search the entire system?

(2) Is there a way to exclude grobs that are in the same system, but
on a different staff?  I've looked at the 'staff-symbol property, but
it's empty in some cases.

(3) Does anybody have any suggestions how to improve the coding?  I'm
enjoying learning Scheme, but my approach is rather hit-and-miss!

Best,
David
\version "2.12.3"

leftAlignGrob =
#(define-music-function (parser location grob-to-align reference-grob) (string? symbol?)
 #{
    \overrideProperty  $grob-to-align #'after-line-breaking #(lambda (grob)
      (let* ((sys (ly:grob-system grob))
	     (array (ly:grob-object sys 'all-elements))
	     (len (ly:grob-array-length array))
	     (current-grob-in-search (lambda (q)
	       (assq-ref (ly:grob-property (ly:grob-array-ref array q) 'meta) 'name)))
	     (default-coord (ly:grob-relative-coordinate grob sys X))
	     (lst '()))
  
       ;; find all instances in a system of the grob we want to use for alignment
       ;; returns list of X-coordinates, minus duplicates
	 (let lp ((x len))
	   (if (positive? x)
	       (begin
		 (if (eq? $reference-grob (current-grob-in-search (1- x)))
		     (set! lst
		       (uniq-list (append lst
			 (list (ly:grob-relative-coordinate (ly:grob-array-ref array (1- x)) sys X))))))
		 (lp (1- x)))))
  
      ;; find the value in the list closest to the X-coordinate of object to be aligned
	(let ((ref (car lst)))
	   (define closest (lambda (x)
	     (if (< (abs (- default-coord (car x))) (abs (- default-coord ref)))
		 (set! ref (car x)))
	     (if (not (null? (cdr x)))
		 (closest (cdr x)))))
  
      (closest lst)
      (ly:grob-set-property! grob 'extra-offset `(,(- ref default-coord) . 0)))))
  #}
)

\relative c' {

  %% bar 1
  \time 3/4
  \key d \major
  \leftAlignGrob #"Score.MetronomeMark" #'TimeSignature
  \tempo 4 = 120
  \once \override  TextScript #'padding = #2
  \leftAlignGrob #"TextScript" #'Clef
  d_"clef"
  \leftAlignGrob #"TextScript" #'KeySignature
  e_"key sig." fis

  %% bar 2
  e
  \once \override  Hairpin #'X-offset = #-1
  \leftAlignGrob #"TextScript" #'Hairpin
  d\<_"hairpin (offset)" e

  %% bar 3
  \leftAlignGrob #"TextScript" #'BarLine
  \time 2/4
  fis^"bar" d

  %% bar 4
  \time 4/4
  \leftAlignGrob #"TextScript" #'TimeSignature
  e^"meter" fis d
  \once \override  DynamicText #'X-offset = #0.5
  \leftAlignGrob #"TextScript" #'DynamicText
  fis\f_"dynamic (offset)"

  %% bar 5
  \leftAlignGrob #"TextScript" #'Stem
  \time 3/4
  e^"stem" fis d

  %% bar 6
  \leftAlignGrob #"Score.RehearsalMark" #'TimeSignature
  \mark #1
  \time 2/4
  fis d
}


<<attachment: image.png>>

_______________________________________________
lilypond-user mailing list
lilypond-user@gnu.org
http://lists.gnu.org/mailman/listinfo/lilypond-user

Reply via email to