2017-03-28 0:39 GMT+02:00 Dmitry <mi...@cargosoft.ru>: > Hi, > > There's been a long standing feature request: > > https://sourceforge.net/p/testlilyissues/issues/3909/ > > #3909 a feature to disable the chord root name printing - just print > the slash and inversion > > Over the years, it has been addressed more or less. Time to give it > another try? > > In a few words, we need a mechanism to suppress printing repeated root > chord name over a progression of slash chords. That means, we'd like to > see this: > > F#min9 /F /E /D# > > instead of this: > > F#min9 F#min9/F F#min9/E F#min9/D# > > The latter is much less readable, occupies more space and bloats the > score. > > To say this feature is demanded in jazz means say nothing! I've > recently started working on a bunch of jazz scores, and the very first > piece features three (!) different progressions with changing bass > notes, like the above. OK, there is a well-known hack that uses > \whiteout: http://lsr.di.unimi.it/LSR/Item?id=776 > > Unfortunately, for the real-life scores it is simply a no-go. It > requires a chord exception for each and every rootless slash chord, it > messes up MIDI output (as slash chords are not recognized in chord > exceptions), not to mention that it produces unclean output. > > There is another workaround from 2011: http://www.mail-archive.com/lily > pond-user%40gnu.org/msg67087.html > Needless to say, it doesn't work in 2017 :) but I've managed to fix it. > Here we go, > > #(define (rootless-chord-names in-pitches bass inversion context) > (ignatzek-chord-names `(,(ly:make-pitch 0 0 0) ,(ly:make-pitch 0 0 > 0)) bass inversion context)) > > #(define (empty-namer pitch lower?) (make-simple-markup "")) > > retainChordNoteNamer = > \applyContext > #(lambda (context) > (let ((rn (ly:context-property context 'chordRootNamer))) > (ly:context-set-property! context 'chordNoteNamer rn))) > > rootless = { > \retainChordNoteNamer > \once \set chordNameFunction = #rootless-chord-names > \once \set chordRootNamer = #empty-namer > } > > After that, one can use \rootless as follows: > > fis2:m7.9 \rootless fis4:m7.9/f \rootless fis4:m7.9/e \rootless > fis1:m7.9/dis > > This produces perfect output, but the code is ugly as hell. What I'm > doing here is basically the following: > - kill off chordRootNamer, but retain chordNoteNamer; > - after that, the root note note wouldn't be printed, but the suffix > (like m9, etc.) would be. To suppress it, we supply a > proxy chordNameFunction that would guarantee a suffix-less chord. > > It should be easy to convert this one-shot semantics to something like > \rootlessOn and \rootlessOff. In fact, it would be nice if mainstream > Lilypond had something similar to "\set chordChanges = ..." but for > slash chords; but of course nobody would like to see ugly hacks like > the above in the mainstream :) > > Off the top of my head, I could propose the following solution: > > - inside Scheme code for chord name functions ({ignatzek,banter,jazz}- > chord-names), allow for NIL "pitches" argument. That should mean > "produce output for bass note only, omitting everything before the > slash"; > - in Chord_name_engraver::process_music, track repeating root parts of > slash chords and pass NIL pitches to a chordNameFunction in case of > repetition. Everything should be similar to handling chordChanges, > however this time we should remember and compare whole chord > structures, not markup. > > What do you think? > > Cheers, > Dmitry
Hi Dmitry, below my approch. I'm afraid you'll not have problems to break it... Comments inline. \version "2.19.57" %% Tries to compare the relevant parts of the markups for current and previous %% chord. %% %% Probably it would be far easier to compare actual pitches in the %% chordNameFunction as delivered there, but 'lastChord' returns only a markup %% not pitches. #(define (test-engraver ctx) (let ((prev '())) (make-engraver (acknowledgers ((chord-name-interface engraver grob source-engraver) ;; As of the 'ignatzek-chord-names'-procedure: ;; 'current' will always be a list, as well as '(last current)' ;; So it seems safe to apply list-modifying procedures to them. ;; Ofcourse this may change, when 'ignatzek-chord-names' is changed ;; or a different chordNameFunction is used. (let* ((current (ly:grob-property grob 'text)) (current-string-lists (split-list-by-separator (filter (lambda (arg) (and (string? arg) (not (string-null? arg)))) (flatten-list current)) (lambda (x) (string=? x "/")))) (prev-string-lists (split-list-by-separator (filter (lambda (arg) (and (string? arg) (not (string-null? arg)))) (if (pair? prev) (flatten-list (car prev)) '())) (lambda (x) (string=? x "/")))) (current-bass (take-right (last current) 1))) ;; print 'current-bass' if the root of current and previous chord ;; are the same, the bass is different and present at all. ;; Otherwise do nothing. (if (and (pair? prev) (equal? (car current-string-lists) (car prev-string-lists)) (not (equal? (last current-string-lists) (last prev-string-lists))) (pair? (cdr current-string-lists))) (ly:grob-set-property! grob 'text (make-line-markup ;; reinject "/", which is not caught ;; by 'current-bass' (cons "/" current-bass)))) (set! prev (cons current prev))))) ((finalize translator) ;; clear 'prev' (set! prev '()))))) \layout { \context { \ChordNames \consists \test-engraver } } \new ChordNames \chordmode { c:m/e c:m/+g c:m/fes c/fes c/d c:7/d c:7/+g d e e:m f:m f:m f } \new ChordNames \chordmode { c c c:m7 c:m7/bes c:m7 c:m7.9/cis c:m7/cis } HTH a bit, Harm _______________________________________________ lilypond-user mailing list lilypond-user@gnu.org https://lists.gnu.org/mailman/listinfo/lilypond-user