%% DO NOT EDIT this file manually; it was automatically
%% generated from the LilyPond Wiki
%% (https://wiki.lilypond.community).
%%
%% Make any changes in the Wiki itself, or in
%% `Documentation/snippets/new/`, then run
%% `scripts/auxiliar/makelsr.pl`.
%%
%% This file is in the public domain.

\version "2.24.0"

\header {
  categories = "Scheme, Tweaks and overrides"

  texidoc = "
When working with grob callbacks, it can be helpful to understand a
grob's ancestry. Most grobs have parents which influence the
positioning of the grob. X- and Y-parents influence the horizontal and
vertical positions for the grob, respectively. Additionally, each
parent may have parents of its own.

Unfortunately, there are several aspects of a grob's ancestry that can
lead to confusion:

@itemize
@item
The types of parents a grob has may depend on context.
@item
For some grobs, the X- and Y-parents are the same.
@item
A particular @emph{ancestor} may be related to a grob in multiple ways.
@item
The concept of @emph{generations} is misleading.
@end itemize

For example, the @code{System} grob can be both parent (on the Y-side)
and grandparent (twice on the X-side) to a @code{VerticalAlignment}
grob.

The macro defined in this snippet prints (to the console) a textual
representation of a grob's ancestry. For example, the call

@example
@{
  \\once \\override NoteHead.before-line-breaking = #display-ancestry
  c
@}
@end example

generates the following output.

@example
------------------------------------
@end example

@example
NoteHead
X,Y: NoteColumn
     X: PaperColumn
        X,Y: System
     Y: VerticalAxisGroup
        X: NonMusicalPaperColumn
           X,Y: System
        Y: VerticalAlignment
           X: NonMusicalPaperColumn
              X,Y: System
           Y: System
@end example

As a consequence, you have to execute the code in this snippet by
yourself, since the generated output file doesn't show the data we are
interested in.
"

  doctitle = "Displaying grob ancestry"
} % begin verbatim


#(define (get-ancestry grob)
   (if (not (null? (ly:grob-parent grob X)))
       (list (grob::name grob)
             (get-ancestry (ly:grob-parent grob X))
             (get-ancestry (ly:grob-parent grob Y)))
       (grob::name grob)))

#(define (format-ancestry lst padding)
   (string-append
    (symbol->string (car lst)) "\n"
    (let ((X-ancestry (if (list? (cadr lst))
                          (format-ancestry (cadr lst) (+ padding 3))
                          (symbol->string (cadr lst))))
          (Y-ancestry (if (list? (caddr lst))
                          (format-ancestry (caddr lst) (+ padding 3))
                          (symbol->string (caddr lst)))))
      (if (equal? X-ancestry Y-ancestry)
          (string-append (format #f "~&")
                         (make-string padding #\space)
                         "X,Y: "
                         (if (list? (cadr lst))
                             (format-ancestry (cadr lst) (+ padding 5))
                             (symbol->string (cadr lst))))
          (string-append (format #f "~&")
                         (make-string padding #\space)
                         "X: " X-ancestry "\n"
                         (make-string padding #\space)
                         "Y: " Y-ancestry (format #f "~&"))))
    (format #f "~&")))

#(define (display-ancestry grob)
   (format (current-output-port)
           "~2&~a~2%~a~&"
           (make-string 36 #\-)
           (if (ly:grob? grob)
               (format-ancestry (get-ancestry grob) 0)
               (format #f "~a is not a grob" grob))))

\relative c' {
  \once \override NoteHead.before-line-breaking = #display-ancestry
  f4
  \once \override Accidental.before-line-breaking = #display-ancestry
  \once \override Arpeggio.before-line-breaking = #display-ancestry
  <f as c>4\arpeggio
}
