%% 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.25.35"

\header {
  categories = "Chords, Contexts and engravers, Scheme, Staff notation"

  texidoc = "
To print subsequent chord names only differing in their bass note as
slash and bass note without a root symbol, use the Scheme engraver
defined in this snippet. The behaviour is controlled by the
@code{chordChanges} context property.
"

  doctitle = "Print chord names with same root and different bass as slash and bass note"
} % begin verbatim


#(define Bass_changes_equal_root_engraver
   (lambda (ctx)
     "Drop root for follow-up chord names that differ only in bass.

In other words, the chord name sequence 'D D/C D/B' gets actually
printed as 'D /C /B'.

Set the `chordChanges` context property to `#t` to activate this
feature."
     (let ((chord-pitches '())
           (last-chord-pitches '())
           (bass-pitch #f))
       (make-engraver
        ((initialize this-engraver)
         (let ((chord-note-namer (ly:context-property ctx
                                                      'chordNoteNamer)))
           ;; Set `chordNoteNamer`, respecting user setting if already
           ;; done.
           (ly:context-set-property! ctx 'chordNoteNamer
                                     (if (procedure? chord-note-namer)
                                         chord-note-namer
                                         (chord-name:markup #f)))))

        (listeners
         ((note-event this-engraver event)
          (let* ((pitch (ly:event-property event 'pitch))
                 (pitch-name (ly:pitch-notename pitch))
                 (pitch-alt (ly:pitch-alteration pitch))
                 (bass (ly:event-property event 'bass #f))
                 (inversion (ly:event-property event 'inversion #f)))
            ;; We look at the `bass` and `inversion` event properties
            ;; to decide how to handle the current note event.  If
            ;; `inversion` is set we add the bass note to the chord as
            ;; an ordinary member so that we can compare inversed
            ;; chords; if `bass` is set the bass note is not added to
            ;; the chord.
            ;;
            ;; In the `chord-pitches` list we actually collect only
            ;; the notes' pitch names (which are integers) and pitch
            ;; alterations as pairs, ignoring the octave.
            (cond (bass (set! bass-pitch pitch))
                  (inversion
                   (set! bass-pitch pitch)
                   (set! chord-pitches
                         (cons (cons pitch-name pitch-alt)
                               chord-pitches)))
                  (else
                   (set! chord-pitches
                         (cons (cons pitch-name pitch-alt)
                               chord-pitches)))))))

        (acknowledgers
         ((chord-name-interface this-engraver grob source-engraver)
          (let ((chord-changes (ly:context-property ctx
                                                    'chordChanges #f)))
            ;; If subsequent chords are equal apart from their bass,
            ;; we change the `text` property to print only the slash
            ;; and the bass note (via the formatter stored in the
            ;; `chordNoteNamer` context property).
            ;;
            ;; Equality is tested by comparing the sorted lists of
            ;; this chord's elements and the previous chord.  Sorting
            ;; is needed because inverted chords may have a different
            ;; order of pitches.  Note that we only do a simplified
            ;; sorting using the pitch name, ignoring the alteration.
            (if (and bass-pitch
                     chord-changes
                     (equal? (sort chord-pitches car<)
                             (sort last-chord-pitches car<)))
                (ly:grob-set-property!
                 grob 'text
                 (make-line-markup
                  (list
                   (ly:context-property ctx 'slashChordSeparator)
                   ((ly:context-property ctx 'chordNoteNamer)
                    bass-pitch
                    (ly:context-property ctx
                                         'chordNameLowercaseMinor))))))
            (set! last-chord-pitches chord-pitches)
            (set! chord-pitches '())
            (set! bass-pitch #f))))

        ((finalize this-engraver)
         (set! last-chord-pitches '()))))))


myChords = \chordmode {
  % \germanChords

  \set chordChanges = ##t
  d2:m d:m/cis

  d:m/c
  \set chordChanges = ##f
  d:m/b

  e1:7
  \set chordChanges = ##t
  e
  \break

  \once \set chordChanges = ##f
  e1/f
  e2/gis e/+gis e e:m/f d:m d:m/cis d:m/c
  \set chordChanges = ##f
  d:m/b
}

<<
  \new ChordNames
    \with { \consists #Bass_changes_equal_root_engraver }
    \myChords
  \new Staff \myChords
>>
