2017-06-16 23:47 GMT+02:00 Shevek <saul.james.to...@gmail.com>: > Following up on an aspect of the discussion on parts sharing a staff > (http://lilypond.1069038.n5.nabble.com/parts-sharing-a-staff-tt203873.html). > > I've spent quite a few hours over the last day trying to figure out how > engravers work and how I might take a crack at writing something to > automatically handle changing Staff names for divisi staves. I feel like > I've understood most of what I've read, but I'm still totally befuddled. > This seems like a difficult problem because: > > 1) It's completely opaque to me how one would check if a Staff is visible or > not on a given system. The hara-kiri-group-spanner, as far as I can tell, > does its work without telling anybody about it. There's not like a boolean > function you can call to find out if a context will be visible. > > 2) One needs to do something in one context depending on what happens in a > different context. Most of the example engravers just do something in one > context. Keep_alive_together_engraver collects grobs from different contexts > and tells them about each other, but then relies on on them to figure out > what to do with that information. That doesn't seem adequate here. > > 3) Such an engraver would need to step through the score by system, after > breaking, rather than event by event, and it might need to be able to > backtrack to insert an event to change the instrument name prior to the most > recent system break. The code and documentation I've read has not given me > any insight into how one might do such a thing. > > I'd love some feedback and guidance.
Hi, I doubt an engraver will ever work for this purpose. As far as I understand an engraver usually puts in stuff far too early. You can assign a procedure to a grob via 'after-line-breaking, but you will not be able to access whatever the procedure returns _in_ the engraver. I may be proven wrong, though. Nevertheless, I tried a different approach: \version "2.19.62" %% NB %% It's a proof of concept, nothing more!! %% Currently it will fail for various reasons with extended examples #(define change-instr-names (lambda (grob) (let* ((sys (ly:grob-system grob)) (sys-all-elts (ly:grob-object sys 'all-elements)) (sys-all-elts-list (if (ly:grob-array? sys-all-elts) (ly:grob-array->list sys-all-elts) '())) ;; get all VerticalAxisGroup-grobs per System (vertical-axis-group-list (filter (lambda (g) (grob::has-interface g 'hara-kiri-group-spanner-interface)) sys-all-elts-list)) ;; get all InstrumentName-grobs per System (instrument-names-list (filter (lambda (g) (grob::has-interface g 'system-start-text-interface)) sys-all-elts-list)) ;; construct a nested list like ;; ((#t #<Grob InstrumentName >) ;; (#f #<Grob InstrumentName >)) ;; the boolean indicates whether the Staff is alive, derived from ;; VerticalAxisGroup.Y-extent (alive?-instr-list (map (lambda (v i) (list (interval-sane? (ly:grob-property v 'Y-extent)) i)) vertical-axis-group-list instrument-names-list))) ;(pretty-print alive?-instr-list) ;; First constructing a list and then fragmenting it in various ways is ;; not elegant, to say the least. ;; Just a proof of concept... (if (any not (map car alive?-instr-list)) (let* ((instr-to-set (remove (lambda (e) (not (car e))) alive?-instr-list))) (ly:grob-set-property! (cadar instr-to-set) 'text (make-column-markup (map (lambda (arg) (ly:grob-property arg 'text)) (map cadr alive?-instr-list))))))))) %%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Example %%%%%%%%%%%%%%%%%%%%%%%%%%%% \layout { \context { \Staff \override VerticalAxisGroup.after-line-breaking = #change-instr-names \RemoveEmptyStaves } } << \new Staff \with { instrumentName = "One" shortInstrumentName = "one" } { R1 \break c \break c } \new Staff \with { instrumentName = "Two" shortInstrumentName = "two" } { c1 R c } >> Cheers, Harm _______________________________________________ lilypond-devel mailing list lilypond-devel@gnu.org https://lists.gnu.org/mailman/listinfo/lilypond-devel